How to encrypt data so that many users can decrypt it?
I have the need to secure the login credentials to a privileged account such tha开发者_开发技巧t they can be accessed by a script of some kind under the proper conditions.
The simple answer could be to encrypt them in the app.config, but then they can be accessed by any user and only on the machine it was encrypted on. I need to distribute this config out via Subversion so that the source will be compiled on any available build server and the build script can access the encrypted data. The build users will be known (could be on different domains), but the machine won't be the same every time.
Can certificates be used? Without a CA? Another method?
Would prefer to do this in C#, so that it can be coupled into an MSBuild task. I do not want to write the decrypted data to the filesystem for security.
Thoughts?
Asymetric encryption is what you need.
Here is a link to MSDN documentation for RSA algorithm which will work.
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx
This is the sample they provide at the bottom of the page.
static void Main()
{
try
{
//Create a UnicodeEncoder to convert between byte array and string.
UnicodeEncoding ByteConverter = new UnicodeEncoding();
//Create byte arrays to hold original, encrypted, and decrypted data.
byte[] dataToEncrypt = ByteConverter.GetBytes("Data to Encrypt");
byte[] encryptedData;
byte[] decryptedData;
//Create a new instance of RSACryptoServiceProvider to generate
//public and private key data.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Pass the data to ENCRYPT, the public key information
//(using RSACryptoServiceProvider.ExportParameters(false),
//and a boolean flag specifying no OAEP padding.
encryptedData = RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false), false);
//Pass the data to DECRYPT, the private key information
//(using RSACryptoServiceProvider.ExportParameters(true),
//and a boolean flag specifying no OAEP padding.
decryptedData = RSADecrypt(encryptedData, RSA.ExportParameters(true), false);
//Display the decrypted plaintext to the console.
Console.WriteLine("Decrypted plaintext: {0}", ByteConverter.GetString(decryptedData));
}
}
catch (ArgumentNullException)
{
//Catch this exception in case the encryption did
//not succeed.
Console.WriteLine("Encryption failed.");
}
}
static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
try
{
byte[] encryptedData;
//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Import the RSA Key information. This only needs
//toinclude the public key information.
RSA.ImportParameters(RSAKeyInfo);
//Encrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
}
return encryptedData;
}
//Catch and display a CryptographicException
//to the console.
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
}
static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
try
{
byte[] decryptedData;
//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Import the RSA Key information. This needs
//to include the private key information.
RSA.ImportParameters(RSAKeyInfo);
//Decrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
return decryptedData;
}
//Catch and display a CryptographicException
//to the console.
catch (CryptographicException e)
{
Console.WriteLine(e.ToString());
return null;
}
}
}
The step of being able to "distribute" a key/encrypted information and allowing certain users to access this regardless of machine is pretty much the same thing as DRM and they still haven't "solved" this problem :)
Anyway I was wondering if this solution may work for you guys?
- Setup an access list on the machine that the encrypted information resides and only allow build servers to access it.
- Now in regards of "users" accessing it, it seems to be implied that the same user will need access but via different build machine? If so then I'm thinking it may be possible to embedded the key to decrypt the encrypted login information in these user accounts that are supposed to have access to this. For example with windows, you have access management and can encrypt user account information.
So basically this leads me to suggest a double prong solution which is a white list of which machines that can access that information, and users who need to be able to run the script can have the key embedded into their profile?
精彩评论