CryptDecryptAndVerifyMessageSignature() Fails !!!!

From: prem (premkumarjayaram_at_hotmail.com)
Date: 07/01/03


Date: Tue, 1 Jul 2003 07:34:52 -0700


Hello Everybody,

I have a problem using certificate APIs.
I have taken a piece of code from MSDN titled "Example C
Program: Sending and Receiving a Signed and Encrypted
Message". I did few customization to my needs and tried to
execute the program ( I had inlcuded the code also, see
below ).
I have two main functions SignAndEncrypt() and
DecryptAndVerify(). I wrote this as two separate program,
I execute SignAndEncrypt() on my w2k prof. mac which signs
the string using the users private key and encrypts using
the CAs public key.
The encrypted and encoded blob which I written into a file
and transfered to a w2k server ( domain controller with
Enterprise CA installed ). Form the w2k server I execute
the DecryptAndVerify() program which reads the encrypted
and encoded blob
from the file and decrypts it using the CA's private key.

Whenever I run DecryptAndVerify(), it fails during
CryptDecryptAndVerifyMessageSignature() and the error I am
getting using GetLastError() is "Cannot find the
certificate and private key to use for decryption".
error no: 2148081676

Also, the self signed certificate for my CA ( "myCA" )
does not say that it has a private key ( as it shows when
we view the personel certificates ).

I would really appreaciate anf kind of help.

Thanks.
-Prem

BYTE *SignAndEncrypt(
     const BYTE *pbToBeSignedAndEncrypted,
     DWORD cbToBeSignedAndEncrypted,
     DWORD *pcbSignedAndEncryptedBlob)
{

        //-------------------------------------------------
-------------------
        // Declare and initialize local variables.
        HCERTSTORE hCertStore, hCertStore1;

        //-------------------------------------------------
-------------------
        // pSignerCertContext will be the certificate of
the
        // the message signer.

        PCCERT_CONTEXT pSignerCertContext ;

        //-------------------------------------------------
-------------------
        // pReceiverCertContext will be the certificate
of the
        // message receiver.

        PCCERT_CONTEXT pReceiverCertContext;

        char pszNameString[256];
        CRYPT_SIGN_MESSAGE_PARA SignPara;
        CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara;
        DWORD cRecipientCert;
        PCCERT_CONTEXT rgpRecipientCert[5];
        BYTE
*pbSignedAndEncryptedBlob = NULL;
        CERT_NAME_BLOB *ReceiverNameBlob;
        DWORD cbNameBlob;
        DWORD dwKeySpec;
        HCRYPTPROV hCryptProv;
        CERT_NAME_BLOB CertBlob;

        //-------------------------------------------------
-------------------
        // Open the MY certificate store.
        // For details, see CertOpenStore.

        if ( !( hCertStore = CertOpenStore(
           CERT_STORE_PROV_SYSTEM,
           0,
           NULL,
           CERT_SYSTEM_STORE_CURRENT_USER,
           L"my")))
        {
                 HandleError("The MY store could not be
opened.");
        }

        //-------------------------------------------------
-------------------
        // Get the certificate for the signer.
        PCCERT_CONTEXT pContext = NULL ;
        while ( pContext = CertEnumCertificatesInStore
(hCertStore, pContext) )
        {
        //-------------------------------------------------
-------------------
        // The following function call is not required.
It is place here to
        // only to demonstrate a call to the
        // CryptAcquireCertificatePrivateKey function.

        if( CryptAcquireCertificatePrivateKey(
                 pContext,
                 0,
                 NULL,
                 &hCryptProv,
                 &dwKeySpec,
                 NULL))
        {
                 printf("CryptAcquireCertificatePrivateKey
worked. \n");
                 CertBlob = pContext->pCertInfo->Issuer;
                 pSignerCertContext = pContext;
                 break;
        }
        else
        {
                 //printf
("CryptAcquireCertificatePrivateKey failed.\n");
                continue;
        }

        }

        if ( !( hCertStore1 = CertOpenStore(
           CERT_STORE_PROV_SYSTEM,
           0,
           NULL,
           CERT_SYSTEM_STORE_CURRENT_USER,
           L"my")))
        {
                 HandleError("The MY store could not be
opened.");
                 return;
        }

        // Getting the certificate of the CA who issued
the user certificate
        //
        if(!(pReceiverCertContext =
CertFindCertificateInStore(
                 hCertStore1,
                 MY_TYPE,
                 0,
                 CERT_FIND_SUBJECT_STR,
                 L"myCA", // myCA is the name of the
Certificate Autority
                 NULL)))
        {
                 HandleError("Cert not found.\n");
                 return;
        }

        //-------------------------------------------------
-------------------
        // Initialize variables and data structures
        // for the call to CryptSignAndEncryptMessage.

        SignPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
        SignPara.dwMsgEncodingType = MY_TYPE;
        SignPara.pSigningCert = pSignerCertContext ;
        SignPara.HashAlgorithm.pszObjId = szOID_RSA_MD2;
        SignPara.HashAlgorithm.Parameters.cbData = 0;
        SignPara.pvHashAuxInfo = NULL;
        SignPara.cMsgCert = 1;
        SignPara.rgpMsgCert = &pSignerCertContext ;
        SignPara.cMsgCrl = 0;
        SignPara.rgpMsgCrl = NULL;
        SignPara.cAuthAttr = 0;
        SignPara.rgAuthAttr = NULL;
        SignPara.cUnauthAttr = 0;
        SignPara.rgUnauthAttr = NULL;
        SignPara.dwFlags = 0;
        SignPara.dwInnerContentType = 0;

        EncryptPara.cbSize = sizeof
(CRYPT_ENCRYPT_MESSAGE_PARA);
        EncryptPara.dwMsgEncodingType = MY_TYPE;
        EncryptPara.hCryptProv = 0;
        EncryptPara.ContentEncryptionAlgorithm.pszObjId =
szOID_RSA_RC4;
        EncryptPara.ContentEncryptionAlgorithm.Parameters.c
bData = 0;
        EncryptPara.pvEncryptionAuxInfo = NULL;
        EncryptPara.dwFlags = 0;
        EncryptPara.dwInnerContentType = 0;

        cRecipientCert = 1;
        rgpRecipientCert[0] = pReceiverCertContext;
        *pcbSignedAndEncryptedBlob = 0;
        pbSignedAndEncryptedBlob = NULL;

        if( CryptSignAndEncryptMessage(
           &SignPara,
           &EncryptPara,
           cRecipientCert,
           rgpRecipientCert,
           pbToBeSignedAndEncrypted,
           cbToBeSignedAndEncrypted,
           NULL, // the
pbSignedAndEncryptedBlob
           pcbSignedAndEncryptedBlob))
        {
           printf("%d bytes for the
buffer .\n",*pcbSignedAndEncryptedBlob);
        }
        else
        {
                DWORD d = GetLastError();
                 HandleError("Getting the buffer length
failed.");
                 return;
        }

        //-------------------------------------------------
-------------------
        // Allocated memory for the buffer

        if(!(pbSignedAndEncryptedBlob=(unsigned char *)
                 malloc(*pcbSignedAndEncryptedBlob)))
                 HandleError("Memory allocation failed.");

        //-------------------------------------------------
-------------------
        // Call the function a second time to copy the
signed and encrypted
        // message into the buffer

        if( CryptSignAndEncryptMessage(
           &SignPara,
           &EncryptPara,
           cRecipientCert,
           rgpRecipientCert,
           pbToBeSignedAndEncrypted,
           cbToBeSignedAndEncrypted,
           pbSignedAndEncryptedBlob,
           pcbSignedAndEncryptedBlob))
        {
                 printf("The message is signed and
enrypted.\n");
        }
        else
        {
                 HandleError("The message failed to sign
and encrypt.");
        }

        FILE *fp=fopen("c:\\signedblob.txt","w");
        fwrite
(pbSignedAndEncryptedBlob,*pcbSignedAndEncryptedBlob,1,fp);
        fclose(fp);

        //-------------------------------------------------
-------------------
        // Clean up.

        if(pSignerCertContext )
        {
                 CertFreeCertificateContext
(pSignerCertContext );
        }
        if(pReceiverCertContext )
        {
                 CertFreeCertificateContext
(pReceiverCertContext );
        }
        CertCloseStore(
                 hCertStore,
                 0);

        //-------------------------------------------------
-------------------
        // Return the signed and encrypted message.

        return pbSignedAndEncryptedBlob;

} // End SignandEncrypt.

void CallDecryptAndVerify()
{
        BYTE pbSignedAndEncryptedBlob[3500];

        FILE *fp=fopen("c:\\signedblob.txt","w");
        int nRead = fread
(pbSignedAndEncryptedBlob,1,3500,fp);
        fclose(fp);

        DecryptAndVerify(pbSignedAndEncryptedBlob,nRead);
}

BYTE *DecryptAndVerify(
     BYTE *pbSignedAndEncryptedBlob,
     DWORD cbSignedAndEncryptedBlob)
{

        //-------------------------------------------------
-------------------
        // Declare and initialize local variables.

        HCERTSTORE hCertStore;
        CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
        CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
        DWORD dwSignerIndex = 0;
        BYTE *pbDecrypted;
        DWORD cbDecrypted;

        //-------------------------------------------------
-------------------
        // Open the certificate store

        if ( !( hCertStore = CertOpenStore(
           CERT_STORE_PROV_SYSTEM,
           0,
           NULL,
           CERT_SYSTEM_STORE_LOCAL_MACHINE,
        // L"root"))) // I trid with both "my"
and "root", no luck
           L"my")))
        {
                 HandleError("The MY store could not be
openned.");
                 return;
        }

        //-------------------------------------------------
-------------------
        // Initialize the needed data structures.

        DecryptPara.cbSize = sizeof
(CRYPT_DECRYPT_MESSAGE_PARA);
        DecryptPara.dwMsgAndCertEncodingType = MY_TYPE;
        DecryptPara.cCertStore = 1;
        DecryptPara.rghCertStore = &hCertStore;

        VerifyPara.cbSize = sizeof
(CRYPT_VERIFY_MESSAGE_PARA);
        VerifyPara.dwMsgAndCertEncodingType = MY_TYPE;
        VerifyPara.hCryptProv = 0;
        VerifyPara.pfnGetSignerCertificate = NULL;
        VerifyPara.pvGetArg = NULL;
        pbDecrypted = NULL;
        cbDecrypted = 0;

        //-------------------------------------------------
-------------------
        // Call CryptDecryptAndVerifyMessageSignature
a first time
        // to determine the needed size of the buffer
to hold the
        // decrypted message.

        if(!(CryptDecryptAndVerifyMessageSignature(
           &DecryptPara,
           &VerifyPara,
           dwSignerIndex,
           pbSignedAndEncryptedBlob,
           cbSignedAndEncryptedBlob,
           NULL, // pbDecrypted
           &cbDecrypted,
           NULL,
           NULL)))
        {
                 HandleError("Failed."); // Here is
where it is failing
                 return;
        }

        //-------------------------------------------------
-------------------
        // Allocate memory for the buffer to hold the
decrypted message.

        if(!(pbDecrypted = (BYTE *)malloc(cbDecrypted)))
                HandleError("Memory allocation failed.");

        if(!(CryptDecryptAndVerifyMessageSignature(
           &DecryptPara,
           &VerifyPara,
           dwSignerIndex,
           pbSignedAndEncryptedBlob,
           cbSignedAndEncryptedBlob,
           pbDecrypted,
           &cbDecrypted,
           NULL,
           NULL)))
        {
                 pbDecrypted = NULL;
        }

        //-------------------------------------------------
-------------------
        // Close the certificate store.

        CertCloseStore(
                 hCertStore,
                 0);

        //-------------------------------------------------
-------------------
        // Return the decrypted string or NULL

        return pbDecrypted;

} // end of DecryptandVerify



Relevant Pages

  • Re: Help please - Can not use/export private key after domain change
    ... You see only one EFS certificate in your private cert store? ... the certificate, also when I view it, it says that I have private key ... Windows XP encrypts the ...
    (microsoft.public.security)
  • Re: How to Decrypt using Public Key?
    ... encrypts with the private key so anyone can decrypt with the public key and ... To decrypt information encrypted with the private key given a certificate, ...
    (microsoft.public.platformsdk.security)
  • Re: Unable to use third-party cert after Exch Sp2 update on SBS200
    ... Every *server* certificate in IIS has to ... The public key is sent when a request from a browser ... The public key is used to *decrypt* data. ... The private key is used ...
    (microsoft.public.windows.server.sbs)
  • RE: SIMple SSL question ??
    ... I believe your book is instructing you to keep the private key secure. ... you use the certificate request wizard in IIS to install the cert after it's ... the certificate that's just been installed. ... If an attacker retrievs the SSL certificate, ...
    (microsoft.public.dotnet.security)
  • RE: SIMple SSL question ??
    ... I believe your book is instructing you to keep the private key secure. ... you use the certificate request wizard in IIS to install the cert after it's ... the certificate that's just been installed. ... If an attacker retrievs the SSL certificate, ...
    (microsoft.public.dotnet.security)