Sample code for 30+ languages & platforms
PureBasic

Sign Mexico Pedimento

See more Misc Examples

Add a signature to a Mexico pedimento file.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkPrivateKey.pb"
IncludeFile "CkBinData.pb"
IncludeFile "CkAsn.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkRsa.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.

    ; This is the contents before signing:

    ; 500|1|3621|4199800|400||
    ; 601|3621|4199800|400|IN|1||EKU9003173C9|EKU9003173C9FRNN09|1||
    ; 507|4199800|IM|2006-7888">
    ; 507|4199800|MS|2">
    ; 800|4199800|1">
    ; 801|M3621037.222|1|5|011|

    ; This is the contents after signing

    ; 500|1|3621|4199800|400||
    ; 601|3621|4199800|400|IN|1||EKU9003173C9|EKU9003173C9FRNN09|1||
    ; 507|4199800|IM|2006-7888">
    ; 507|4199800|MS|2">
    ; 800|4199800|1|fhP2Ker54D2+3+UZch23F0E72 .... 9qNSPIuAqpj524qLZbbA==|30001000000500003416|
    ; 801|M3621037.222|1|5|011|

    ; First create the text to be signed.
    bCRLF.i = 1
    sb.i = CkStringBuilder::ckCreate()
    If sb.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; Use CRLF line endings.
    CkStringBuilder::ckAppendLine(sb,"500|1|3621|4199800|400||",bCRLF)
    CkStringBuilder::ckAppendLine(sb,"601|3621|4199800|400|IN|1||EKU9003173C9|EKU9003173C9FRNN09|1||",bCRLF)
    CkStringBuilder::ckAppendLine(sb,"507|4199800|IM|2006-7888">",bCRLF)
    CkStringBuilder::ckAppendLine(sb,"507|4199800|MS|2">",bCRLF)

    ; Generate the MD5 hash of what we have so far..
    md5_base64.s = CkStringBuilder::ckGetHash(sb,"md5","base64","utf-8")
    Debug "MD5 hash = " + md5_base64

    ; Complete the original file.
    ; After signing, we'll update the BASE64_SIGNATURE and CERT_SERIAL
    CkStringBuilder::ckAppendLine(sb,"800|4199800|1|BASE64_SIGNATURE|CERT_SERIAL|",bCRLF)
    CkStringBuilder::ckAppendLine(sb,"801|M3621037.222|1|5|011|",bCRLF)

    ; We're going to sign the MD5 hash using the private key.
    privKey.i = CkPrivateKey::ckCreate()
    If privKey.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkPrivateKey::ckLoadAnyFormatFile(privKey,"qa_data/certs/mexico_test/Certificados_de_Prueba/Certificados_Pruebas/Personas Morales/EKU9003173C9_20230517223532/CSD_EKU9003173C9_20230517223903/CSD_Sucursal_1_EKU9003173C9_20230517_223850.key","12345678a")
    If success = 0
        Debug CkPrivateKey::ckLastErrorText(privKey)
        CkStringBuilder::ckDispose(sb)
        CkPrivateKey::ckDispose(privKey)
        ProcedureReturn
    EndIf

    ; Generate the ASN.1 to be signed.

    ; <sequence>
    ;     <sequence>
    ;         <oid>1.2.840.113549.2.5</oid>
    ;         <null/>
    ;     </sequence>
    ;     <octets>SwxHfaJhG+N3pPqay6UzVA==</octets>
    ; </sequence>

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

    CkXml::setCkTag(xml, "sequence")
    CkXml::ckUpdateChildContent(xml,"sequence|oid","1.2.840.113549.2.5")
    CkXml::ckUpdateChildContent(xml,"sequence|null","")
    CkXml::ckUpdateChildContent(xml,"octets",md5_base64)

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

    CkAsn::ckLoadAsnXml(asn,CkXml::ckGetXml(xml))
    Debug "ASN.1 = " + CkAsn::ckGetEncodedDer(asn,"base64")

    ; Sign with the private key.
    rsa.i = CkRsa::ckCreate()
    If rsa.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkRsa::ckUsePrivateKey(rsa,privKey)
    If success = 0
        Debug CkRsa::ckLastErrorText(rsa)
        CkStringBuilder::ckDispose(sb)
        CkPrivateKey::ckDispose(privKey)
        CkXml::ckDispose(xml)
        CkAsn::ckDispose(asn)
        CkRsa::ckDispose(rsa)
        ProcedureReturn
    EndIf

    ; Create the opaque signature.
    bdSig.i = CkBinData::ckCreate()
    If bdSig.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkBinData::ckAppendEncoded(bdSig,CkAsn::ckGetEncodedDer(asn,"base64"),"base64")
    success = CkRsa::ckSignRawBd(rsa,bdSig)
    If success = 0
        Debug CkRsa::ckLastErrorText(rsa)
        CkStringBuilder::ckDispose(sb)
        CkPrivateKey::ckDispose(privKey)
        CkXml::ckDispose(xml)
        CkAsn::ckDispose(asn)
        CkRsa::ckDispose(rsa)
        CkBinData::ckDispose(bdSig)
        ProcedureReturn
    EndIf

    ; bd now contains the opaque signature, which embeds the ASN.1, which contains the MD5 hash.
    ; We're going to add this line:
    ; 800|4199800|1|BASE64_SIGNATURE|CERT_SERIAL_NUM|

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

    success = CkCert::ckLoadFromFile(cert,"qa_data/certs/mexico_test/Certificados_de_Prueba/Certificados_Pruebas/Personas Morales/EKU9003173C9_20230517223532/CSD_EKU9003173C9_20230517223903/CSD_Sucursal_1_EKU9003173C9_20230517_223850.cer")
    If success = 0
        Debug CkCert::ckLastErrorText(cert)
        CkStringBuilder::ckDispose(sb)
        CkPrivateKey::ckDispose(privKey)
        CkXml::ckDispose(xml)
        CkAsn::ckDispose(asn)
        CkRsa::ckDispose(rsa)
        CkBinData::ckDispose(bdSig)
        CkCert::ckDispose(cert)
        ProcedureReturn
    EndIf

    serialHex.s = CkCert::ckSerialNumber(cert)
    ; The serial in hex form looks like this:   3330303031303030303030353030303033343136
    ; Decode to us-ascii.
    sbSerial.i = CkStringBuilder::ckCreate()
    If sbSerial.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkStringBuilder::ckDecodeAndAppend(sbSerial,serialHex,"hex","us-ascii")
    Debug "serial number in us-ascii: " + CkStringBuilder::ckGetAsString(sbSerial)

    numReplaced.i = CkStringBuilder::ckReplace(sb,"CERT_SERIAL",CkStringBuilder::ckGetAsString(sbSerial))
    numReplaced = CkStringBuilder::ckReplace(sb,"BASE64_SIGNATURE",CkBinData::ckGetEncoded(bdSig,"base64"))

    Debug "------------------------------------"
    Debug "Result:"
    Debug CkStringBuilder::ckGetAsString(sb)


    CkStringBuilder::ckDispose(sb)
    CkPrivateKey::ckDispose(privKey)
    CkXml::ckDispose(xml)
    CkAsn::ckDispose(asn)
    CkRsa::ckDispose(rsa)
    CkBinData::ckDispose(bdSig)
    CkCert::ckDispose(cert)
    CkStringBuilder::ckDispose(sbSerial)


    ProcedureReturn
EndProcedure