Countersigning Signed Messages
Sometimes you may want to countersign a signed message. For example, assume that user A sends a document, in the form of a signed-data message, to user B, expecting B to confirm agreement to the terms contained in the document. User B decodes the message, reads the terms and, if in agreement, countersigns the message. The countersigned message is then sent the back to user A. User A now knows, and can prove, that user B agreed to the terms.
There are some CryptoAPI low-level message functions that assist with the countersigning process.
-
CryptMsgCountersign. Countersigns an already existing signature in a message, and adds the countersignature to the message as an unauthenticated attribute.
-
CryptMsgCountersignEncoded. Countersigns an already existing signature (encoded SignerInfo, as defined by PKCS # 7) in a message. It outputs an encoded SignerInfo blob suitable for adding to a signed-data message, or a signed-and-enveloped-data message, as an unauthenticated attribute.
-
CryptMsgVerifyCountersignatureEncoded. Verifies a countersignature at the SignerInfo level. It verifies that a retrieved countersignature attribute contains the encrypted hash of the encryptedDigest field of the original SignerInfo.
Note Although the syntax of these functions allows for multiple countersigners, only a single countersigner is currently supported.
To countersign a signed message by using CryptMsgCountersign
-
Call CryptMsgOpenToDecode to get a handle to the signed message.
-
Initialize a PCMSG_SIGNER_ENCODE_INFO structure for the countersigner.
-
Add the PCMSG_SIGNER_ENCODE_INFO structure to an array of countersigners (only one countersigner is currently supported).
-
Call CryptMsgCountersign to add the countersignature(s).
If the function call succeeds, the original message now has a countersignature included as an unauthenticated attribute.
-
Call CryptMsgOpenToDecode to get a handle to the signed message.
-
Call CryptMsgGetParam to retrieve the encoded SignerInfo of the signed message.
-
Initialize a PCMSG_SIGNER_ENCODE_INFO structure for the countersigner.
-
Add PCMSG_SIGNER_ENCODE_INFO structure to an array of countersigners (only one countersigner is currently supported).
-
Call CryptMsgCountersignEncoded to create the encoded countersignature attribute.
-
Call CryptMsgControl to add the countersignature attribute to the original message as an unauthenticated attribute.
If all of the function calls succeed, a countersignature attribute was added to the original message.
To Verify a Countersignature
-
Call CryptMsgOpenToDecode to get a handle to the signed message.
-
Get a pointer to the countersigner's certificate (PCERT_INFO).
-
Call CryptMsgGetParam to retrieve the SignerInfo from the message.
-
Call CryptMsgGetParam to retrieve the Countersignature from the message.
-
Call CryptMsgVerifyCountersignatureEncoded to verify the countersignature.
If the CryptMsgVerifyCountersignatureEncoded function call succeeds, the countersignature is verified.