Is there any way of specifying an alternative location for user or machine level key containers?

Discussion in 'ASP.NET 2.0' started by hypothetico, Jan 17, 2006.

  1. Without having to code a custom encryption key provider class like the TripleDES example app on MSDN...




    Is there any way of configuring or specifying an alternate user or machine level key container location?


    I have looked at the <configProtectedData> tag documentation, to see if there is such a thing as a keyfilepath or keycontainerpath or keylocation attribute. There is nothing mentioned and there is no such tag in the default configProtectedData tag of the machine.config file (see below.)


    Morover, the RsaProtectedConfigurationProviderclass in the class library does not expose any properties or methods that suggest a configuration of the key container location is possible (see below).


    Is there in fact any way of doing this without having to code a custom provider?





    <configProtectedData defaultProvider="RsaProtectedConfigurationProvider">


    <providers>


    <add name="RsaProtectedConfigurationProvider"


    type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"


    description="Uses RsaCryptoServiceProvider to encrypt and decrypt"


    keyContainerName="NetFrameworkConfigurationKey"


    cspProviderName=""


    useMachineContainer="true"


    useOAEP="false" />


    <add name="DataProtectionConfigurationProvider"


    type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"


    description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt"


    useMachineProtection="true"


    keyEntropy="" />


    </providers>


    </configProtectedData>


    .


    .


    .


    using System;


    using System.Collections.Specialized;


    using System.Security.Cryptography;


    using System.Xml;


    namespace System.Configuration


    {


    // Summary:


    // Provides a System.Configuration.ProtectedConfigurationProvider that uses


    // RSA encryption to encrypt and decrypt configuration data.


    public sealed class RsaProtectedConfigurationProvider : ProtectedConfigurationProvider


    {


    // Summary:


    // Initializes an instance of the System.Configuration.RSAProtectedConfigurationProvider


    // class using default settings.


    public RsaProtectedConfigurationProvider();


    // Summary:


    // Gets the name of the Windows cryptography API (crypto API) cryptographic


    // service provider (CSP).


    //


    // Returns:


    // The name of the CryptoAPI cryptographic service provider.


    public string CspProviderName { get; }


    //


    // Summary:


    // Gets the name of the key container.


    //


    // Returns:


    // The name of the key container.


    public string KeyContainerName { get; }


    //


    // Summary:


    // Gets the public key used by the provider.


    //


    // Returns:


    // An System.Security.Cryptography.RSAParameters object that contains the public


    // key used by the provider.


    public RSAParameters RsaPublicKey { get; }


    //


    // Summary:


    // Gets a Boolean value indicating whether the System.Configuration.RSAProtectedConfigurationProvider


    // is using the machine key container.


    //


    // Returns:


    // true if the System.Configuration.RSAProtectedConfigurationProvider is using


    // the machine key container; otherwise, false.


    public bool UseMachineContainer { get; }


    //


    // Summary:


    // Gets a value indicating whether the provider is using Optimal Asymmetric


    // Encryption Padding (OAEP) key exchange data.


    //


    // Returns:


    // true if the System.Configuration.RSAProtectedConfigurationProvider is using


    // Optimal Asymmetric Encryption Padding (OAEP) key exchange data; otherwise,


    // false.


    public bool UseOAEP { get; }


    // Summary:


    // Adds a key to the RSA key container.


    //


    // Parameters:


    // exportable:


    // true to indicate that the key is exportable; otherwise, false.


    //


    // keySize:


    // The size of the key to add.


    public void AddKey(int keySize, bool exportable);


    //


    // Summary:


    // Decrypts the XML node passed to it.


    //


    // Parameters:


    // encryptedNode:


    // The System.Xml.XmlNode to decrypt.


    public override XmlNode Decrypt(XmlNode encryptedNode);


    //


    // Summary:


    // Removes a key from the RSA key container.


    public void DeleteKey();


    //


    // Summary:


    // Encrypts the XML node passed to it.


    //


    // Parameters:


    // Node:


    // The System.Xml.XmlNode to encrypt.


    //


    // Returns:


    // An encrypted System.Xml.XmlNode object.


    public override XmlNode Encrypt(XmlNode node);


    //


    // Summary:


    // Exports an RSA key from the key container.


    //


    // Parameters:


    // xmlFileName:


    // The file name and path to export the key to.


    //


    // includePrivateParameters:


    // true to indicate that private parameters are exported; otherwise, false.


    //


    // Exceptions:


    // System.IO.DirectoryNotFoundException:


    // The specified path is invalid, such as being on an unmapped drive.


    //


    // System.ArgumentNullException:


    // path is null.


    //


    // System.Security.SecurityException:


    // The caller does not have the required permission.


    //


    // System.NotSupportedException:


    // path is in an invalid format.


    //


    // System.IO.IOException:


    // An error occurred while opening the file.


    //


    // System.ArgumentException:


    // path is a zero-length string, contains only white space, or contains one


    // or more invalid characters as defined by System.IO.Path.InvalidPathChars.


    //


    // System.IO.PathTooLongException:


    // The specified path, file name, or both exceed the system-defined maximum


    // length. For example, on Windows-based platforms, paths must be less than


    // 248 characters, and file names must be less than 260 characters.


    //


    // System.UnauthorizedAccessException:


    // path specified a file that is read-only.-or- This operation is not supported


    // on the current platform.-or- path specified a directory.-or- The caller does


    // not have the required permission.


    //


    // System.IO.FileNotFoundException:


    // The file specified in path was not found.


    public void ExportKey(string xmlFileName, bool includePrivateParameters);


    //


    // Summary:


    // Imports an RSA key into the key container.


    //


    // Parameters:


    // xmlFileName:


    // The file name and path to import the key from.


    //


    // exportable:


    // true to indicate that the key is exportable; otherwise, false.


    //


    // Exceptions:


    // System.IO.DirectoryNotFoundException:


    // The specified path is invalid, such as being on an unmapped drive.


    //


    // System.IO.FileNotFoundException:


    // The file specified in path was not found.


    //


    // System.UnauthorizedAccessException:


    // path specified a file that is write-only.-or- This operation is not supported


    // on the current platform.-or- path specified a directory.-or- The caller does


    // not have the required permission.


    //


    // System.NotSupportedException:


    // path is in an invalid format.


    //


    // System.IO.IOException:


    // An error occurred while opening the file.


    //


    // System.ArgumentException:


    // path is a zero-length string, contains only white space, or contains one


    // or more invalid characters as defined by System.IO.Path.InvalidPathChars.


    //


    // System.IO.PathTooLongException:


    // The specified path, file name, or both exceed the system-defined maximum


    // length. For example, on Windows-based platforms, paths must be less than


    // 248 characters, and file names must be less than 260 characters.


    //


    // System.ArgumentNullException:


    // path is null.


    public void ImportKey(string xmlFileName, bool exportable);


    //


    // Summary:


    // Initializes the provider with default settings.


    //


    // Parameters:


    // configurationValues:


    // A System.Collections.Specialized.NameValueCollection collection of values


    // to use when initializing the object.


    //


    // name:


    // The provider name to use for the object.


    public override void Initialize(string name, NameValueCollection configurationValues);


    }


    }
     
  2. I don't think there's any way to configure a different location for the machine key container. That property is just not available.

    DiscountASP.NET
    www.DiscountASP.NET
     
  3. I got the following reply from the Microsoft ASP.NET Security forum moderator:




    User containers won't work forASP.NET because we don't load the Windows user profile for the application's associated application pool. So machine level containers are the only workable solution. DPAPI wouldn't be the right choice though since everyone on the machine has access to the machine container.


    RSA would work - but your hoster would have to run your app(s) in a separate application pool running as a custom NT account. With this approach (if the hoster allowed it) you could import RSA keys into a machine level container on the hoster machine - but ACL it so only your app pool's NT account had read access to the specific RSA container. That way other app pool accounts would be unable to read the key from the container. You could then encrypt the config section on your own home machine (since it would have the same key pair), and the app pool on your web server would have access to the key container. However I can see where a hoster might not want to do all this - or maybe charge extra for the effort involved!


    Technically a custom protected configuration provider can be written to load configuration from any arbitrary location. You can write a "protected" configuration provider that implements the ProtectedConfigurationProvider base class. Then you can add the provider to configuration in the <configProtectedData /> section. Unless the hoster has locked down <configProtectedData /> you should be able to add your custom provider in your app's web.config.


    At runtime your "protected" connection strings section will be loaded using your provider. Take a look at the output of the existing protected configuration providers. You can basically rig up a similarsyntax for the <connectionStrings /> section that tells your custom provider what to do:


    <connectionStrings configProtectionProvider="YourCustomProvider">
    <EncryptedData>
    <!-- your custom Xmlgoes here -->
    </EncryptedData>
    </membership>





    Bruce


    See http://forums.asp.net/AddPost.aspx?PostID=1172637
     

Share This Page