1

My requirement is to verify the signed hash in my C++ application which was earlier signed in VB.Net !

I ll briefly explain you what I did to achieve it.. First of all I created a Private/Public Key Pair with CspParameters.KeyNumber value = "Signature" and exported its CspBlob to a file "KeyPair.txt" for using the Public Key in my C++ program.

 Dim str As testData= "Hello World"
  Dim Hash() As Byte = HashAlgorithm.Create("SHA1").ComputeHash(testData)
  Hash = RSA.SignHash(Hash, CryptoConfig.MapNameToOID("SHA1"))
  Array.Reverse(Hash)

and saved the Signed Hash in a File "Signature.txt" in reverse order for VB.Net to Native CAPI compatibility (Big Endian to Little Endian).

2.) On other end ( C++ Program) ...

Firstly, I computed the SHA1 of testData "Hello World" and then did used below code for verifying the signature.

  BYTE* Message_Digest_SHA1 = SHA1("Hello World");
    BYTE* pbBlob = ReadFile("KeyPair.txt");
    int pbBlobLen = GetFileLen("KeyPair.txt");
    BYTE* pbSignature = ReadFile("Signature.txt");
    int pbSignatureLen = GetFileLen("Signature.txt");

    if (!CryptAcquireContext(&hProv, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
        {
    //Error checking omitted !
    }


   if (pbBlob) {
            if (!CryptImportKey(hProv, pbBlob, pbBlobLen , 0, 0, &hPubKey))
                return FALSE;
               } 


    HCRYPTHASH hHash;
    if(CryptCreateHash(
       hProv, 
       CALG_SHA1, 
       0, 
       0, 
       &hHash)) 
    {
         printf("The hash object has been recreated. \n");
    }
    else
    {
        // Error
    }

    if(CryptHashData(
       hHash, 
       Message_Digest_SHA1 , 
       20, // length of message digest
       0)) 
    {
         printf("The new hash has been created.\n");
    }
    else
    {
         //Error
    }

    if(CryptVerifySignature(
       hHash, 
       pbSignature, 
       pbSignatureLen , 
       hPubKey,
       NULL, 
       0)) 
    {
         printf("The signature has been verified.\n");
    }
    else
    {
        DWORD error = GetLastError(); // 2148073478   in HEX 0x80090006  NTE_BAD_SIGNATURE
         printf("Signature not validated!\n");
    }


    if(hHash) 
      CryptDestroyHash(hHash);

But, CryptVerifySignature fails with NTE_BAD_SIGNATURE ! Can you please look into my code and point out my mistake

Thank you.

  • 1
    I strongly suspect you shouldn't be reversing the hash... it's just a sequence of bytes, not a number to be considered as little-endian or big-endian... – Jon Skeet Jan 16 '14 at 21:02
  • @JonSkeet Pls refer this MSDN link , if it could help http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx#remarksToggle – Windows Programmer Jan 16 '14 at 21:06
  • Interesting, but that says it's for encryption rather than signing. Have you at least *tried* not reversing it? – Jon Skeet Jan 16 '14 at 21:08
  • Yes, I tried both ways ! Infact , also came across http://stackoverflow.com/questions/16015408/digital-signature-made-in-c-sharp-does-not-verify-in-c?rq=1 – Windows Programmer Jan 16 '14 at 21:11
  • 2
    Right. Just as an aside, your "C#" code appears to be a mixture of C# and VB, and your C++ code appears to be invalid (look at the arguments to ReadFile for example). Can you post short but *complete and valid* C# and C++ programs which demonstrate the problem? – Jon Skeet Jan 16 '14 at 21:12
  • Pls consider the .NET code in VB, and I just added the File Reading functions for reference , these are not actual functions, except those functions all the Code is Actual. – Windows Programmer Jan 16 '14 at 21:18
  • 1
    Without real code, it's going to be very hard to reproduce the problem. With short but complete programs we're likely to be able to help you more easily. – Jon Skeet Jan 16 '14 at 21:20

1 Answers1

1

You seem to hash twice. Once in

BYTE* Message_Digest_SHA1 = SHA1("Hello World");

then again in

CryptHashData(hHash, Message_Digest_SHA1, 20,0)

I suspect you need to hash only once. I would recommend removing the first one as the signature method expects a reference to a hash object. Supply the correct binary encoding of "Hello World" as data instead.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • 1
    Note that I don't see any `ComputeHash` method for strings, so pretty please with sugar on top, provide us with an SSCCE (or two). – Maarten Bodewes Jan 16 '14 at 21:50