问题
I'm writing a Windows service and need to make authenticated web requests. The service will not be running under the ownership of the credentials used to make the request; this implies that I need to store the credentials for the request in some way.
What are the best practices here? The credentials will need to be stored in App.config (or an analog); I'd rather not have the password hanging out in plain text. As passwords change frequently, building or otherwise baking in the password to the binary is not an option.
The same question applies for Powershell. I need to make authenticated requests, but I don't want the script to contain in a plain-text form the credentials used for the requests.
回答1:
Can't take the credit for the answer: But here's a blog post called "Encrypting Passwords in .NET App Config" With full code included.
http://weblogs.asp.net/jgalloway/archive/2008/04/13/encrypting-passwords-in-a-net-app-config-file.aspx
回答2:
I always refer to Keith Brown's "The .NET Developer's Guide to Windows Security" book for stuff like this.
The complete text is online at http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook.HomePage
The specific section you want (on storing secrets) is at http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook/HowToStoreSecretsOnAMachine.html
回答3:
Option #1: Encrypt sections in your App.config for Web.config file using the ProtectSection()
method. This is designed to work for Web and Desktop apps and also web farms that rely on replicating Web.config files with encrypted sections.
In depth MSDN tutorials covering use of RSA provider:
- Encrypting Configuration Information Using Protected Configuration:
Example:
static public void ProtectSection()
{
// Get the current configuration file.
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
// Get the section.
UrlsSection section =
(UrlsSection)config.GetSection("MyUrls");
// Protect (encrypt)the section.
section.SectionInformation.ProtectSection(
"RsaProtectedConfigurationProvider");
// Save the encrypted section.
section.SectionInformation.ForceSave = true;
config.Save(ConfigurationSaveMode.Full);
// Display decrypted configuration
// section. Note, the system
// uses the Rsa provider to decrypt
// the section transparently.
string sectionXml =
section.SectionInformation.GetRawXml();
Console.WriteLine("Decrypted section:");
Console.WriteLine(sectionXml);
}
Older approach using DPAPI provider:
- How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
To encrypt:
aspnet_regiis -pe "connectionStrings" -app "/SampleApplication" -prov "RsaProtectedConfigurationProvider"
To decrypt :
aspnet_regiis -pd "connectionStrings" -app "/SampleApplication"
- Encrypt/Decrypt command reference
Unencrypted Section:
<configuration>
<connectionStrings>
<add name="SampleSqlServer" connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;" />
</connectionStrings>
</configuration>
Encrypted Section:
<configuration>
<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>RXO/zmmy3sR0iOJoF4ooxkFxwelVYpT0riwP2mYpR3FU+r6BPfvsqb384pohivkyNY7Dm4lPgR2bE9F7k6TblLVJFvnQu7p7d/yjnhzgHwWKMqb0M0t0Y8DOwogkDDXFxs1UxIhtknc+2a7UGtGh6Di3N572qxdfmGfQc7ZbwNE=
</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>KMNKBuV9nOid8pUvdNLY5I8R7BaEGncjkwYgshW8ClKjrXSM7zeIRmAy/cTaniu8Rfk92KVkEK83+UlQd+GQ6pycO3eM8DTM5kCyLcEiJa5XUAQv4KITBNBN6fBXsWrGuEyUDWZYm6Eijl8DqRDb11i+StkBLlHPyyhbnCAsXdz5CaqVuG0obEy2xmnGQ6G3Mzr74j4ifxnyvRq7levA2sBR4lhE5M80Cd5yKEJktcPWZYM99TmyO3KYjtmRW/Ws/XO3z9z1b1KohE5Ok/YX1YV0+Uk4/yuZo0Bjk+rErG505YMfRVtxSJ4ee418ZMfp4vOaqzKrSkHPie3zIR7SuVUeYPFZbcV65BKCUlT4EtPLgi8CHu8bMBQkdWxOnQEIBeY+TerAee/SiBCrA8M/n9bpLlRJkUb+URiGLoaj+XHym//fmCclAcveKlba6vKrcbqhEjsnY2F522yaTHcc1+wXUWqif7rSIPhc0+MT1hB1SZjd8dmPgtZUyzcL51DoChy+hZ4vLzE=
</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
</configuration>
Option #1a Instead of performing the encryption using aspnet_regiis
, you can move this encryption into your app. It just detects if the sections you need to secure are encrypted and if not, it encrypts them. You'll need an option during development to avoid running this code until production.
- Examples
Option #2 Encrypt strings in your config file and use SecureString() to temporarily store the decrypted strings. This may or may not get you much attack surface mileage depending on whether the APIs you're using the strings for support SecureString.
- Examples
来源:https://stackoverflow.com/questions/508608/credential-storage-best-practices