Sample code for 30+ languages & platforms
PureBasic

Aadhaar Paperless Offline e-kyc

See more XML Digital Signatures Examples

Opens an encrypted .zip containing Aadhaar Paperless Offline e-KYC XML. Gets the XML and validates the digital signature. Then computes the hash for the mobile number and Email ID.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkPublicKey.pb"
IncludeFile "CkBinData.pb"
IncludeFile "CkXmlDSig.pb"
IncludeFile "CkZipEntry.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkCrypt2.pb"
IncludeFile "CkZip.pb"
IncludeFile "CkCert.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This example requires the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    ; Open the .zip containing the Aadhaar Paperless Offline e-KYC XML.
    ; The .zip is encrypted using the "Share Phrase".
    zip.i = CkZip::ckCreate()
    If zip.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkZip::ckOpenZip(zip,"qa_data/xml_dsig/offline_paperless_kyc.zip")
    If success = 0
        Debug CkZip::ckLastErrorText(zip)
        CkZip::ckDispose(zip)
        ProcedureReturn
    EndIf

    ; The .zip should contain 1 XML file.
    entry.i = CkZipEntry::ckCreate()
    If entry.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkZip::ckEntryAt(zip,0,entry)
    If success = 0
        Debug CkZip::ckLastErrorText(zip)
        CkZip::ckDispose(zip)
        CkZipEntry::ckDispose(entry)
        ProcedureReturn
    EndIf

    ; To get the contents, we need to specify the Share Phrase.
    sharePhrase.s = "Lock@487"
    CkZip::setCkDecryptPassword(zip, sharePhrase)

    bdXml.i = CkBinData::ckCreate()
    If bdXml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; The XML file will be unzipped into the bdXml object.
    success = CkZipEntry::ckUnzipToBd(entry,bdXml)
    If success = 0
        Debug CkZipEntry::ckLastErrorText(entry)
        CkZip::ckDispose(zip)
        CkZipEntry::ckDispose(entry)
        CkBinData::ckDispose(bdXml)
        ProcedureReturn
    EndIf

    ; First verify the XML digital signature.
    dsig.i = CkXmlDSig::ckCreate()
    If dsig.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkXmlDSig::ckLoadSignatureBd(dsig,bdXml)
    If success = 0
        Debug CkXmlDSig::ckLastErrorText(dsig)
        CkZip::ckDispose(zip)
        CkZipEntry::ckDispose(entry)
        CkBinData::ckDispose(bdXml)
        CkXmlDSig::ckDispose(dsig)
        ProcedureReturn
    EndIf

    ; The UIDAI XML signature does not contain the KeyInfo, so we must load the uidai certificate
    ; and indicate that its public key is to be used for verifying the signature.
    cert.i = CkCert::ckCreate()
    If cert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkCert::ckLoadFromFile(cert,"qa_data/xml_dsig/uidai_auth_sign_prod_2023.cer")
    If success = 0
        Debug CkCert::ckLastErrorText(cert)
        CkZip::ckDispose(zip)
        CkZipEntry::ckDispose(entry)
        CkBinData::ckDispose(bdXml)
        CkXmlDSig::ckDispose(dsig)
        CkCert::ckDispose(cert)
        ProcedureReturn
    EndIf

    ; Get the certificate's public key.
    pubKey.i = CkPublicKey::ckCreate()
    If pubKey.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkCert::ckGetPublicKey(cert,pubKey)

    CkXmlDSig::ckSetPublicKey(dsig,pubKey)

    ; The XML in this example contains only 1 signature.
    bVerifyReferenceDigests.i = 1
    bVerified.i = CkXmlDSig::ckVerifySignature(dsig,bVerifyReferenceDigests)
    If bVerified = 0
        Debug CkXmlDSig::ckLastErrorText(dsig)
        Debug "The signature was not valid."
        CkZip::ckDispose(zip)
        CkZipEntry::ckDispose(entry)
        CkBinData::ckDispose(bdXml)
        CkXmlDSig::ckDispose(dsig)
        CkCert::ckDispose(cert)
        CkPublicKey::ckDispose(pubKey)
        ProcedureReturn
    EndIf

    Debug "The XML digital signature is valid."

    ; Let's compute the hash for the Mobile Number.

    ; 	Hashing logic for Mobile Number :
    ; 	Sha256(Sha256(Mobile+SharePhrase))*number of times last digit of Aadhaar number
    ; 	(Ref ID field contains last 4 digits).
    ; 
    ; 	Example :
    ; 	Mobile: 1234567890
    ; 	Aadhaar Number:XXXX XXXX 3632
    ; 	Passcode : Lock@487
    ; 	Hash: Sha256(Sha256(1234567890Lock@487))*2
    ; 	In case of Aadhaar number ends with Zero we will hashed one time.

    crypt.i = CkCrypt2::ckCreate()
    If crypt.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkCrypt2::setCkHashAlgorithm(crypt, "sha256")
    CkCrypt2::setCkEncodingMode(crypt, "hexlower")

    strToHash.s = "1234567890Lock@487"
    bdHash.i = CkBinData::ckCreate()
    If bdHash.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkBinData::ckAppendString(bdHash,strToHash,"utf-8")

    ; Hash a number of times equal to the last digit of your Aadhaar number.
    ; If the Aadhaar number ends with 0, then hash one time.
    ; For this example, we'll just set the number of times to hash
    ; for the case where an Aadhaar number ends in "9"
    numTimesToHash.i = 9
    i.i
    For i = 1 To numTimesToHash
        tmpStr.s = CkCrypt2::ckHashBdENC(crypt,bdHash)
        CkBinData::ckClear(bdHash)
        CkBinData::ckAppendString(bdHash,tmpStr,"utf-8")
    Next

    Debug "Computed Mobile hash = " + CkBinData::ckGetString(bdHash,"utf-8")

    ; Let's get the mobile hash stored in the XML and compare it with our computed hash.
    xml.i = CkXml::ckCreate()
    If xml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkXml::ckLoadBd(xml,bdXml,1)
    m_hash.s = CkXml::ckChilkatPath(xml,"UidData|Poi|(m)")

    Debug "Stored Mobile hash   = " + m_hash

    ; Now do the same thing for the email hash:

    strToHash = "abc@gm.comLock@487"
    CkBinData::ckClear(bdHash)
    success = CkBinData::ckAppendString(bdHash,strToHash,"utf-8")

    For i = 1 To numTimesToHash
        tmpStr.s = CkCrypt2::ckHashBdENC(crypt,bdHash)
        CkBinData::ckClear(bdHash)
        CkBinData::ckAppendString(bdHash,tmpStr,"utf-8")
    Next

    Debug "Computed Email hash = " + CkBinData::ckGetString(bdHash,"utf-8")

    e_hash.s = CkXml::ckChilkatPath(xml,"UidData|Poi|(e)")
    Debug "Stored Email hash   = " + e_hash


    CkZip::ckDispose(zip)
    CkZipEntry::ckDispose(entry)
    CkBinData::ckDispose(bdXml)
    CkXmlDSig::ckDispose(dsig)
    CkCert::ckDispose(cert)
    CkPublicKey::ckDispose(pubKey)
    CkCrypt2::ckDispose(crypt)
    CkBinData::ckDispose(bdHash)
    CkXml::ckDispose(xml)


    ProcedureReturn
EndProcedure