CryptoSys PKI Toolkit Manual

CMS_GetSigDataDigest

CMS_GetSigDataDigest extracts the message digest from a signed-data CMS object file and verifies the signature.

VB6/VBA Syntax

Public Declare Function CMS_GetSigDataDigest Lib "diCrPKI.dll" (ByVal strHexDigest As String, ByVal nHexDigestLen As Long, ByVal strFileIn As String, ByVal strCertFile As String, ByVal nOptions As Long) As Long

nRet = CMS_GetSigDataDigest(strHexDigest, nHexDigestLen, strFileIn, strCertFile, nOptions) As Long

Parameters

strHexDigest
[out] String to receive the message digest output.
nHexDigestLen
[in] Long specifying the length of the output string.
strFileIn
[in] String with name of signed-data CMS object file.
strCertFile
[in] String specifying an (optional) X.509 certificate file to be used to identify the signer.
nOptions
[in] Long option flags:
PKI_DEFAULT (0) for default options
PKI_CMS_FORMAT_BASE64 to read input formatted with base64 encoding (default binary BER-encoded)

C/C++ Syntax

long _stdcall CMS_GetSigDataDigest(char *szHexDigestOut, long nDigestLen, const char *szFileIn, const char *szX509File, long nOptions);

Returns (VB6/C)

Long: If successful, the return value is a non-negative value indicating the message digest algorithm (CAUTION: this is not the number of characters in the output); otherwise it returns a negative error code.

.NET Equivalent

Cms.GetSigDataDigest Method

Remarks

This function extracts the message digest of the signed encapsulated content. In doing so, it also verifies that the signature is valid. The object may be a "detached signature" object. If signed attributes are present, the function will extract the messageDigest attribute for both RSA and [New in version 2.8] DSA signature algorithms. If signed attributes are not present, the message digest is extracted directly from the signature value, but only for RSA signatures, as the message digest cannot be directly extracted for a DSA signature. If given, the function will use the public key from the specified X.509 certificate to validate the signature; otherwise it will use the first valid SignerInfo and certificate pair it finds in the SignedData. The message digest, if found, is copied into strHexDigest. The maximum expected length of strHexDigest is PKI_MAX_HASH_CHARS characters. C/C++ users should allocate one extra. The message digest is encoded in hexadecimal format using lower-case letters [a-f].

The message digest algorithm is indicated by the return code:
PKI_HASH_SHA1 (0) SHA-1
PKI_HASH_MD5 (1) MD5
PKI_HASH_MD2 (2) MD2
PKI_HASH_SHA256 (3) SHA-256
PKI_HASH_SHA384 (4) SHA-256
PKI_HASH_SHA512 (5) SHA-512
PKI_HASH_SHA224 (6) SHA-224

CAUTION: unlike other hash-related functions, this function does not return the length of the digest string; it returns the code for the digest algorithm.

Note that this does not verify that the message digest is that of the content. It does, however, verify that the message digest was indeed signed by the purported signer, but it does not check the content itself. To verify that the SignedData object is validly signed, the user must extract the content separately and verify that its message digest matches the digest extracted by this function. To do this, use the functions CMS_ReadSigDataToString and HASH_HexFromBytes (or, for VB users, HASH_HexFromString). See the examples below.

[New in version 2.8:] Alternatively, use the CMS_VerifySigData to verify the signature and message digest directly and use CMS_QuerySigData to extract the messageDigest attribute, if present, without validation.

Example

This example extracts the message digest from the "detached signature" signed CMS object created by CMS_MakeDetachedSig above.

Dim nDigAlg As Long
Dim strCMSFile As String
Dim strHexDigest As String
strCMSFile = "C:\Test\DetSignByAlice.bin"
strHexDigest = String(PKI_MAX_HASH_CHARS, " ")
nDigAlg = CMS_GetSigDataDigest(strHexDigest, Len(strHexDigest), strCMSFile, "", 0)
Debug.Print "CMS_GetSigDataDigest returns " & nDigAlg
If nDigAlg < 0 Then
    Exit Function
End If
Debug.Print "Extracted digest is"
Debug.Print "[" & strHexDigest & "]"

This should produce the output

CMS_GetSigDataDigest returns 0
Extracted digest is
[406aec085279ba6e16022d9e0629c0229687dd48]

This second example shows how to retrieve the message digest and independently verify this against a hash of the content.

Dim strCMSFile As String
Dim strHexDigest As String
Dim nDigAlg As Long
Dim strData As String
Dim nDataLen As Long
Dim strContentDigest As String
Dim nHashLen As Long

strCMSFile = "C:\Test\4.2.bin"

' 1. Get the digest value
strHexDigest = String(PKI_MAX_HASH_CHARS, " ")
nDigAlg = CMS_GetSigDataDigest(strHexDigest, _
    Len(strHexDigest), strCMSFile, "", 0)
Debug.Print "CMS_GetSigDataDigest returns " & nDigAlg
If nDigAlg < 0 Then
    Exit Function
End If
Debug.Print "Extracted digest is"
Debug.Print "[" & strHexDigest & "]"

' 2. Go get the content - in this case it's in the signed-data object
nDataLen = CMS_ReadSigDataToString("", 0, strCMSFile, 0)
If nDataLen <= 0 Then
    Exit Function
End If
strData = String(nDataLen, " ")
nDataLen = CMS_ReadSigDataToString(strData, nDataLen, strCMSFile, 0)
Debug.Print "CMS_ReadSigDataToString returns " & nDataLen
Debug.Print "Data is [" & strData & "]"

' 3. Compute independently the hash of what we found
' (Note how we use the digest algorithm code returned above)
strContentDigest = String(PKI_MAX_HASH_CHARS, " ")
nHashLen = HASH_HexFromString(strContentDigest, _
    Len(strContentDigest), strData, nDataLen, nDigAlg)
Debug.Print "Computed hash of content is"
Debug.Print "[" & strContentDigest & "]"

' 4. Can we match this hash digest with 
'    what we extracted from the signed-data?
strContentDigest = Left(strContentDigest, nHashLen)
strHexDigest = Left(strHexDigest, nHashLen)
If strContentDigest = strHexDigest Then
    Debug.Print "SUCCESS - digests match!"
Else
    Debug.Print "FAILS! - no match"
End If

This should produce the output

CMS_GetSigDataDigest returns 0
Extracted digest is
[406aec085279ba6e16022d9e0629c0229687dd48]
CMS_ReadSigDataToString returns 28
Data is [This is some sample content.]
Computed hash of content is
[406aec085279ba6e16022d9e0629c0229687dd48]
SUCCESS - digests match!

And again, this time using C:

char *infile = "C:\\Test\\4.2.bin";
long ndigalg, mlen, hlen;
char hexdigest[41];
char conthash[41];
char *message;

/* 1. Get the digest string */
ndigalg = CMS_GetSigDataDigest(hexdigest, sizeof(hexdigest)-1, 
	infile, NULL, 0);
printf("CMS_GetSigDataDigest returns %ld\n", ndigalg);
if (ndigalg < 0) disp_error(ndigalg);
printf("SigDataDigest = %s\n", hexdigest);
//assert(lRet >= 0);

/* 2. Get the content from the signed-data object */
mlen = CMS_ReadSigDataToString(NULL, 0, infile, 0);
printf("Message data is %ld bytes long\n", mlen);
if (mlen < 0) disp_error(mlen);
assert(mlen >= 0);

/* Allocate some memory - NB add an extra byte */
message = malloc(mlen + 1);
assert(message);

/* Now read in */
mlen = CMS_ReadSigDataToString(message, mlen, infile, 0);
printf("CMS_ReadSigDataToString returns %ld\n", mlen);
if (mlen < 0) disp_error(mlen);
assert(mlen >= 0);
printf("Message is '%s'\n", message);

/* 3. Create a digest of this content 
   -- use the algorithm we got above */
hlen = HASH_HexFromBytes(conthash, sizeof(conthash)-1, 
	(unsigned char*)message, mlen, ndigalg);
printf("ContentDigest = %s\n", conthash);

/* 4. Finally we can compare */
if (strncmp(conthash, hexdigest, hlen) == 0)
	printf("SUCCESS - digests match!\n");
else
	printf("FAILS! - no match\n");

/* Clean up */
free(message);

See Also

CMS_ReadSigData CMS_ReadSigDataToString CMS_QuerySigData CMS_VerifySigData

[Contents] [Index]

[HOME]   [NEXT: CMS_MakeDetachedSig...]

Copyright © 2004-9 D.I. Management Services Pty Ltd. All rights reserved.