Click here to Skip to main content
Click here to Skip to main content
Articles » Languages » XML » Web Services » Downloads
 
Add your own
alternative version
Go to top

Central Key Management

, 8 Mar 2006
A central key manager for multiple web server clients in a web farm.
centralkeymanager_src.zip
Core
Cryptography
WrappedData.xsx
Properties
KeyManager
Properties
TestClient
Properties
Settings.settings
Web References
KeyManager
Reference.map
Service.disco
Service.wsdl
SessionKeyInfo.datasource
using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace Core.Cryptography
{
    public static class CryptHelper
    {
        private static readonly string _storageSlot = "__KeyManagerAsymmetricKeys";
        private static readonly object _storageLock = new object();

        static CryptHelper()
        {
            Dictionary<string, RSACryptoServiceProvider> list = new Dictionary<string, RSACryptoServiceProvider>();
            AppDomain.CurrentDomain.SetData(_storageSlot, list);
        }

        public static WrappedData AsymmetricEncrypt(RSACryptoServiceProvider csp, string plainText)
        {
            // Generate the temporary Session Key
            RijndaelManaged symmetric = new RijndaelManaged();
            symmetric.GenerateIV();
            symmetric.GenerateKey();

            // encrypt the data using the temporary session Key
            byte[] inputBuffer = Encoding.Unicode.GetBytes(plainText);
            byte[] encryptedData = symmetric.CreateEncryptor().TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);

            // encrypt the session key using the Asymmetric CSP
            byte[] encryptedKeyData = csp.Encrypt(symmetric.Key, true);

            // Create the wrapped data structure
            WrappedData wrappedData = new WrappedData();
            wrappedData.EncryptedData = Convert.ToBase64String(encryptedData);
            wrappedData.EncryptedKey = Convert.ToBase64String(encryptedKeyData);
            wrappedData.IV = Convert.ToBase64String(symmetric.IV);
            return wrappedData;
        }

        public static WrappedData AsymmetricEncrypt(string certificateThumb, string plainText)
        {
            RSACryptoServiceProvider csp = GetAsymmetricKey(certificateThumb, false);
            WrappedData wrappedData = AsymmetricEncrypt(csp, plainText);
            wrappedData.Certificate = certificateThumb;
            return wrappedData;

        }

        public static string AsymmetricDecrypt(WrappedData wrappedData)
        {
            // Get the Asymmetric key that matches the wrapped data certificate
            RSACryptoServiceProvider csp = GetAsymmetricKey(wrappedData.Certificate, true);

            // decrypt the temporary Symmetric Key
            byte[] clearKey = csp.Decrypt(Convert.FromBase64String(wrappedData.EncryptedKey), true);
            byte[] iv = Convert.FromBase64String(wrappedData.IV);
            byte[] encryptedData = Convert.FromBase64String(wrappedData.EncryptedData);

            // Setup the tetm
            RijndaelManaged symmetric = new RijndaelManaged();
            byte[] clearData = symmetric.CreateDecryptor(clearKey, iv).TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            return Encoding.Unicode.GetString(clearData);
        }

        private static RSACryptoServiceProvider GetAsymmetricKey(string thumb, bool includePrivate )
        {
            Dictionary<string, RSACryptoServiceProvider> list =
                AppDomain.CurrentDomain.GetData(_storageSlot) as Dictionary<string, RSACryptoServiceProvider>;

            if (list == null)
            {
                throw new ApplicationException("Invalid State: The key storage is not setup");
            }

            RSACryptoServiceProvider csp = null;
            if (list.ContainsKey(thumb) == false)
            {
                lock (_storageLock)
                {
                    if (csp == null)
                    {
                        csp = LoadKey(thumb, includePrivate);
                        list[thumb] = csp;
                    }
                }
            }
            else
            {
                csp = list[thumb];
            }

            return csp;

        }

        public static string CreateSessionKeyString()
        {
            RijndaelManaged csp = new RijndaelManaged();
            csp.GenerateIV();
            csp.GenerateKey();

            String xml = string.Format( 
                "<RijndaelManagedKey format='B64'><Key>{0}</Key><IV>{1}</IV></RijndaelManagedKey>", 
                System.Convert.ToBase64String( csp.Key ), 
                System.Convert.ToBase64String( csp.IV ) );

            return xml;
        }

        public static RijndaelManaged GetSessionKey(string sessionKeyString)
        {
            System.Xml.XmlDocument document = new System.Xml.XmlDocument();
            document.LoadXml(sessionKeyString);

            System.Xml.XmlNode node = document.SelectSingleNode("/RijndaelManagedKey");
            System.Xml.XmlAttribute attribute = node.Attributes["format"];
            if (attribute != null && attribute.Value != "B64")
                throw new ApplicationException("Unknown key format " + attribute.Value);

            byte[] key = null;
            byte[] iv = null;

            foreach (System.Xml.XmlNode child in node.ChildNodes)
            {
                switch (child.Name)
                {
                    case "Key":
                        key = Convert.FromBase64String(child.InnerText);
                        break;

                    case "IV" :
                        iv = Convert.FromBase64String(child.InnerText);
                        break;
                }
            }

            RijndaelManaged csp = new RijndaelManaged();
            csp.Key = key;
            csp.IV = iv;

            return csp;
        }
        
        private static RSACryptoServiceProvider LoadKey(string thumb, bool includePrivate)
        {
            System.Security.Cryptography.X509Certificates.X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);

            string certThumb = thumb.Replace(" ", string.Empty);

            foreach (X509Certificate2 certificate in store.Certificates)
            {
                if (certThumb.ToLower() == certificate.Thumbprint.ToLower())
                {
                    RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
                    if (includePrivate == true)
                    {

                        if (certificate.HasPrivateKey == false)
                            throw new ArgumentException("Private key for specified key is not available");

                        csp.FromXmlString(certificate.PrivateKey.ToXmlString(true));

                    }
                    else
                    {
                        csp.FromXmlString(certificate.PublicKey.Key.ToXmlString(false));
                    }

                    return csp;
                }
            }

            throw new ApplicationException("Specified certificate was not found on this machine");
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Brian Bayless

United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 8 Mar 2006
Article Copyright 2006 by Brian Bayless
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid