将TSA的响应添加到CryptSignMessage的CRYPT_SIGN_MESSAGE_PARA(c ++,Crypto Api)

时间:2013-08-26 15:21:45

标签: c++ cryptoapi trusted-timestamp

我正在努力如何将TSA服务器的响应添加到我的CryptSignMessage中?

使用PKCS#7。我目前有消息摘要,并且我使用来自crypto api的CryptSignMessage成功签名。像这样:

// Initialize the signature structure.
CRYPT_SIGN_MESSAGE_PARA  SigParams;
SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType = MY_ENCODING_TYPE;
SigParams.pSigningCert = hContext;
SigParams.HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
SigParams.HashAlgorithm.Parameters.cbData = NULL;
SigParams.cMsgCert = 1;
SigParams.rgpMsgCert = &hContext;
SigParams.dwInnerContentType = 0;
SigParams.cMsgCrl = 0;
SigParams.cUnauthAttr = 0;
SigParams.dwFlags = 0;
SigParams.pvHashAuxInfo = NULL;
SigParams.cAuthAttr = 0;
SigParams.rgAuthAttr = NULL;

// First, get the size of the signed BLOB.
if(CryptSignMessage(
    &SigParams,
    FALSE,
    1,
    MessageArray,
    MessageSizeArray,
    NULL,
    &cbSignedMessageBlob))
{
    printf("%d bytes needed for the encoded BLOB.", cbSignedMessageBlob);
}
else
{
    MyHandleError();
    fReturn = false;
    exit_SignMessage();
}

// Allocate memory for the signed BLOB.
if(!(pbSignedMessageBlob = 
   (BYTE*)malloc(cbSignedMessageBlob)))
{
    MyHandleError();
    exit_SignMessage();
}

// Get the signed message BLOB.
if(CryptSignMessage(
      &SigParams,
      TRUE,
      1,
      MessageArray,
      MessageSizeArray,
      pbSignedMessageBlob,
      &cbSignedMessageBlob))
{
    printf("The message was signed successfully. \n");


    // pbSignedMessageBlob now contains the signed BLOB.
    fReturn = true;
}
else
{
    MyHandleError();
    fReturn = false;
    exit_SignMessage();
}

现在我想使用TSA服务器为我的摘要加时间戳,但我不确定如何包含它。假设我有一个rfc3161 TimeStamp请求;我发送给我的TSA,我收到一个rfc3161 TimeStamp响应(可能使用libcurl)。如何将响应纳入我的SigParams?我必须提取TimeStampToken,然后将其存储为未经身份验证的计数器签名吗?类似的东西:

CRYPT_ATTR_BLOB cablob[1];
CRYPT_ATTRIBUTE ca[1];    
cablob[0].cbData = tstResponseSize; 
cablob[0].pbData = tstResponse; // the response from TSA

ca[0].pszObjId = "1.2.840.113549.9.6"; // object identifier for counter signature
ca[0].cValue = 1;
ca[0].rgValue = cablob;

然后设置SigParams:

SigParams.cUnauthAtt = 1;
SigParams.rgUnauthAttr = ca;

任何建议都将不胜感激。 谢谢, 玛格达

1 个答案:

答案 0 :(得分:1)

我挣扎了几天。那里没有那么多例子,所以这是我的解决方案。希望它有所帮助:)

HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, NULL, NULL, NULL);
    if (NULL == hMsg)
    {
        throw std::exception("Failed to open messsage to decode");
    }

    if (!::CryptMsgUpdate(hMsg, signedData.pbData, signedData.cbData, TRUE))
    {
        throw std::exception("Failed to add signature block to message");
    }

    //get the digest from the signature
    PCRYPT_TIMESTAMP_CONTEXT pTsContext = NULL;
    DWORD encDigestSize = 0;
    if (::CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, NULL, &encDigestSize))
    {
        std::unique_ptr<BYTE> pEncDigest(new BYTE[encDigestSize]);
        if (::CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, pEncDigest.get(), &encDigestSize))
        {
            //get timestamp 
            if (::CryptRetrieveTimeStamp(L"http://sha256timestamp.ws.symantec.com/sha256/timestamp",
                TIMESTAMP_NO_AUTH_RETRIEVAL,
                0, //timeout?????
                szOID_NIST_sha256,
                NULL,
                pEncDigest.get(),
                encDigestSize,
                &pTsContext,
                NULL,
                NULL))
            {

                CRYPT_ATTR_BLOB cryptBlob = {};
                cryptBlob.cbData = pTsContext->cbEncoded;
                cryptBlob.pbData = pTsContext->pbEncoded;

                CRYPT_ATTRIBUTE cryptAttribute = {};
                cryptAttribute.pszObjId = "1.2.840.113549.1.9.16.2.14"; //id-smime-aa-timeStampToken
                cryptAttribute.cValue = 1;
                cryptAttribute.rgValue = &cryptBlob;

                DWORD encodedAttributeSize = 0;
                std::unique_ptr<BYTE> encodedAttribute;
                if (::CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_ATTRIBUTE, &cryptAttribute, NULL, &encodedAttributeSize))
                {
                    encodedAttribute.reset(new BYTE[encodedAttributeSize]);
                    if (::CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_ATTRIBUTE, &cryptAttribute, encodedAttribute.get(), &encodedAttributeSize))
                    {
                        CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA unauthenticatedParam = { 0 };
                        unauthenticatedParam.cbSize = sizeof(unauthenticatedParam);
                        unauthenticatedParam.dwSignerIndex = 0; //only have 1 cert
                        unauthenticatedParam.blob.cbData = encodedAttributeSize;
                        unauthenticatedParam.blob.pbData = encodedAttribute.get();

                        if (::CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR, &unauthenticatedParam))
                        {
                            DWORD encodedMessageLength = 0;
                            if (::CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, NULL, &encodedMessageLength))
                            {
                                std::unique_ptr<BYTE> pData(new BYTE[encodedMessageLength]);
                                if (::CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, pData.get(), &encodedMessageLength))
                                {
                                    //save pData/encodedMessageLength here to file
                                }
                            }
                        }

                    }
                }


            }
        }
    }


    if (NULL != pTsContext)
    {
        ::CryptMemFree(pTsContext);
    }

    if (NULL != hMsg)
    {
        ::CryptMsgClose(hMsg);
    }