We get this question a lot:
I am using your CryptoSys PKI Toolkit to generate a signature and XYZ-validator tells me it's not valid.
Normally with this thrown in:
My code to generate the signature is taken from your example code. Why is it wrong?
We will gladly give your code a quick look to see if you are calling our CryptoSys PKI functions correctly and check for any obvious errors. Beyond that, we will have to charge our usual programming rates to solve the problem for you. Creating signatures is particularly tricky and debugging takes a long time, especially for XML documents. The answer is almost certainly that you have got the input wrong. But first check that you are using the RSA algorithm correctly in the One quick check you can make below.
We provide lots of examples on this site of how to use the CryptoSys PKI Toolkit (see for example here).
One common factor in almost all the code people send us to check is that all the debugging statements in our original code will have been removed. This immediately tells us what sort of programmer we are dealing with.
Our FirmaSAT utility provides support for XML-based signatures as specified by the S.A.T. in Mexico. If you are creating signatures for S.A.T., you can use FirmaSAT to carry out some additional tests on your XML file. See Troubleshooting FirmaSAT.
Check that the public key in the certificate can be used to decrypt the signature properly. This will either work and provide you with a message digest value or it will not. If you can extract a message digest (any message digest) then the CryptoSys RSA functions are working properly and the problem is definitely in your text input to the signature process. If you cannot extract a digest, you have the wrong certificate or you used the wrong private key to sign with. This is much easier to fix. There is no possiblity at all that the wrong public key can be used to extract a message digest from the signature - the output will be unformatted garbage.
Dim strPublicKey As String Dim strSello As String Dim strCertificado As String Dim abMsg() As Byte Dim abData() As Byte Dim nRet As Long Dim nSigLen As Long Dim nMsgLen As Long ' INPUT: Base64 strings extracted from the XML file (Ref: Muestra_v2_signed2.xml) strSello = "UlUSwGNEicfigV6i4RhTy0eb2RYWFYyFatJFcM/u5Wlkb5XRxXiCizTGw5Yxz9oZNk8msAgO4C5Gevjh+S2TJPZueYhaQeZlo6k0rE3CQexkOGVRpHkvAoAgOM5kGKzYe24DKZbTgjNL+ai+tbhEHmRAFcpv2rDpehbL3w6BnYU=" strCertificado = "MIIDhDCCAmygAwIBAgIUMTAwMDEyMDAwMDAwMDAwMjI1MTcwDQYJKoZIhvcNAQEFBQAwgcMxGTAXBgNVBAcTEENpdWRhZCBkZSBNZXhpY28xFTATBgNVBAgTDE1leGljbywgRC5GLjELMAkGA1UEBhMCTVgxGjAYBgNVBAMTEUFDIGRlIFBydWViYXMgU0FUMTYwNAYDVQQLFC1BZG1pbmlzdHJhY2nzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5" & _ "mb3JtYWNp824xLjAsBgNVBAoUJVNlcnZpY2lvIGRlIEFkbWluaXN0cmFjafNuIFRyaWJ1dGFyaWEwHhcNMDgwODIxMTUyMjA4WhcNMTAwODIxMTUyMjA4WjCBmDElMCMGA1UELRMcQUFBMDEwMTAxQUFBIC8gQUFBQTAxMDEwMUFBQTEeMBwGA1UEBRMVIC8gQUFBQTAxMDEwMUhERlJYWDAxMRIwEAYDVQQKEwlNYXRyaXogU0ExEzARBgNVBA" & _ "sTClVuaWRhZCAxMCAxEjAQBgNVBAMTCU1hdHJpeiBTQTESMBAGA1UEKRMJTWF0cml6IFNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpmiW1q9gyzCFtMcbaFDJexk2IpLoTdNXg4ToGRZ/f+hIjmj3N6ODWX1ARNFGYocEHf113GpW5Oe/mj6UqhBpiH4JRTNR4Udb8myJTArIlODynVHuIUuyhKo7gbMbDdXjilTAYY2XWQuQ7aDtWw" & _ "ntUmNg4vAC/F3OtRz3+y9wM5QIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAafyD4gMsOvq7E3raPntmQlJTxpWwNySqskE7fe23HVL9UKFCUlWWx/W8gluxIX9S19y17iWnGbtmbNddHxG5PznPsy/a8PlwNHjDW0FOpia2LsvDrNcdPiJhzL/1OVagkenffFf8bLEetF3ktxZ7ifcH1yxV" & _ "xpZ7PS/pe8YIOpWRuMmTV4ypGdsw9TW3HVP5IJ/canuQGPTb3LQ8ojihW2dHnC6ojaWW4GHFSZAPhQJ/DaH/UgFjaQke/RBtoAketfROdG+1qYeA1q/is04O4AXNmMByGp7ZnvGNrO9LDBvs3eKN4ZYcQyjxFEbr1X/xUqHCRF1VEkkC5jJQ1ktC4g==" ' 1. Read in Public key from X.509 certificate string directly strPublicKey = rsaGetPublicKeyFromCert(strCertificado) If Len(strPublicKey) = 0 Then Debug.Print "ERROR: failed to read Certificado string" Exit Sub End If ' --Show we got something useful Debug.Print "Public key is " & RSA_KeyBits(strPublicKey) & " bits long" ' 2. Convert base64 signature value to byte array abData = cnvBytesFromB64Str(strSello) nSigLen = UBound(abData) - LBound(abData) + 1 ' 2a. Check lengths match Debug.Print "Signature bytes=" & nSigLen Debug.Print "Key bytes =" & RSA_KeyBytes(strPublicKey) If nSigLen <> RSA_KeyBytes(strPublicKey) Then Debug.Print "ERROR: key length does not match signature" Exit Sub End If ' 3.Decrypt using RSA public key nRet = RSA_RawPublic(abData(0), nSigLen, strPublicKey, 0) Debug.Print "RSA_RawPublic returns " & nRet & " (expected 0)" If nRet <> 0 Then Debug.Print "ERROR: failed to decrypt RSA signature: error code " & nRet Exit Sub End If ' Display result in hex Debug.Print "Decrypted signature=" & vbCrLf & cnvHexStrFromBytes(abData) ' 4. Decode to extract the original message digest nMsgLen = RSA_DecodeMsg(0, 0, abData(0), nSigLen, PKI_EMSIG_DEFAULT) ReDim abMsg(nMsgLen - 1) nMsgLen = RSA_DecodeMsg(abMsg(0), nMsgLen, abData(0), nSigLen, PKI_EMSIG_DEFAULT) ' Display in hex Debug.Print "MD5 digest as hex: " & cnvHexStrFromBytes(abMsg)
This should give output like this
Public key is 1024 bits long
Signature bytes=128
Key bytes =128
RSA_RawPublic returns 0 (expected 0)
Decrypted signature=
0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003020300C06082A864886F70D0205050004104CD8ED248D7A02314C50778A37D1522D
MD5 digest as hex: 4CD8ED248D7A02314C50778A37D1522D
If you get a properly formatted block beginning with 0001FFFFFF...
then the RSA part is working OK.
The message digest is the last 16 (MD5) or 20 (SHA-1) bytes in the decrypted block (keep scrolling to the right!).
It would be good practice to build such a check into your signature generating program. So, every time you create a signature in your code, check that you can use the corresponding public key to extract the digest. Verifying the signature takes a lot less computing time than creating it. A simple check like this can save you hours of debugging and help-desk calls.
Dim sbPublicKey As StringBuilder Dim strSello As String Dim strCertificado As String Dim abMsg() As Byte Dim abData() As Byte ''Dim nRet As Integer Dim nSigLen As Integer ''Dim nMsgLen As Integer ' INPUT: Base64 strings extracted from the XML file (Ref: Muestra_v2_signed2.xml) strSello = "UlUSwGNEicfigV6i4RhTy0eb2RYWFYyFatJFcM/u5Wlkb5XRxXiCizTGw5Yxz9oZNk8msAgO4C5Gevjh+S2TJPZueYhaQeZlo6k0rE3CQexkOGVRpHkvAoAgOM5kGKzYe24DKZbTgjNL+ai+tbhEHmRAFcpv2rDpehbL3w6BnYU=" strCertificado = "MIIDhDCCAmygAwIBAgIUMTAwMDEyMDAwMDAwMDAwMjI1MTcwDQYJKoZIhvcNAQEFBQAwgcMxGTAXBgNVBAcTEENpdWRhZCBkZSBNZXhpY28xFTATBgNVBAgTDE1leGljbywgRC5GLjELMAkGA1UEBhMCTVgxGjAYBgNVBAMTEUFDIGRlIFBydWViYXMgU0FUMTYwNAYDVQQLFC1BZG1pbmlzdHJhY2nzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5" & _ "mb3JtYWNp824xLjAsBgNVBAoUJVNlcnZpY2lvIGRlIEFkbWluaXN0cmFjafNuIFRyaWJ1dGFyaWEwHhcNMDgwODIxMTUyMjA4WhcNMTAwODIxMTUyMjA4WjCBmDElMCMGA1UELRMcQUFBMDEwMTAxQUFBIC8gQUFBQTAxMDEwMUFBQTEeMBwGA1UEBRMVIC8gQUFBQTAxMDEwMUhERlJYWDAxMRIwEAYDVQQKEwlNYXRyaXogU0ExEzARBgNVBA" & _ "sTClVuaWRhZCAxMCAxEjAQBgNVBAMTCU1hdHJpeiBTQTESMBAGA1UEKRMJTWF0cml6IFNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpmiW1q9gyzCFtMcbaFDJexk2IpLoTdNXg4ToGRZ/f+hIjmj3N6ODWX1ARNFGYocEHf113GpW5Oe/mj6UqhBpiH4JRTNR4Udb8myJTArIlODynVHuIUuyhKo7gbMbDdXjilTAYY2XWQuQ7aDtWw" & _ "ntUmNg4vAC/F3OtRz3+y9wM5QIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAafyD4gMsOvq7E3raPntmQlJTxpWwNySqskE7fe23HVL9UKFCUlWWx/W8gluxIX9S19y17iWnGbtmbNddHxG5PznPsy/a8PlwNHjDW0FOpia2LsvDrNcdPiJhzL/1OVagkenffFf8bLEetF3ktxZ7ifcH1yxV" & _ "xpZ7PS/pe8YIOpWRuMmTV4ypGdsw9TW3HVP5IJ/canuQGPTb3LQ8ojihW2dHnC6ojaWW4GHFSZAPhQJ/DaH/UgFjaQke/RBtoAketfROdG+1qYeA1q/is04O4AXNmMByGp7ZnvGNrO9LDBvs3eKN4ZYcQyjxFEbr1X/xUqHCRF1VEkkC5jJQ1ktC4g==" ' 1. Read in Public key from X.509 certificate string directly sbPublicKey = Rsa.GetPublicKeyFromCert(strCertificado) If sbPublicKey.Length = 0 Then Console.WriteLine("ERROR: failed to read Certificado string") Exit Sub End If ' --Show we got something useful Console.WriteLine("Public key is " & Rsa.KeyBits(sbPublicKey.ToString) & " bits long") ' 2. Convert base64 signature value to byte array abData = System.Convert.FromBase64String(strSello) nSigLen = abData.Length ' 2a. Check lengths match Console.WriteLine("Signature bytes=" & nSigLen) Console.WriteLine("Key bytes =" & Rsa.KeyBytes(sbPublicKey.ToString)) If nSigLen <> Rsa.KeyBytes(sbPublicKey.ToString) Then Console.WriteLine("ERROR: key length does not match signature") Exit Sub End If ' 3.Decrypt using RSA public key abData = Rsa.RawPublic(abData, sbPublicKey.ToString) Console.WriteLine("RSA_RawPublic returns " & abData.Length & " bytes (expected >0)") If abData.Length = 0 Then Console.WriteLine("ERROR: failed to decrypt RSA signature.") Exit Sub End If ' Display result in hex Console.WriteLine("Decrypted signature=" & vbCrLf & Cnv.ToHex(abData)) ' 4. Decode to extract the original message digest abMsg = Rsa.DecodeDigestForSignature(abData) ' Display in hex Console.WriteLine("MD5 digest as hex: " & Cnv.ToHex(abMsg))
To comment on this page or for more information, please send us a message.
This page last updated 10 January 2019