2013-08-26 40 views
3

我正在努力如何將來自TSA服務器的響應添加到我的CryptSignMessage?添加來自TSA的CRYPT_SIGN_MESSAGE_PARA對CryptSignMessage的響應(C++,Crypto Api)

使用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; 

任何意見將不勝感激。 謝謝, Magda

+0

你有想過嗎? –

回答

0

我掙扎了幾天。這裏沒有那麼多的例子,所以這裏是我的解決方案。希望它有幫助:)

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); 
    }