Friday, January 5, 2018

Decrypting EnvelopedCms with non-default AlgorithmIdentifier

Leave a Comment

I'm trying to decrypt a EnvelopedCms that was encrypted using a non-default AlgorithmIdentifier like this:

ContentInfo contentInfo = new ContentInfo(data); EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo, new AlgorithmIdentifier(new System.Security.Cryptography.Oid("2.16.840.1.101.3.4.1.42"))); CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, certificates); envelopedCms.Encrypt(recipients); byte[] encryptedData = envelopedCms.Encode(); 

The encryption works as expected. Now when I try to decrypt the envelopedCms using something like this:

EnvelopedCms envelopedCms = new EnvelopedCms(); envelopedCms.Decode(encryptedData ); envelopedCms.Decrypt(certificates); byte[] decryptedData = envelopedCms.ContentInfo.Content; 

I notice that a.) the access to the certificate takes quite long (longer then when using the default AlgorithmIdentifier) and b.) I get this error message:

System.Security.Cryptography.CryptographicException: Access denied 

Which, looking at the source where this fails, is probably not the issue. Now I see that I haven't provided the encryption algorithm to use in the decrypt method anywhere and I believe that's the issue but I'm not sure how to specify the AlgorithmIdentifier for the decryption.

From the documenation I can see that the EnvelopedCms.Decrypt can take a RecipientInfo which can specify the algorithm but since we used multiple certificates for the encryption I'm not sure how to build such an object. Ideally I was thinking that the correct RecipientInfo, containing the actually used AlgorithmIdentifier, is already contained in the EnvelopedCms.RecipientInfos array. But it seems like this is not the case.

Can anyone get the decrypt code above working?

1 Answers

Answers 1

Although my answer may lead to some incomplete tangents, I believe that it will get you the same assertion that I have come to. The fact is that I use a X509Store allows me to locate the certificates that my machine has. I then pass the collection into the CmsReceipientCollection with a X509Certificate2Collection that is found from my store.Certificates. This method takes 128ms to execute. HTH!

 [TestMethod]     public void TestEnvelopedCMS()     {         X509Store store = new X509Store("MY", StoreLocation.CurrentUser);         store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);          X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;         X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);          byte[] data = new byte[256];         //lets change data before we encrypt         data[2] = 1;          ContentInfo contentInfo = new ContentInfo(data);         EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo, new AlgorithmIdentifier(new System.Security.Cryptography.Oid("2.16.840.1.101.3.4.1.42")));         CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, fcollection);         envelopedCms.Encrypt(recipients);         byte[] encryptedData = envelopedCms.Encode();          //lets decrypt now         envelopedCms.Decode(encryptedData);         envelopedCms.Decrypt(fcollection);         byte[] decryptedData = envelopedCms.ContentInfo.Content;           //grab index from byte[]         var item = decryptedData.Skip(2).Take(1).FirstOrDefault();         var item2 = data.Skip(2).Take(1).FirstOrDefault();          Assert.IsTrue(item == item2);     } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment