CryptoSys Home > PKI > My signature will not validate

My signature will not validate


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?

Our free support service

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.

Our Example Code

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.

FirmaSAT utility

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.

One quick check you can make

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.

Example in VB6

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.

Same example in VB.NET

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))

Contact

To comment on this page or for more information, please send us a message.

This page last updated 10 January 2019