locked
Signature verification using Crypto APIs RRS feed

  • Question

  • Hi

    I have a server signing the binary using OpenSSL (hash Algo: SHA1). I have a client (running on Windows XP) which downloads this binary and needs to verify the signature. What I can get from the server is the public key in the der format converted to hex. I am trying to verify signature in client using CryptVerufySignature. However the call fails with NTE_BAD_SIGNATURE

    The steps I follow in client are:

    CryptAcquireContext(&hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)

    CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)

    CryptHashData(hHash, buffer, length, 0)

    CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&dwHashLen, &dwHashLenSize, 0)

    CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)

     

    // Initialize Public Key BLOB. Refer http://msdn.microsoft.com/en-us/library/aa387459.aspx

    blobSize =

    sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + keySize + 1

    publicKeyBlob = (BYTE*) malloc(blobSize)

    memset(publicKeyBlob, 0, blobSize)

    blobHeader = (BLOBHEADER*)publicKeyBlob

    blobHeader->bType = PUBLICKEYBLOB

    blobHeader->bVersion = CUR_BLOB_VERSION

    blobHeader->reserved = 0

    blobHeader->aiKeyAlg = CALG_RSA_SIGN

    rsaPubKey = (RSAPUBKEY*)(publicKeyBlob +

    sizeof(BLOBHEADER));

    rsaPubKey->magic = 0x31415352;

    // "RSA1"

    rsaPubKey->bitlen = (keySize + 1) * 8;

    rsaPubKey->pubexp = 65537;

    // 0x00010001

    memcpy(publicKeyBlob +

    sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), keyBuffer, keySize + 1);

     

     

    CryptImportKey(hCryptProv, (BYTE*)publicKeyBlob, blobSize, 0, 0, &hPubKey)

    Here I change the endianness of the signature.

    CryptVerifySignature(hHash, signature, strlen(signature), hPubKey, NULL, 0).

    However if I do the same thing using openSSL in client it succeeds.

    Steps:

    get SHA1 hash of the content. This matches with the one I get from CryptGetHashParam

    publicKeyRSA = d2i_RSA_PUBKEY(0, &p, (

    long)publicKeySize);

     

    // Decrypt

    decrypted = (

    char*)malloc(RSA_size(publicKeyRSA) + 1);

    size = RSA_public_decrypt((

    int)encryptedSize, (unsigned char*)encrypted, (unsigned char*)decrypted, publicKeyRSA, RSA_PKCS1_PADDING);

    RSA_free(publicKeyRSA);

    decrypted[size] =

    '\0';

    Here decrypted matches with the SHA1 hash.

    Any help would be highly appreciated.

    Thanks

    Karishma

     

    Wednesday, May 12, 2010 9:11 AM

All replies

  • is my usage of CryptImportKey indeed correct?
    Wednesday, May 12, 2010 9:13 AM
  • Hi,

    When creating the Public Key Blob, the value of the modulus copied at the end of the structure must be in LITTLE ENDIAN format.
    In your code, did you try changing the endianess of the variable keybuf before calling memcpy?

    --
    Mounir IDRASSI
    IDRIX
    http://www.idrix.fr

    Wednesday, May 12, 2010 4:29 PM
  • Hey Thanks.

    Ya I tried doing that.

    Both the key and the signature that I get in client are in hex format. I first convert them to binary in the code and then change the endianness of the binary data before using them. I convert them to binary even when using openSSL APIs. So I am pretty confident that that conversion is fine.

    I even tried using CRYPT_NOHASHOID in CryptVerifySignature as the last param (as I have a RSA signature). Still no luck!

    Thursday, May 13, 2010 7:37 AM