EnvelopedCms decrypt problem
.NET’s EnvelopedCms class represents a CMS/PKCS #7 structure for enveloped data. Such data are for example used in S/MIME encrypted messages.
EnvelopedCms class contains several Decrypt method overloads:
- Decrypt(RecipientInfo, X509Certificate2Collection)
Each Decrypt method decrypts the contents of the decoded enveloped CMS/PKCS #7 data. Each searches the current user and local machine My stores for the appropriate certificate and private key.
Last two overloads allow passing additional collection of X509 certificates, that should be searched to find matching certificate for decryption.
There are 2 most common errors that can occur while decrypting:
- “The enveloped-data message does not contain the specified recipient.” – Which means that no matching certificate was found in My stores and in the additional certificate collection.
- “Cannot find object or property.” – Certificate was found, but there is no private key in it, so it can not be used to decryped the enveloped data.
There are 3 ways of adding certificates to My store, 2 of those don’t import private key:
- “Personal” tab in CertMgr (does not import private key).
- MMC “Certificates” snap-in (“My user account”) (does not import private key).
- Double clicking the pfx file (imports private key).
In many cases data are encrypted using 2 or more certificates (so both sender and receiver are able to decrypt the message)
The problem with all Decrypt methods is that they try to use only the first certificate they find. The matching is based on certificate SN. First, both My stores are search, then extra store (passed certificate collection).
This leads to a problem when, both certificates are in My store, but only one contains a private key.
.NET is going to use the first certificate it finds – if it’s the one without the private key, “Cannot find object or property” exception is going to be thrown.
The only workaround for this problem is to try to decrypt the message for each ReceipientInfo separately. This way we are sure that all certificates will be tried.
Mail.dll .NET secure email component does this automatically, so no additional code is required.