CAPI: creating pkcs7 signature from large data
From: G. Rodr?guez (hez0s0_at_yahoo.com)
Date: 12/01/03
- Next message: Vishal Agarwal[MSFT]: "Re: Problem with Windows 2003 Certificate Server CDP"
- Previous message: Michel Gallant: "Re: Encryption in .NET and CryptoAPI Certificate Stores"
- Next in thread: G. Rodr?guez: "Re: CAPI: creating pkcs7 signature from large data"
- Reply: G. Rodr?guez: "Re: CAPI: creating pkcs7 signature from large data"
- Reply: Vishal Agarwal[MSFT]: "Re: creating pkcs7 signature from large data"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Date: 1 Dec 2003 10:01:17 -0800
Hi, i've been using CAPICOM to build some S/MIME messages in p7
format. However, CAPICOM seems to be unable to work with streaming,
which makes it unacceptable to sign large amounts of data. So i moved
to CryptoAPI, and tried to run some CAPI samples with streaming
signatures. I finally made the sample to run with my smartcard, but
the data i get does not seem to be valid ASN1 information. Such data
is (b64-encoded):
MYHnMIHkAgEBMD4wNjELMAkGA1UEBhMCRVMxDTALBgNVBAoTBEZOTVQxGDAWBgNVBAsTD0ZOTVQgQ2xhc2UgMiBDQQIEPHNZBjANBgkqhkiG9w0BAQUF
I'd like to find a way to produce a message similar to CAPICOM
SignedData.sign. I can't find my mistake in the following C CAPI code:
void main(void){
char szContentTotal[] = "Se firmara este mensaje partido en dos
trocitos.";
char* pszContentTotal = szContentTotal;
BYTE* pbContentTotal = (BYTE*) pszContentTotal;
DWORD cbContentTotal = sizeof(pszContentTotal);
char* pszProvider = "CeresCSP";
HCRYPTPROV hCryptProv = NULL; // Handle returned here
BOOL fReturn = FALSE;
fReturn = CryptAcquireContext(&hCryptProv, NULL, pszProvider,
PROV_RSA_FULL, 0 );
if(!fReturn) {
printf("CryptAcquireContext failed");
return;
}
HCERTSTORE hStoreHandle = NULL;
hStoreHandle = CertOpenSystemStore(hCryptProv, "MY");
if (!hStoreHandle) {
printf( "Error Getting Store Handle");
return;
}
PCCERT_CONTEXT pSignerCert = NULL;
pSignerCert = GetMySignerCert(hStoreHandle);
if(!pSignerCert)
{
printf( "Error Getting Signer Cert");
return;
}
DWORD HashAlgSize;
CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
HashAlgSize = sizeof(HashAlgorithm);
memset(&HashAlgorithm, 0, HashAlgSize);
HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
SignerEncodeInfo.pCertInfo = pSignerCert->pCertInfo;
SignerEncodeInfo.hCryptProv = hCryptProv;
SignerEncodeInfo.dwKeySpec = AT_SIGNATURE;
SignerEncodeInfo.HashAlgorithm = HashAlgorithm;
SignerEncodeInfo.pvHashAuxInfo = NULL;
CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1];
SignerEncodeInfoArray[0] = SignerEncodeInfo;
CERT_BLOB SignerCertBlob;
SignerCertBlob.cbData = pSignerCert->cbCertEncoded;
SignerCertBlob.pbData = pSignerCert->pbCertEncoded;
CERT_BLOB SignerCertBlobArray[1];
SignerCertBlobArray[0] = SignerCertBlob;
CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
SignedMsgEncodeInfo.cSigners = 1;
SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
SignedMsgEncodeInfo.cCertEncoded = 1;
SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray;
SignedMsgEncodeInfo.rgCrlEncoded = NULL;
DWORD cbEncodedBlob;
BYTE *pbEncodedBlob = NULL;
printf("Total size: %d\n", cbContentTotal);
cbEncodedBlob = CryptMsgCalculateEncodedLength( PKCS_7_ASN_ENCODING,
// Msg encoding type
0, // Flags
CMSG_SIGNED, // Msg type
&SignedMsgEncodeInfo, // Ptr. to struct.
NULL, // Inner content ObjID
cbContentTotal); // size of content
if(0 == cbEncodedBlob) {
printf("Getting cbEncodedBlob length failed\n");
return;
}else{
printf("Se reservarán %d bytes\n", cbEncodedBlob);
}
pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob);
if(NULL == pbEncodedBlob) {
printf("Malloc failed\n");
return;
}
HCRYPTMSG hMsg = NULL;
CMSG_STREAM_INFO streamInfo;
streamInfo.cbContent = cbContentTotal;
streamInfo.pfnStreamOutput = CmsgStreamOutputCallback;
streamInfo.pvArg = NULL;
hMsg = CryptMsgOpenToEncode(
PKCS_7_ASN_ENCODING,
0,
CMSG_SIGNED,
&SignedMsgEncodeInfo,
szOID_RSA_data,
&streamInfo);
if(NULL == hMsg) {
printf("OpenToEncode failed\n");
MyHandleError("Abriendo para codificar");
free(pbEncodedBlob);
return;
}
BOOL fResult;
fResult = CryptMsgUpdate( hMsg, pbContentTotal, cbContentTotal,
TRUE); if(!fResult){
printf("MsgUpdate failed: %d\n", GetLastError());
free(pbEncodedBlob);
MyHandleError("Haciendo el update del MSG1");
return;
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
CryptMsgClose(hMsg);
} //fin del main
BOOL WINAPI CmsgStreamOutputCallback(IN const void *pvArg, IN BYTE
*pbData, IN DWORD cbData, IN BOOL fFinal){
if (fFinal){
char *cResult = Encode64((char*) pbData);
printf("Message encoded sucessfully: #%s#\n", cResult);
}
return TRUE;
} //fin del CmsgStreamOutputCallback
Thank you in advance.
- Next message: Vishal Agarwal[MSFT]: "Re: Problem with Windows 2003 Certificate Server CDP"
- Previous message: Michel Gallant: "Re: Encryption in .NET and CryptoAPI Certificate Stores"
- Next in thread: G. Rodr?guez: "Re: CAPI: creating pkcs7 signature from large data"
- Reply: G. Rodr?guez: "Re: CAPI: creating pkcs7 signature from large data"
- Reply: Vishal Agarwal[MSFT]: "Re: creating pkcs7 signature from large data"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]