I've been tasked with signing some data with the C# RSACryptoServiceProvider.SignData() Method. In order to generate the public and private key i've used the RSACryptoServiceProvider and passed a keycontainername in order to store the keys safely.
When i run the MSDN example to generate a set of public/private keys on my machine with the fixed keycontainername, the expected public / private keys are generated every time the same.
This will work fine on a single server environment, however, we are operating on an elastic environment where the servers are load balanced. If i encrypt the data with a private key on any one single machine and store this data in through the RSACryptoServiceProvider the data will only exist at the machine level. Each machine will use a different key to sign the data and the user of the public key won't be able to verify the signature.
Is there any way i can store the key safely in a distributed environment?
Thanks
There are two that come to mind.
The first is use X509 certificates that contain the private key. You can use the X509Certificate2 class to get an RSACryptoServiceProvider instance that has the private key. The certificate and private key itself would be kept in the Windows certificate store. You can then limit access to the private key through the certificate store to certain accounts. You would then just install the certificate on each machine / AMI that needs it.
Your other option is to use an Hardware Security Module. AWS has a service called CloudHSM that allows you to use a network HSM inside of a VPC (I don't know how well that will work with Elastic Bean Stalk). The HSM vendor, SafeNet IIRC, allows installing a CSP that points to the HSM. You'd then give the RSACryptoServiceProvider a instance of CspParameters that accepts the container and CSP name.
The HSM solution is the most secure, albeit more complex and expensive.
Related
I was just wondering about the following scenario: I have a certificate containing a private key in my Windows certificate store and would like to use it for signing stuff. Is it possible to let Windows do this, so that I do not need to make the private key accessible (like in TPM)? In case I really must make the private key accessible, how can I protect it from being accessed by other (potentially malicious) applications? Having a separate user account?
Thanks
Currently, I have developed two desktop applications, one is C++ another is C#. The certificates have been stored in eToken and marked as non-exportable
I would like to get the private key from eToken through PKCS#11 library and transform or copy the private key into memory stream or byte array structures, and then pass the key object to the third party cryptography API (BC/OpenSSL) for data encryption/decryption.
How can I view or get the private key from the eToken which marked as non-exportable?
You can't extract a private key marked as non-exportable from your token and that's why is used. If you need to perform some operation you must send data to the token and then retrieve the result.
At least you could read the certificate inside the USB using the X509Store class (C#)
I had a look on
configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
but I had two questions:
Is there a way to encrypt config file with a key, because any one can decrypt my file if he knows this method, right?
Does the decryption done automatically when retrieving the connection string at run-time? (in any class, or in data-sets)?
thanks
Yes, Encrypting config file is common. DPAPI way uses symmetric key and therefore, if someone gets the key, he can decrypt.
In my case I used an RSA asymmetric key. That way encryption with public key is performed. Decryption can be performed only with private key protected and held by server in SQL database. On application side, users and application don't need the decrypted secret but need to stay encrypted. Simply, public key is to encrypt and private key is to decrypt. And nobody can easily get the private key.
Furthermore, when it comes to cloud platform like Microsoft Azure, we have to use certificate way which is of also RSA.
My case took almost 1 month to understand the complexity. I completed this task just recently.
The decryption is performed automatically by indicating the thumbprint of private key in the config file.
I want to allow users on my site to create an asymmetric private & public key so they can:
upload the public key to the site so my web application can encrypt
files they upload
download files and decrypt them using a local
application and the private key
My issue is that if the users machine dies then they will most likely loose their private key.
My concept is that the application the users download to pull the files from the site will also allow them to generate the keys for use on the site.
So my question is, Is it possible to create an asymmetric private/public key pair based on a passphrase? This would allow the user to regenerate the private key if required.
One way to do exactly what you are asking is:
Define a security level N, the larger the more secure but slower this process will be.
Generate a "salt" and associate it with the user's id.
Since RSA key generation requires a secure random number generator, use the user's password and salt with PBKDF2, starting at iteration N, to generate secure random data.
This process should deterministically generate a public/private RSA key pair. However, the reasons not to do this are:
It was cooked up by me and, AFAIK, this post is the first time this process will be publicly vetted.
It is not known to me if PBKDF2 actually works as a secure random number generator for use with RSA.
It may or may not be true the PBKDF2 is guaranteed to generate a data from which a public/private RSA key pair will originate.
In practice, while this does work, it takes a very long time and the time it takes is based on the user's password, which is a user experience and security exposure point that needs considered.
A better way to accomplish what you are trying to do is:
Define a security level N, the larger the more secure but slower this process will be.
Generate a "salt" and associate it with the user's id.
Generate an RSA public / private key pair.
Iterate PBKDF2 N times to create a symmetric key based on the user's password and salt.
Use a symmetric encryption algorithm to encrypt the private key.
Upload the unencrypted public key and encrypted private key to the server.
This is better because:
All processes listed above are, AFAIK, standard and vetted.
Generation of public / private keys (time consuming) only occurs once while setting up the user's account.
Accessing the keys always occurs in a fixed amount of time.
This solves your problem:
Since the server only has the encrypted private key it cannot decrypt the user's data.
If the client machine dies the server can re-issue the private key.
Of course there are the obvious warnings like if the user forgets their password all their data is locked until public knowledge on how to crack RSA is available or a billion years of current computing power is put to the task of breaking their password ;-) (depending on N and key size of course). Also, the salt is important to prevent dictionary attacks.
What the fields are for your algorithm (e.g. RSA http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsaparameters.aspx) are more or less up to you. You could easily create an algorithm to generate D and P from some string (calculating the other RSA fields from those). I'd really recommend you wouldn't pick one from an answer on StackOverflow though (that would simply give someone who wanted to get at your data something easy to try).
The reason algorithms like RSA are hard to break is the amount of effort that goes into reverse engineering the private/public key based on the encrypted data. If you introduce a "shortcut" like a reproducible generation algorithm based on a passphrase, the security of your system now depends on how well the passphrase is kept secret, not the encryption algorithm itself.
The same is true for the private key; which is why many organizations don't store the private key on hard drives and store them on secure external devices protected by a password or some biometric information.
I'd recommend you do not generate keys from a passphrase and simply use recommended practices for storing and protecting your private key.
I am using the RSACryptoServiceProvider and C#. I have a web server (A) that will be encrypting data and storing it in a database. I have another server (B) that will be reading the encrypted data and decrypting it. The private key will only ever live on server B.
I would like to limit private key access to my application and a very short list of domain users.
What is the best way to store the key so that it is safe from compromise by an unauthorized person?
You can use Windows RSA Key containers to store the key. The key can be installed / created by the aspnet_regiis.exe tool that ships with the .NET framework.
Here is a walkthrough.
The two options to look out for are:
-pi (installs a key to the RSA container)
-pa (managements permissions for the key)