Развернуть все
Свернуть все

Создание подписи (через работу с потоками)

Пример создания подписанного сообщения (через работу с потоками) с помощью низкоуровневых функций КриптоПро ЭЦП 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;