Skip to main content

Use X509 certificate to encrypt and decrypt

1. To make a test certificate, use the makecert.exe tool
makecert -n "CN=My Company" -ss "MyCompany.com" -pe -sr LocalMachine -sky Exchange test.cer
Here the -sky Exchange parameter is very important, without this, the generated certificate can only be used for signing, but not for encrypting/decrypting.


2. Write C# code as following:
    public class CertificateSSO
    {
        private X509Certificate2 GetCertificate()
        {
            X509Store store = new X509Store("
MyCompany.com", StoreLocation.LocalMachine);
            store.Open(OpenFlags.OpenExistingOnly);
            X509Certificate2 cert = store.Certificates.Find(X509FindType.FindBySubjectName, "My Company", false)[0];
            store.Close();
            return cert;
        }

        public string Encrypt(string strPlainText)
        {
            X509Certificate2 cert = GetCertificate();
            using (RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PublicKey.Key)
            {
                return Convert.ToBase64String(provider.Encrypt(UTF8Encoding.UTF8.GetBytes(strPlainText), false));
            }
        }

        public string Decrypt(string strBase64CipherText)
        {
            X509Certificate2 cert = GetCertificate();
            using (RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey)
            {
                byte[] arrPlainText = provider.Decrypt(Convert.FromBase64String(strBase64CipherText), false);
                return UTF8Encoding.UTF8.GetString(arrPlainText, 0, arrPlainText.Length);
            }
        }

        public string Sign(string strTextToSign)
        {
            X509Certificate2 cert = GetCertificate();
            using (RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey)
            {
                return Convert.ToBase64String(provider.SignData(UTF8Encoding.UTF8.GetBytes(strTextToSign), new SHA1CryptoServiceProvider()));
            }
        }

        public bool VerifySignature(string strOriginalText, string strSignature)
        {
            X509Certificate2 cert = GetCertificate();
            using (RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey)
            {
                 return provider.VerifyData(UTF8Encoding.UTF8.GetBytes(strOriginalText), new SHA1CryptoServiceProvider(), Convert.FromBase64String(strSignature));
            }
        }


        public string ExportPublicKey()
        {
            X509Certificate2 cert = GetCertificate();


            // RawData is byte array holding ASN.1 encoded key
            return Convert.ToBase64String(cert.PublicKey.EncodedKeyValue.RawData);
        }

        public string EncryptWithPublicKey(string strPublicKey, string strPlainText)
        {
            //
"1.2.840.113549.1.1.1" is the id for RSA
            Oid oid = new Oid("1.2.840.113549.1.1.1");
            AsnEncodedData keyValue = new AsnEncodedData(Convert.FromBase64String(strPublicKey));
            AsnEncodedData keyParam = new AsnEncodedData(new byte[] { 05, 00 });    // 05, 00 sequence means NULL in ASN.1
            PublicKey pubKey = new PublicKey(oid, keyParam, keyValue);
            using (RSACryptoServiceProvider provider = (RSACryptoServiceProvider)pubKey.Key)
            {
                return Convert.ToBase64String(provider.Encrypt(UTF8Encoding.UTF8.GetBytes(strPlainText), false));
            }
        }
    }

3. How to remove certificate store from certificate snap-in:
To remove certificate with the corresponding certificate store, you have to export the certificate with checked "Delete the private key if export successful" option.

Comments