Search code examples
c#encryptionx509pfx

Encrypting string using a PFX-File in C#


I want to encrypt my string using a PFX-File. Then the encrypted string are written into the database. The password of the PFX-File is securely stored in the app.config and also encrypted. Always when the method gets executed it throws a System.NullReferenceException, but I don't know why. I watched at my variabled and the password of the file was correctly decrypted. Here is my source code.

public string EncryptString(string text, string certificatePath, string password)
    {
        byte[] data = Encoding.UTF8.GetBytes(text);
        X509Certificate2Collection collection = new X509Certificate2Collection();
        collection.Import(certificatePath, password, X509KeyStorageFlags.PersistKeySet);
        X509Certificate2 certificate = collection[0];
        RSACryptoServiceProvider publickey = certificate.PublicKey.Key as RSACryptoServiceProvider;
        byte[] encrypted = publickey.Decrypt(data, false);

        return Convert.ToBase64String(encrypted);
    }

After debugging Visual Studio says "publickey = null"

PFX as Base64:

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

(I created my certificates with XCA) Password: test123

Can someone help me?


Solution

  • You cannot just encrypt data with a pfx, you need to specify a format.

    Windows uses .pfx for a PKCS #12 file. This file can contain a variety of cryptographic information, including certificates, certificate chains, root authority certificates, and private keys. Its contents can be cryptographically protected (with passwords) to keep private keys private and preserve the integrity of root certificates.

    What is the difference between a cer, pvk, and pfx file?

    With EnvelopedCms you have a format which is easy to use and consumes a pfx file, for more information see Cryptographic Message Syntax https://www.rfc-editor.org/rfc/rfc5652.

    If you want to secure sensitive data you should get your implementation reviewed from pros!

    Code

    Some students created with for learning purpose, https://github.com/haevg-rz/LearnToCode/blob/master/Examples/EncryptionDemo/EncryptionDemo.Sample/CryptographicMessageSyntax.cs

    I changed the code a bit, so its is more familier to your code.

    using System;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Cryptography.Pkcs;
    using System.Text;
    using System.IO;
    using System.Security;
    
    namespace PfxTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello to PfxTest!");
                File.WriteAllBytes("test.pfx", Convert.FromBase64String(pfxBase64));
                
                var r = EncryptString("Hello", "test.pfx","test123");
                Console.WriteLine(r);
            }
    
            static string pfxBase64 = "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";
    
            static public string EncryptString(string text, string certificatePath, string password)
            {
                byte[] data = Encoding.UTF8.GetBytes(text);
                CmsRecipientCollection collection = new CmsRecipientCollection();
                 var secureString = new SecureString();
                foreach (var item in password) secureString.AppendChar(item);
                var certificate = new X509Certificate2(File.ReadAllBytes(certificatePath),secureString);
                collection.Add(new CmsRecipient(certificate,RSAEncryptionPadding.OaepSHA512));
                
                var envelopedCms = new EnvelopedCms(new ContentInfo(data));
                if (envelopedCms.ContentEncryptionAlgorithm.Oid.FriendlyName != "aes256")
                    // After .NET Core 3 aes256 is the standard ContentEncryptionAlgorithm, before it was 3des.
                    throw new Exception("Only aes256 is allowed.");
    
                envelopedCms.Encrypt(collection);
                var encrypted = envelopedCms.Encode();
    
                return Convert.ToBase64String(encrypted);
            }
        }
    }
    

    Output

    PS C:\DEV\PfxTest> dotnet run
    Hello to PfxTest!
    MIICBgYJKoZIhvcNAQcDoIIB9zCCAfMCAQAxggGuMIIBqgIBADBjMFcxCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRlbi1Xw7xydHRlbWJlcmcxDTALBgNVBAoTBFRlc3QxDTALBgNVBAsTBFRlc3QxDTALBgNVBAMTBFRlc3QCCHmuh+2/frVqMDwGCSqGSIb3DQEBBzAvoA8wDQYJYIZIAWUDBAIDBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIDBQAEggEAfHlhUeK6xv7jPZzE6/VFFrAh6dnEMrxeOivkUWr5TtWiu4Bulmd7QuhEwSNXvzLUW8uBVxkqHCWwY4jIM4QX8deCEY29DrLNyFM7XWl8wzxM4VJlL6E20zCQskAh+zuXq1KqNV8blXX7D+VYBl8xobDA1Lwp8iBU+4haajq7L2/XTtQphYVQY+tHMBbNArqZAt9UiV1RQFy4rzY5vwRnaukousJEaw58OlfnuVbX9/30q1RCXGt+MMkkUV4H/273JPQ0z5MXNtiqRpJLjoQehvhyjeviaqk/6M+f4hXjF+sgIe2UCxpMS3yiQJNFY8Ahw7OcBaszaDzYh5vBrTHjNjA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBtJS1U3cF3DtpKH9JReigSgBCmbHnsRVXWmZVilQbGnBXj