0 votes
by (210 points)
edited

Is there a simple way to get a digest value of the signed multipart Mime Message with a detached signature?

In my case it is a SHA-1 MIC value.

I load the message like this:

var mmSigned = new MimeMessage();
mmSigned.Load(memoryStream);
Applies to: Rebex Secure Mail

2 Answers

0 votes
by (210 points)
edited

Is it possible to to get the digest value from the signed data?

        var contentInfo = new ContentInfo(msData.ToArray());
        var signedData = new SignedData(contentInfo, true);
        signedData.IncludeOption = CertificateIncludeOption.EndCertificateOnly;

        var signer = new SignerInfo(signingCertificate, SubjectIdentifierType.IssuerAndSerialNumber, SignatureHashAlgorithm.SHA1);
        signedData.SignerInfos.Add(signer);
        signedData.Sign(SignatureOptions.SkipCertificateUsageCheck);
0 votes
by (144k points)
edited

There is no easy-to-use API to retrieve the digest value from the signed data, but it's still possible.

Method #1 - retrieve the hash value from signer's signed attributes collection:

        // get 'message digest' signed attribute
        byte[] digestOctetString = signer.SignedAttributes["1.2.840.113549.1.9.4"].Values[0];

        // discard the first two bytes (first one is 4, second one is octet string length)
        byte[] digest = new byte[digestOctetString.Length - 2];
        Array.Copy(digestOctetString, 2, digest, 0, digest.Length);

Method #2 - determine the hash algorithm from signer.DigestAlgorithm.Value and calculate the hash yourself using .NET's HashAlgorithm object:

        // determine digest algorithm name
        string algName = new Oid(signer.DigestAlgorithm.Value).FriendlyName;

        // create an instance of .NET's HashAlgorithm
        HashAlgorithm alg = HashAlgorithm.Create(algName);

        // calculate the hash
        byte[] digest = alg.ComputeHash(contentInfo.Content);

Note: To get SignedData object from a MimeMessage object, use this code:

        var mmSigned = new MimeMessage();
        mmSigned.Load(memoryStream);

        SignedData signedData = mmSigned.SignedContentInfo;
by (144k points)
edited

Please note that method #1 will only work for signatures that use signed attributes (whose use was already recommended by S/MIME v3 in 1999). On the other hand, it will work even without access to the actual signed data (unlike method #2).

...