1

I am trying to create a self-signed Certificate using the CLR-Security library Security.Cryptography.dll (their homepage: http://clrsecurity.codeplex.com)

I am able to create the certificate and even to Encrypt with it, but Decrypt fails with the following error "Invalid provider type specified."

Here is the certificate creation code:

public static bool generateCertificate(string distinguishedName)
{
        // Generate Key
        CngKeyCreationParameters keyParams = new CngKeyCreationParameters();
        keyParams.KeyCreationOptions = CngKeyCreationOptions.MachineKey | CngKeyCreationOptions.OverwriteExistingKey;
        keyParams.KeyUsage = CngKeyUsages.AllUsages; //CngKeyUsages.Decryption | CngKeyUsages.Signing;
        keyParams.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider;
        keyParams.ExportPolicy = CngExportPolicies.AllowExport;
        CngKey newKey = CngKey.Create(CngAlgorithm2.Rsa, Guid.NewGuid().ToString(), keyParams);

        // Init certificate
        X509CertificateCreationParameters certParams = new X509CertificateCreationParameters(new X500DistinguishedName(distinguishedName));
        certParams.SignatureAlgorithm = X509CertificateSignatureAlgorithm.RsaSha1;
        certParams.StartTime = DateTime.Now;
        certParams.EndTime = DateTime.Now.AddYears(10);

        // Create cert
        X509Certificate2 newCert = newKey.CreateSelfSignedCertificate(certParams);

        // Save to store
        X509Store lmStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        lmStore.Open(OpenFlags.ReadWrite);
        lmStore.Add(newCert);
        lmStore.Close();

        return true;
}

Here is the Encrypt method:

public static byte[] encryptStringPKCS7(string toEncrypt, List<byte[]> recipients)
    {
        // get bytes from encrypt text
        UnicodeEncoding unicode = new UnicodeEncoding();
        byte[] msgBytes = unicode.GetBytes(toEncrypt);

        // Create the certificate collection of the intended recipients
        X509Certificate2Collection recipientsCollection = new X509Certificate2Collection();
        foreach (byte[] currCertificate in recipients)
        {
            recipientsCollection.Add(new X509Certificate2(currCertificate));
        }

        //  Place message in a ContentInfo object.
        ContentInfo contentInfo = new ContentInfo(msgBytes);
        EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo);

        //  Formulate a CmsRecipientCollection object that
        //  represents information about the set of recipients 
        //  to encrypt the message for.
        CmsRecipientCollection cmsRecipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, recipientsCollection);

        //  Encrypt the message for the collection of recipients.
        envelopedCms.Encrypt(cmsRecipients);            
        return envelopedCms.Encode();
    }

Here is the Decrypt method:

public static string decryptStringPKCS7(byte[] toDecrypt)
    {
        // Place message in a ContentInfo object.
        // This is required to build an EnvelopedCms object.
        EnvelopedCms envelopedCms = new EnvelopedCms();            

        // Decrypt the message
        envelopedCms.Decode(toDecrypt);
        envelopedCms.Decrypt();
        byte[] msgDecrypted = envelopedCms.ContentInfo.Content;

        // Decode
        string msgClearText = Encoding.Unicode.GetString(msgDecrypted);
        return msgClearText;
    }

When I use exactly the same code with a certificate I created with makecert.exe - it works well. The makecert command line I use is: makecert.exe -sr LocalMachine -ss My -n CN=[SomeDN] -sk [SomeRandomGUID] -sky exchange

Do I need to specify some extra parameters in the creation of the CngKey or the Certificate? Or maybe pass in some extra info during Encrypt?

Thanks in advance for any help!

Roman
  • 91
  • 10
  • I presume you will have to set or set up the private key somewhere. It cannot be in `toDecrypt` so somewhere some link has to be made. This could be by the runtime system, but maybe that lookup - if any - fails (remark: I'm not a cng expert) – Maarten Bodewes Jun 19 '13 at 15:59
  • Supposedly, adding the RecipientCollection to the PKCS7 envelope upon encrypting - should point the decryption process back to the Certificate that should be used. But it seems that it cannot find it... I wonder if it is the Certificate cannot be found, or is it the case of the decryption itself that is failing? – Roman Jun 20 '13 at 10:31

0 Answers0