Digital Signature Verification failed using SHA256

2019-02-27 09:17发布

I am trying to validate the digital signature with given certificate files for the offline aadhaar KYC verification application.

This instruction is given in the documentation for the verification.

  1. Read the entire XML and separate the s=”xxxx” tag from it.

  2. Use a signature validation algorithm leveraging “SHA256withRSA” based hashing and encryption technique

  3. Signature value present in “s” tag, remaining XML (without "s" tag) and UIDAI public key (available here.) is to be fed to the algorithm to validate the digital signature.

Sample C# code snippets provided by the organization. (PS :which is also not working)

using System;
using System.Security.Cryptography.X509Certificates;
using System.Xml;

namespace test
{
class MainClass
{
    public static void Main(string[] args)
    {
        // link -> https://drive.google.com/file/d/1aSv3HJUFf5_42Z-FqpdVHEk5b3VA3T3D/view


        string XMLFilePath = "offlineaadhaar.xml"; //Get the XML file

// link -> https://drive.google.com/file/d/1FW4ciIhZqJuelOcGF2x6VaBCSDO9J-gM/view


string KeyFilePath = "okyc-publickey.cer"; //Get the public key certificate file

        XmlDocument ObjXmlDocument = new XmlDocument();
        ObjXmlDocument.Load(XMLFilePath); //Load the XML
        XmlAttributeCollection SignatureElement = ObjXmlDocument.DocumentElement.Attributes; //Get the all XML attribute
        string SignatureValue = SignatureElement.GetNamedItem("s").InnerXml; // Get Signature value

        SignatureElement.RemoveNamedItem("s");//Remove the signature "s" attribute from XML and get the new XML to validate

        /*----------------Read and parse the public key as string-----------------------*/
        X509Certificate2 ObjX509Certificate2 = new X509Certificate2(KeyFilePath, "public"); //Initialize the public ket certificate file

        Org.BouncyCastle.X509.X509Certificate objX509Certificate;
        Org.BouncyCastle.X509.X509CertificateParser objX509CertificateParser = new Org.BouncyCastle.X509.X509CertificateParser();

        objX509Certificate = objX509CertificateParser.ReadCertificate(ObjX509Certificate2.GetRawCertData());
        /*----------------End-----------------------*/

        /* Init alg */
        Org.BouncyCastle.Crypto.ISigner signer = Org.BouncyCastle.Security.SignerUtilities.GetSigner("SHA256withRSA");

        /* Populate key */
        signer.Init(false, objX509Certificate.GetPublicKey());

        /* Get the signature into bytes */
        var expectedSig = Convert.FromBase64String(SignatureValue);

        /* Get the bytes to be signed from the string */
        var msgBytes = System.Text.Encoding.UTF8.GetBytes(ObjXmlDocument.InnerXml);


        /* Calculate the signature and see if it matches */
        signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
        bool Flag = signer.VerifySignature(expectedSig);            
        if (Flag)
        {
            Console.WriteLine("XML Validate Successfully");
        }
        else
        {
            Console.WriteLine("XML Validation Failed");
        }
    }
}
}

I am trying to implement in Python and getting the XML validation failed. I am not sure if the certificate file is wrong or there is some bug on my code.

Here is my Python Code :

import xml
import xml.etree.cElementTree as etree
from xml.etree import ElementTree
import OpenSSL
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from Crypto.PublicKey import RSA
from base64 import b64encode, b64decode
from M2Crypto import BIO, RSA, EVP

xmlDoc = open('adhar.xml', 'r').read()
Tr = etree.XML(xmlDoc)
Tr.keys()
# ['s', 'r', 'a', 'g', 'm', 'e', 'd', 'i', 'n', 'v']

sign = Tr.get('s')
len(sign)
# 344

del Tr.attrib['s']

from M2Crypto import X509

x509 =X509.load_cert('ekyc_public_key.cer')
#x509 =X509.load_cert(cert4)
rsa = x509.get_pubkey().get_rsa()
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)

xmlstr = etree.tostring(Tr, encoding='utf8', method='xml')
#rstr=str(xmlstr)[45:][:-1]
#rstr = rstr.encode(encoding='utf-8')


# if you need a different digest than the default 'sha1':
pubkey.reset_context(md='sha256')
pubkey.verify_init()

# hashlib.sha256(message_without_sign).digest()
pubkey.verify_update(xmlstr)
if(pubkey.verify_final(b64decode(sign)) != 1):
    print('Digital Signeture not validated')
else: 
    print('Digital Signeture validated')  

3条回答
何必那么认真
2楼-- · 2019-02-27 09:33

In cryptography, the devil is in the details, like what really is meant by:

remaining XML (without "s" tag)

We are lucky: this ridiculously vague specification comes came with a sample XML file and matching certificate, allowing to:

  • extract the signature signature field (converted from Base64 to binary) from the former to get S;
  • extract N and e from the later;
  • compute V = S e mod N
  • check that V is indeed formatted per SHA256withRSA (also known as RSASSA-PKCS1-v1_5 with SHA-256 hash),
  • on the right of V after a fixed DER prefix 3031300d060960864801650304020105000420 characteristic of a Digestinfo with SHA-256 we extract the 32-byte value f4efef8c788058df45385ec65a49e92f806b9ffd6fc6d11b4f3c2cf89a81fe2f, which thus is the expected hash for that example's signed data.

So with a little trial and error we find what that signed data really is. We want to start from XML file and remove

  1. the s tag
  2. its = (and, should there be any, whitespace between former s tag and =, and after = as allowed by the XML syntax)
  3. its value field including leading and closing " (which contains the base64-encoded signature)
  4. precisely two nearby space characters, like the one before the s tag and the one after the closing " (alternatively, we might want to leave a single space where there are now several, probably three after the removals in bullet points 1-3).

then hash what remains including < /> delimiters (as UTF-8), that is in the sample code pass it to BlockUpdate or verify_update. For that example:

<OKV v="1"  n="Ravi Krishna Nalagatla"  i="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADIAKADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDyTI60Zq2bVgOgNMa2f+7+VOyXUggpN+KkaBh/AfyppjI6qaQbjdxpd5FJs5o2mi4rC76N/rTdrUm0+lFx2Hb+cZpd3Tmo8H0o3U7k2Jd5POaTzDzUBY9lNG7jJ4/Gi47FiNg7Y3KPdqR3VWxlT7g1AGB6Z/KkKg9aTY0TmZB6D8ahe4i4BOaQxjrik8tfSlcBVu4z608XCE53VGYgelKIgD0ouPqSiUHjIpQ4xUQAHQUuDSA2+3WjNBpPxqQA/SjGaTp9KWkAhA9KaY0P8Ip/8qM0AR+RH/dqP7KhPVh9DVjikzg0agV/sa4+8aT7IMcGrJpwXIzRcCkbRuxFNNq+Ku45pDwOaLsCgbdxj5T+dNML91atH0NJ+BouFjNMbehoEZPTmtMqKYwGaOYCh5Teho8l6uEU0jmjmAy7qU27BcAk1Zt08yJWOQSKZdWRuGDBgMDvVqGMRxqmc4GKd9C9LaF/rRVk6bqC/e06+H1tnH9Kje2uI/vwSr/vIRSvqRYhopC6j+NfzoDq3RgfoaSY7C0UCnpG0rhVGWp7iGDk8ClKFRlh/wDWqw+23jK7AZRg8VnSyO0x6A8jAYfp0FNILEzzReVhOTnkkEVBNciID93kMOgpisFbPIA68c1FcCAKrCV/mJ7dPzq0gFF5KoDeWWXrjOP0ojvjNMEKAEnjnrUUciANhpCp6jdyaz7gsG3D5QPWhoZ0728sSgygKW7ZFKttM4BSJ3B7qpNc/BfzOuGJkI7ntWpaXlzGVkDOMHkgnj2PPSo5QtYsONhw/wApHrUZIYnkH6Guo0XUbS9nMF1PMlyOE3Xku2TPoN2M+3866CSyV0CiVwPfD/8AoQNZt2eoHmpHHSm4Fd6dBgJy8nmd/nt4P6RimS6FCylUisx7/Z8f+gsKXMBwmM0AV2DeGogrFlt2A5wqSKfz8w0NoFnJZh4bfErKCFMzADOO5Dfyp8wGkdLsMgixtuOn7lf8Kl8mJPuIqY/ujFTlfX8qiZhnA5NeEqkrbm1iFkY/8t7hR/s3Dr/I1Wa1Vmybi9P+9eykf+hVaY9utRnn/GrVWovtBZFX7JCoJwTj/noxfHv82axp7iOOVvLSIIAcGOMKT9cACreu6gtpb+UrESy9COoFctHdsdxZRhj3Oa9LBqclzyZnK3QdO8905ZsBOgPrVYs/m4Q4HTA6U6aViSXYgn+E9f0qukoBI7mu5ElqaORQsjE/3enT8KdyY137TkdTxx9aIiXtGjBUkcrkdP8ACq8n7+IbXO9Ox4qkIrk+WWA9euelVJz1BOcmrYmUELNGMeoGDUMnkknaTnGOaBkdoCJPlA9K32Pk2yiTIJHbBx9RWbYRLw56juP/AK4p1/I6kcHHbjpR1AW6ulLRlCCVHHqK9L8KXq+ILHCX+y7hA82J4wxx2IOeR/nvXkxJfg9ueBiuh8D3z2Hia1lV2Cyt5LqTgENx/PH/AOuokk0J7aHrI0W6PC3kZOO8WP6mqF7aX9nsJ8h1ZtpwxyPwxXVJvADdGxWTq+4tbo/JMnHA575rnasEW3uY90PLglBOSEOe3amJ8qqvYDFPvuROPZhUQPNSUSMWPXIHoOtRP8vXv0A6mmXsxS0ndPlxGx3Yyelc7HaGW2R/tl0jOoJ2SY7fSvOw+GdZOz2NJSsdA2T149hQR6jiuae1kXpqF8P+25qq8dwo/wCQlfEf9fDV0f2e/wCYn2iI/FDkaqrcDYigDH1rEjn3cuE6/lUuqmQygySPI395zkn6ms3zCg7Zr0aUOSCiJu7Ls82QcLjn2qGMCVshgGFQkSNgKcjHpTl+UgsMN7VdxWLBnMUTxLkMfvZ/lVBJ2D5DHIq0+JQBncRwCBzTTaSAj5DmnzIFFhkygtgA98VG0RPbvWjaWLFcFGLHgYFacNgeQ0TdPSs5VEjVU2zGtEYbsqwwP0pt3t3AKxYnua1riAo2AmKzJ7dgaammS6bRSztOSefQdqntp3t5EmjIDowZfYjkVE6lTjj3oiR5pVjUFnc7VVRkkngAD3qyGj6YSOSa3ikjdWR1DBgeGBGQaw79JVvLJZWLkztjP+6eldjb2my1hUD5VjUYH0rm9UVX1S0A6Kzv+hH9a5ZIUJaNHN3f35P97+tQjr+FNnfO4+rf1qMOeakZDfSH+z7hXKvIIm3ELgHg9ueKyImZLeMDsoFXr64tb3Tby4sLhZIYwUY7GB5+orMWXEY9hiqw9J03JNCk7oV33D71V3GRUhYHt1qFsV0kGLrCkNG2MjmsV8ySYHc8CuyubG3u9McAyfad2VwRtA9DxkmsTSNMebWooZFIIOSPpU86NYwej7l7SdHlmABUkntXRR+C1mXLMFJ9RmpZrn+yBtt4y0hrMl13UYXd3mK+277tcr556p2On3Y6Wubtv4Gt48fv8H1210Vt4I0byd0jPM+c/OcAfQCuAh8ZXcbjdiVP7y810OmeLxcAKwZMjoaiUKkdWaRlF6WOntvD9vCpW3jiC9B3/Wq914et1JbcGeoH1tYIVkdiFPTvXP3/AI5hhZlUM38qztKWyLbjHcfqGhr5fyKM45xXL31m0WQy4NaX/CXTzuCq4X+7gmq8uri+zDcRgPn5GArVU6kdTJzjI42cMs7KRiul+HejtrPjXTbfB8qGT7TKc4wqfN/6FtH41lazB5V0hA+8K9W+Csem29tqEh8w6rJk7dpwbddv3fX5zz/wH8exTvG5yTT1SPV5XVV2hsMcEAdTXKa3CsOvQhRx9lkc9+cqK6ISbzJLHbk4PDHoxHAA9K5zXC/9vFpAAUtJAQDkclKwlqRyuOhxUuSOnU1HjG7ippAMrjHWmYGDxUMo86i16e1sp7XyB5czbm4Oc8f4CnDxEoHzQN+BqSe2maUF4VRV6ndVWWSMjA289+f8K7Oa+rJsWR4htT1WQH6CnDWrRujn8qxJIx14Y1CITjG0e2TQB2djfQyqY42UsDu69RVvSIhLrskzDaFiwv51w9o0lpcqwPT0r0LRHH2oyBSFeBWBJ77mzXPVhZ3R005pw5exr6lo0s8YlgUvhcHHOK54aQghurWUBGkUYk25ZcHP4g/h3rvdOvlQjcMjuK0J9L0/VBnb8x6HGMflXIpuLOnl5keSQ6TDYxTtPGZZZFCptIAXnr161Z0jT5J7uNBGSoPzEdAK9Cn8I2kOWkcyAdB0FEFvDEmyNFRV5+Ue9XOs2EaKRQ8RaCYtDEsQ3P5e5QDndg8152lgt0JVOVkKfuyemffHSvatTlzolojAHh8H1+auWHh62vGMkGEkzyOxNTCpyscqdzg7HQZ1WSW9VooxF8gLkvv9gCRjg9fX8RasdPku9qvHucHIbFd3D4RckGaUqnoDnNWrm3tNPgKQqARxkjmqnWbIVLlPNdXsV/tG0jkxtw2ffGP8a7b4eWko1uS4SNDHFAykF9uQ3GOh9/8Avk1zOqpHLqMbufljRnOB0GQf6V634V0Q6Po8aSKRdTAST5PQ9l/DOPrk1or6GVSSjF92bC6s6P5A0W/EajHmboNv5eZu/SuY1i5E+t35UMNlmhwwwecjkf8AAa6plNcVqJI1vWWPT7JAv/j81U5X0OJLW5z8g5X68VH2PTr3p75yKiY7UY+lTY0OHbU7a9haK4/d57pVf7LphH/H7IPqf/rVkLk8CnlD14rs5exJqLYacxx/aAA/2mAqdNFs5D+6v1b6EGsQL7UFcH3ot5jL+q6YNPeLEhcPnmuwtZY49G0qWKVCrQlGQdUIPII9zk5rgRu245x9a6PTPEsZ8PQ6DPbHdDdGeK438DIIKlce/r+HepqRuioOz0Oxs7g5BJxmumspwgyMhsdQOa4qzlKkKScVsrqKQpulcBQO5rzpx10PQi7I6G+u5HtnILMwU5qC2tzHCrbtxIz161hy+J7M2k0athmjYA/XiuPh8S3Npchmmm8teoLZX8v8KcaUmN1Yo9Zvir6XaqBlomkz7Btp/wAf1rMsi1veHH3G5+lcNqXj5jA0NrG5kP8AEQAo/Xn9K0PD3iNXs3lvHJkJwDgcAf8A66UqUrXH7SF7JneXF8DGcjJxxXL6neHkZBznpUz6hFPDvRwykZFc/f3PJ560oRbYpS0HaTEt1q/2mUEpAy8D+LnJB/SvQG8WT9oUHPPFcLpa31vYoY7a3ZZcybnnZSc9MjYe2K0A10cAiJD+Lf4V0nnzfMzpH8V3faOPH0rKuNRaZ7l2jXfOAHbPYZI/mfzrKdb4/duLcD0MDH/2emeXdn79xF/wGEj+bGgmxK33hUTDIIIyD1BpY0kVjvlZ+O4Ax+QqEwuXLC6mAPO3CYH6ZoA8xjBzU+zPateLw+8PF1PDCT/CDvYH6Dj9a0NN0oX6M2l2moamEO12tLdpVB99oOPzrtEcwIzViy0y81O9SzsLaa6uX+7FAhdj74HQepPAr2Tw38H5L9Y7vXomsYSMpaxENM/OfnblUHsMk56qRivVNI0TS/Dth9i0rT4bSIn5lhXlj6sx5Y+5yaBpHgmjfBPxVqDKb1LXTIifm+0Sh5APUImQfoWWtvVfAuh+ENDuQtiL6+ZTH9qujlunzOifdjAP3TyRn7xIwfbXkVEO1NzYwTXI+PNGC+D7mSMHziFMz7uTyBk/kB+XpUzvYq1tTxLTpt6bDnenXPenau0jWwKZC5+bHespbvy5i6D7rFTjuAauzXSXECgMee3YVhKGvMjojK6szM2iNA7I7AnsKsBUeI77VvLI6shI/PtVmHeMII9wHFJJqotMqYZNp6hBmle+g4pFEWoKkxWLtGD95Y2K/wDfWMVFu+coIHjI6bhnB9v8+taCasLshFSZR6MAM1O7JsIK0N2G4p7EWjXUhR43JwoyKfdzKZFTaHDHLqDj5e/NVkuI7ZHxjnrUelzNeakYEDyXL5AhGMuAM4U/3uDx3pqF5XIlLljY9C8mU2SXZiYQNj5scKSeh9OePrgVGRgZ5rvvA7Q674ViuoDHNgeXJGR8rjABDZ79fw4NTt8KfCMxd/7KktJm/itruVAPoobaPyqvZXMHbdHm5B96YevSu01H4P2627Pp3ibVbZw2f9KZZowPTaAh/WuD1bw14u0eXCo+oQZ4kskExx7ptDj3OCo9aXsZdBa72Hn75PtTCa56PxK5lZX+zyMOCithgeevJxVyLW4JABJG8Zxz/EB+I/wqXTaFc9j03wH4X8OhZHsGvLjOftF4nnMDnghQNqn3VQf51teIvP8A7Ale1uHikRTKwSQxv5aj5sHqMcdMenekkuhE8SSSKzxSbeeCykZBx361oTWS3Sxyu4ikVWAKgHKnG5TkdDgenQc12NaG8ocqTPNvDnjLXIYHWBZdStLZmlu57ly52EfKqMPuAAZ3Pu3Hd0GMej6ZqttqloLrT2MiE4eM8NG2MlXHY8g+hGCMgg1Z023gtbILF5YVmJYoAoJzXP8Airwvby6NdXOkJLZarDEz272UrQM5GG8s7SAQ2Mc+uazs0yZuLlojooAqyYcgvjOB/D9amuIIbu2kgnRZIZVKOp6MDwRXB/Da31WXSdQv7+7upftE/lQLcSFsLHkMcH7p3lgc8/IK7O1luJ1iZrfy7d4w/wAxIkRuPlZfX8e1O6JmrM+U/EWhzeFfFOoaNMzssMuYnbrJGeUbPqRwfcH0qmGdRuQ4HXivqTxB4R0zxDAPt9olxIqlRvPIB9D1B9CPf1rxTxX8NrzQmabSpJb21A3GFh++jH0H3h9Bn2PWk4t6o1px5locva6sgAVyEfjr0NWLrVIXjOUiY46kA1gsVkHQNURjTpkisrJvUeqNyDUIeCAinucVXvtTRsrEQcjkAdDWSIU/vU4KF6MB9BStG+ga2sOQM7Auxx6Vatbe4F7FdWj+VdROskMg/hdTlT+YFNtbd5XG1T9TXUadpjLgsvPXpUVKnKNQueleDtWW2uotRsoBBZ+I0a5MGPkt7yM7Z07deSPXDdgBXpNtcknbKeT0JryHw7Yu3hvWoow27TbqDWICB0bDLIo9dyRuPrJXp8T+bEOOcc5H610QkpK5nyKzRJe2syysys7xHnGSdp+npWS00LNtyxx26fqa6K3uCX8mQ5OPkb+8P8afPZ29yCJolb36EfjWqlbRlwrcmkkc6bQah+6kMEidAsnzD6cisu9+GmjXvJ0m1jJOT5KiEk+pKbSa6CbSjbOXgnUIf4XH+HWk07xBbO0qPOrRRyNH5h4wVO1uvYEEfhQ3fY1lJy1p6/I5KS5muZJBJMWARGRjgMAdxHTv0rTaeSe1X7TKzRgYwW4OKyTmGaZJFwVCrgjqMtx/n1pzzPIQWbOex/oK3uj1/ZqUVY6/R5fPsE4wu5sDp3rSaJSjhh8uDnP0rM8NoP7HiPfL/wDoRrcC/LjA5rCT1PBxGlWVu55prXinW9P15Uh2woqBQJIspP3LdRnrjgj3rXsfiHbHYNXszZqzhTOj+ZEmeAWJAKjpzggZ5OASOmvNGs7+BobmFJYy24Kw+6fUEcg8nkVzOq+Cka0nWydg7KcRyHg/Q/4/nUFxlSnZSVjtQQRkHIqvdWMF4p82JS2MBiOfz615HoPjjUvDCrp13avdWEXCxH5ZoVx0Unhl9AcdeGwAB6ro+tafrtgLzTrlZoc7WxwyN/dYHkHkcH1HrRqmKth6lB3e3c818d/ChdSWTU9DUJqOS8luSAlz9D/C/oT17nuPEmgdHeORGjkjYo6OuGVgcEEHoQe1fYUkiqvzAkE4AHJJrgfHfgew1cS6zawf8TCJf9IRFyZ1AHYdXUdD1IGOcLiJ7EQm2/ePnoQZIwK09P0R7lwzKQufTrXW2+iWI2ugyDyDjtWhDFDEWWNQMCuSVXTQ6VDuUbPSIYUXCAVox22DgAVMp56CplxzziuaTuapI2/CjfZNZZmkIimtZIjHjIZ8qVJ+gDD/AIFXa2I3IFHMiDDD1/z6/wCRxGhb4pmuNgYcoo7+px+n0/GtmHxXpNpfR2v22L7fI5UQAhmz1w2MhRwepHSvTw0bUrszqUtOZdTT0y7utWV86de6dLEqSxtcxgBsk8dfbkcEZ9wabqHivSLK6eG81O2iuYsK1oH3zKeoxGuWJOR0ByCKp+IfEWv6ckksFjYxWSLGTcvO0juzEgoibRgg4OScYPQ8gQanp1xI5vIHJh8lWdtx3Meckjvxj/IrSOrszOjSU377silqmv6jqyvb2CT6dat8r3MmBcOv/TNP+WeR3bB5+6DyKQhiSKKCKLy4ohhUHTgY5PU/1qSVPssXEffrjrVJ7qXeP1xWiVj2KNGFLSJeupo57qSWORX8xvMYjjknP/1ufSmKRyc1naLeJBeAyKr/ADrGXAzg5I/mtd1C0TDfu4xxWqHUq+xXKlsXvDKAaNCVPBLnI/32raqCzZXtIyhyMYzU9c8tz56rLmm35gBikZQwwaWipMzjta8Hx6hPIHEbQuxZSSVZCewIrmL3wdq/haVdY8NahK80YHnwOmfNUdiBw45Py9eSVOcCvULyTyoN+MgEA1Va6hkjwFJ49MVoryWp2wxNVxSeqOd8OePbLWEjh1ONbK7OAG3fupD0+Vj909OG7nAJrrVgVFxGAOS34nk1xuqeFLK8ne4iHkvIDv2jKyZ67l7n3/PNQWU2teGsC33ajp6/ftGOJIx/0yJPTGflPHAA2jJpODWqHUoRmual9xS8YeGhpl1/aNsMWUzfvFH/ACxcn9FJ6eh4zyAOYSPD5JI98Zr2e0vLHXNN8yIrNbTJh0YdiOQw+hryrxLpU3h/Vkt33PbS5a2lPO5e6n/aXjJPUEH1A4qtL7SIpVPsyKfOcdfenZIHv2WkjlRlDsdv0qvqkmNPuFhAMmxsL17VzNHQmdjZ+Ebu/uLb+17mWDS4MpHaW5INw3OXlYfw9SF6cjJySK67TvD+kafpb6dZ2EcVoxIZNp+cjuSeT04J9BjjFcB8Ktf1XV9OvYtYna4WNhJayvjcVJIZeOMAjj647Cu9kvzbSRIrDazBMfXPP4dfwr0ltoctZzctzFvBdaPcWkM0IuLNGkEbFiduBkFlCkkhcjgjucNxjTsfFWmzWUUk5a1lYlTA6EsCCR0A5BxkH0K9MgVrSQ22oWzQ3EEc0G4fJKgYEjBBwfQ/yrO1TQNOvLSONI47aZZFeCWNMFXBJyMYzxu/AmquZ86l8Rxmp+Ibc38z28oktovlktnA3lS3DKO4Izj6AHBJpHGn3wMlsyNjqIz8y9uR2/GtHxJptlK1vb2dparMm4yMsA5LAZ6dMkAk+qjvyOZ1PRNWS4xZGxkgCIrJNI8buFAwAQCowQOSDwB05NWtUenQqe4mjOthG2szhH4JiY4PHDNkf+O/rXR3OupaLhCGY0UVT3O2t8Rd0HxG1zcHT5pADMd0Sg4JOOR16d/wNdpaQzeVsYujRH5GOcMPofyooqJKx42NgozTXUvLu4LHBxyB0zTqKKg4yK5hFxbvEf4h+vasdbN4GYPIo/CiiqjJo0pza0Rn3Ou2FtcC1a4jeRcb1QjIJxgdevI/MetW2jEuHUAnHPoRRRW0T0JQUIRkt2WY9N3JHd2bfZ7peGI+7IAejev1681DrVjB4i0qXTLxfs1396B2GdkgBAdT34JBAIOCRRRXPJK7POl8TPIWt7pJ3s7uLyrqAmKZDztOQeOmQQFIPcEHvShZghSFBuclVOME57e56UUVxzS5rHTTd1qdpolnb+G9MtrfrcLbRxTFWOGYFmY+2WdjWzYTpPefbLqRUjT5UznliM4H5fpRRXY97FVFeSiad54gs7S3ch3Pl8nYvU9QOcVzzeNBJMDHaBxt2KGn2lB3/hOSR/nmiitVBHoYfAUHC8lcqzeIZLogrZfZ9qBQquX7sSckCqZvmBZ5YpS57kYAoop2O6OHpxXKkf/Z"  d="10121993" e="ac342bb947d5aa49847a0a05f87c388759a6cb156e04eac6ae995e9dca5ba1d9" m="254618fd06a2e7308247c7f0fb547f58174ab3b99e7b042d6705a5457235f32a"  g="male"  a="S/O Narasimham, 45, 74, 4, 7, Secunderabad, Hyderabad, Andhra Pradesh - 500003" r="328020181115111938451" />

Update: sample XML, certificate, and the above are in this zip archive.

查看更多
Summer. ? 凉城
3楼-- · 2019-02-27 09:44

I was trying to achieve the same in Java, Can anyone kindly suggest some change what I am doing wrong: I am using okyc-publickey.cer

I am unable to validate the signature.

DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance()
                                            DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
                                            Document ObjXmlDocument = docBuilder.parse(XMLFilePath);

                                            NodeList nl = ObjXmlDocument.getElementsByTagName("OKV");
                                            NamedNodeMap nodeMap = nl.item(0).getAttributes();
                                            String signatureValue = nodeMap.getNamedItem("s").getNodeValue();
                                            nodeMap.removeNamedItem("s");

                                            CertificateFactory fact = CertificateFactory.getInstance("X.509","BC");
                                            FileInputStream in = new FileInputStream(keyFilePath);
                                            X509Certificate cert = (X509Certificate) fact.generateCertificate(in);

                                            Signature signature = Signature.getInstance("SHA256withRSA","BC");

                                            signature.initVerify(cert);
                                            /* Get the signature into bytes */
                              byte[] expectedSig = org.apache.commons.codec.binary.Base64.decodeBase64(signatureValue);
                            byte[] msgBytes = nodeMap.toString().getBytes("UTF-8");
                              signature.update(msgBytes);

                              boolean isValid=signature.verify(expectedSig);
查看更多
女痞
4楼-- · 2019-02-27 09:49

For this project, all the instructions can be found on this page in Steps to validate signature step.

Sample data, sample public key and sample c# code can be found on this page in Offline ekyc Sample data tab.

For your own data please refer to this link and download the zip file and extract it.

Here is the ekyc public key for the other xml validation ekyc_public_key.cer

Please find the complete answer in below code snippet which is implemented in python :

from M2Crypto import BIO, RSA, EVP
from M2Crypto import X509

# 'ekyc_public_key.cer' for own your own data. as 'okyc_public_key.cer' only work for sample data only

x509 =X509.load_cert('okyc_public_key.cer')
rsa = x509.get_pubkey().get_rsa()
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)


import lxml.etree as le

with open(xml_path,'r') as f:
    doc=le.parse(f)
    for elem in doc.xpath('//*[attribute::s]'):
        sign = elem.attrib['s']
        elem.attrib.pop('s')    
data_str = str(le.tostring(doc))[2:][:-1]

data = data_str[:-2] +  ' />'

pubkey.reset_context(md='sha256')
pubkey.verify_init()

pubkey.verify_update((data_str[:-2] +  ' />').encode())

is_valid_signeture = ""
if(pubkey.verify_final(b64decode(sign)) != 1):
    print('Digital Signeture not validated')
    is_valid_signeture = 'Invalid'
else: 
    print('Digital Signeture validated') 
    is_valid_signeture = 'Valid'
查看更多
登录 后发表回答