PureBasic
PureBasic
Sign Mexico Pedimento
See more Misc Examples
Add a signature to a Mexico pedimento file.Chilkat PureBasic Downloads
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