cryptoapi — Добавление ответа от TSA в CRYPT_SIGN_MESSAGE_PARA для CryptSignMessage (c ++, Crypto Api)

Я изо всех сил, как я должен добавить ответ от сервера TSA к моему CryptSignMessage?

Использование PKCS # 7. В настоящее время у меня есть дайджест сообщения, и я успешно подписал его с CryptSignMessage из crypto api. Вот так:

// 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;

Любой совет будет принята с благодарностью.
Спасибо,
Магда

4

Решение

Я боролся с этим пару дней. Там не так много примеров, так что вот мое решение. Надеюсь, поможет 🙂

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

Другие решения

Других решений пока нет …