Пример создания подписанного сообщения (через работу с потоками) с помощью низкоуровневых функций КриптоПро ЭЦП SDK
C++
CMSG_SIGNER_ENCODE_INFO signer = { sizeof(CMSG_SIGNER_ENCODE_INFO) }; signer.pCertInfo = pCertContext->pCertInfo; signer.hCryptProv = hProv; signer.dwKeySpec = dwKeySpec; signer.HashAlgorithm.pszObjId = szOID_OIWSEC_sha1; CMSG_SIGNED_ENCODE_INFO info = { sizeof(CMSG_SIGNED_ENCODE_INFO) }; info.cSigners = 1; info.rgSigners = &signer; CADES_ENCODE_INFO cadesInfo = { sizeof(cadesInfo) }; cadesInfo.pSignedEncodeInfo = &info; std::vector<BYTE> original; CMSG_STREAM_INFO stream = {}; stream.cbContent = 0xFFFFFFFF; // неопределенная длина stream.pfnStreamOutput = ConvertCallback; stream.pvArg = &original; HCRYPTMSG hMsg = CadesMsgOpenToEncode( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,0,&cadesInfo,0,&stream); if(!hMsg) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); std::cout << "CadesMsgOpenToEncode() failed" << std::endl; return empty; } std::vector<BYTE> data(10,25); if(!CryptMsgUpdate(hMsg,&data[0],(DWORD)data.size(),FALSE)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); CryptMsgClose(hMsg); std::cout << "CryptMsgUpdate() failed" << std::endl; return empty; } if(!CryptMsgUpdate(hMsg,&data[0],(DWORD)data.size(),TRUE)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); CryptMsgClose(hMsg); std::cout << "CryptMsgUpdate() failed" << std::endl; return empty; } if(!CryptMsgClose(hMsg)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); std::cout << "CryptMsgGetParam() failed" << std::endl; return empty; } std::vector<BYTE> message; stream.pvArg = &message; hMsg = CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,0,0,0,&stream); if(!hMsg) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); std::cout << "CryptMsgOpenToDecode() failed" << std::endl; return empty; } if(!CryptMsgUpdate(hMsg,&original[0],10,FALSE)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); CryptMsgClose(hMsg); std::cout << "CryptMsgUpdate() failed" << std::endl; return empty; } if(!CryptMsgUpdate(hMsg,&original[0]+10,(DWORD)original.size()-10,TRUE)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); CryptMsgClose(hMsg); std::cout << "CryptMsgUpdate() failed" << std::endl; return empty; } CADES_SIGN_PARA signPara = { sizeof(signPara) }; signPara.dwCadesType = CADES_X_LONG_TYPE_1; signPara.pSignerCert = 0; if(!CadesMsgEnhanceSignature(hMsg,0,&signPara)) { CertFreeCertificateContext(pCertContext); CryptReleaseContext(hProv,0); CryptMsgClose(hMsg); std::cout << "CadesMsgAddEnhanceSignature() failed" << std::endl; return empty; } DWORD size = 0; if(!CryptMsgGetParam(hMsg,CMSG_ENCODED_MESSAGE,0,0,&size)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); CryptMsgClose(hMsg); std::cout << "CryptMsgGetParam() failed" << std::endl; return empty; } std::vector<BYTE> detached(size); if(!CryptMsgGetParam(hMsg,CMSG_ENCODED_MESSAGE,0,&detached[0],&size)) { CryptReleaseContext(hProv,0); CertFreeCertificateContext(pCertContext); CryptMsgClose(hMsg); std::cout << "CryptMsgGetParam() failed" << std::endl; return empty; } if(!CryptMsgClose(hMsg)) { CertFreeCertificateContext(pCertContext); CryptReleaseContext(hProv,0); std::cout << "CryptMsgGetParam() failed" << std::endl; return empty; } CertFreeCertificateContext(pCertContext); CryptReleaseContext(hProv,0); std::vector<BYTE> convertedMessage; stream.pvArg = &convertedMessage; PCADES_CONVERT_CONTEXT pConvert = CadesMsgConvertCreateContext(&stream,(PBYTE)&detached[0],(DWORD)detached.size()); if(!pConvert) { std::cout << "CadesMsgCreateConvertContext() failed" << std::endl; return empty; } DWORD chunkSize = 100; DWORD chunkCount = (DWORD)original.size()/chunkSize; DWORD lastChunkSize = (DWORD)original.size()%chunkSize; DWORD lastChunkStart = chunkCount*chunkSize; for( DWORD i = 0; i < chunkCount; ++i) { if(!CadesMsgConvertUpdate(pConvert,&original[i*chunkSize], chunkSize, FALSE)) { CadesMsgConvertFreeContext(pConvert); std::cout << "CadesMsgConvertUpdate() failed" << std::endl; return empty; } } if(!CadesMsgConvertUpdate(pConvert,&original[lastChunkStart], lastChunkSize, TRUE)) { CadesMsgConvertFreeContext(pConvert); std::cout << "CadesMsgConvertUpdate() failed" << std::endl; return empty; } if(!CadesMsgConvertFreeContext(pConvert)) { std::cout << "CadesMsgConvertFreeContext() failed" << std::endl; return empty; } return convertedMessage;