none
Key or Password Vault?

    Question

  • I thought Windows had a "key vault" where passwords, symmetric keys, and other crypto components could be stored and accessed only by the user who inserted the item.  A search online suggests there are several commercial products that provide this capability, but I'm not seeing anything as part of Windows itself.

    The closest thing I see is the Windows certificate store, but to my knowledge the certificate store only holds asymmetric keys - and does not restrict access based on the user's account.

    So my question is: if such a "crypto vault" exists in Windows, what is it and what namespace in .net helps me gain access to it?  Can the certificate store be made to be user-sensitive and store other crypto keys (passwords, symmetric keys) besides assymetric keys?

    If there is no such thing as I'm describing, then my next interest would be to store a password in a user-specific location, that only that user or an administrator can access.  For example, I know that Vista has "Known Folder" IDs such as "FOLDERID_LocalApplications Data" that identify what might be a location I could work with (and the CSIDL entries are now deprecated).  But what does the BCL offer to access such "known folder" IDs and locations? 


    -Brent Arias
    • Edited by Brent Arias Friday, January 22, 2010 9:24 PM added more questions
    Friday, January 22, 2010 9:07 PM

Answers

  • Well, I don't know anything similar for symmetric algorithms, but it all depends on the needs you have for your application.
    Usually the keys that are stored are asymmetric pairs, not symmetric. Symmetric keys are most commonly created on the fly.

    If you need to store passwords locally, asymmetric keys will do it better. The only downside is that asymmetric encryption requires more computation, so it is not suited for long transmission. For this, symmetric keys are generated on the fly, using asymmetric ones to be sure no-one reads them.

    I'll make an example here.

    If you need to keep secret a communication
    from you to, let's say, Bill, this is one of the best approaches:

    1) You generate your RSA key pair, keep them in a storage. The storage name is the password only you know. You give away freely your public key to Bill. Bill does the same locally, and gives you his public key.

    2) You generate a symmetric key with AES. You can generate a new symmetric key every time, as you will see, no need to store it.

    3) You encrypt the symmetric key with Bill's public key. Now, only Bill can decrypt the message (since he's the only one having his private key).

    4) You transmit encrypted symmetric key to Bill. You are sure no other can read the message (to be sure no-one ALTERS the message, though, you have to sign it digitally --use DSA for this).

    5) Bill decrypts your message, now you both have the symmetric key to exchange data. You communicate as long as you want, and when your session is finished you throw away your key. Next time you will generate another one the same way.

    And that's it.


    If you only want to store some settings and want to have them safe from others' eyes , you can always entrust everything to the framework, storing your data in application configuration file and then using SectionInformation.ProtectSection() method. You can get a SectionInformation instance from a ConfigurationSection  object. The framework does all the encryption for you. When you need your data back, all you need to do is to call SectionInformation.UnprotectSection() and you are there.

    Now, I hope this covers your needs. I think your original question has been answered, but if you have other questions definitely post them.

    Best regards,
    -- Alessio Massuoli
    • Marked as answer by Brent Arias Saturday, January 23, 2010 1:25 AM
    Friday, January 22, 2010 11:49 PM

All replies

  • Such storage does exist, as far as I know only for asymmetric encryption algorithms (RSACryptoServiceProvider and DSACryptoServiceProvider classes).

    It's a storage in the CryptoServiceProvider (CSP), and handles storage for keys you want to reuse. You can't handle it directly, instead you access and retrieve key data by referring to a KeyContainerName . The CSP stores keys in local machine, period. To export your keys elsewhere, you have to export them in XML format.

    Now I'm covering both arguments.

    To Store asymmetric key pairs in CSP:

    //First, I create the CSP Parameters object where my key pair will be stored
    CspParameters myParameters = new CspParameters();
    
    //Now, I specify KeyContainerName, to be able to retrieve my keys later
    myParameters.KeyContainerName = "fooKeys";
    
    //I'm ready to create my CSP class, specifying to use parameters I provided
    
    RSACryptoServiceProvider crypto = new RSACryptoServiceProvider(myParameters);
    
    /**
    * NOTE:
    * The first time I run this code, crypto is instantiated with an
    * auto-generated key pair.
    * If I now instruct the RSA CSP instance to store key,
    * next time I run code using CspParameters with the same KeyContainerName,
    * the code will retrieve automatically ALWAYS THE SAME KEY!
    **/
    
    //Now I'm instructing my RSA CSP instance to store this key in CSP, under the container name of "fooKeys" (specified in myParameters)
    crypto.PersistKeyInCsp = true;
    
    //...

    Until you keep using the same KeyContainerName and you keep instructing your CSP instance to persist keys in CSP, your key will be automatically stored and retrieved for you every time you run the code. This storage is not assembly-related, so you can access your keys from every assembly you run, provided you enter the correct keyName.

    Like I said, your key pair is stored locally. To export it, you must call ExportParameters(bool) or ToXmlString(bool) .
    Both methods accept a boolean as parameters that, if set to true , allows the method to export both private and public keys, when false instructs the method to export public key only .

    ExportParameters() returns an RSAParameters structure that exposes the private-public keys as byte[] members. The most significant members are (example):

    //by calling ExportParameters(true), I'm exporting both public and private key
    RSAParameters myKey = crypto.ExportParameters(true);
    
    /** now myKey contains:
    * myKey.D is the private key
    * myKey.Modulus is first part of public key
    * myKey.Exponent is second part of public key
    * (other properties are not relevant for retrieving key pair)
    * --ALL MEMBERS ARE byte[] --
    **/
    On the other hand, ToXmlString() returns a really handy XML string ready to be written, sent, transported and parsed.

    I think this is all, best regards,
    -- Alessio Massuoli
    • Edited by Alessio Massuoli Friday, January 22, 2010 11:00 PM (I wrote "on the other and", corrected)
    Friday, January 22, 2010 10:58 PM
  • Wow, that is good info!  But it does have the limitation that any user account can access the key - if they know the key container name.  That doesn't seem secure enough.  Also, you are showing that it stores asymmetric keys - but I need it to store symmetric keys such as AES (or even a user selected password).
    -Brent Arias
    Friday, January 22, 2010 11:24 PM
  • Well, I don't know anything similar for symmetric algorithms, but it all depends on the needs you have for your application.
    Usually the keys that are stored are asymmetric pairs, not symmetric. Symmetric keys are most commonly created on the fly.

    If you need to store passwords locally, asymmetric keys will do it better. The only downside is that asymmetric encryption requires more computation, so it is not suited for long transmission. For this, symmetric keys are generated on the fly, using asymmetric ones to be sure no-one reads them.

    I'll make an example here.

    If you need to keep secret a communication
    from you to, let's say, Bill, this is one of the best approaches:

    1) You generate your RSA key pair, keep them in a storage. The storage name is the password only you know. You give away freely your public key to Bill. Bill does the same locally, and gives you his public key.

    2) You generate a symmetric key with AES. You can generate a new symmetric key every time, as you will see, no need to store it.

    3) You encrypt the symmetric key with Bill's public key. Now, only Bill can decrypt the message (since he's the only one having his private key).

    4) You transmit encrypted symmetric key to Bill. You are sure no other can read the message (to be sure no-one ALTERS the message, though, you have to sign it digitally --use DSA for this).

    5) Bill decrypts your message, now you both have the symmetric key to exchange data. You communicate as long as you want, and when your session is finished you throw away your key. Next time you will generate another one the same way.

    And that's it.


    If you only want to store some settings and want to have them safe from others' eyes , you can always entrust everything to the framework, storing your data in application configuration file and then using SectionInformation.ProtectSection() method. You can get a SectionInformation instance from a ConfigurationSection  object. The framework does all the encryption for you. When you need your data back, all you need to do is to call SectionInformation.UnprotectSection() and you are there.

    Now, I hope this covers your needs. I think your original question has been answered, but if you have other questions definitely post them.

    Best regards,
    -- Alessio Massuoli
    • Marked as answer by Brent Arias Saturday, January 23, 2010 1:25 AM
    Friday, January 22, 2010 11:49 PM
  • If you only want to store some settings and want to have them safe from others' eyes , you can always entrust everything to the framework, storing your data in application configuration file and then using SectionInformation.ProtectSection() method. You can get a SectionInformation instance from a ConfigurationSection  object. The framework does all the encryption for you. When you need your data back, all you need to do is to call SectionInformation.UnprotectSection() and you are there.


    -- Alessio Massuoli

    I think your comment above covers my needs, so I will mark it as the answer.
    -Brent Arias
    Saturday, January 23, 2010 1:25 AM