凭证存储最佳实践

我正在编写Windows服务,需要进行经过身份validation的Web请求。 该服务不会在用于发出请求的凭据的所有权下运行; 这意味着我需要以某种方式存储请求的凭据。

这里的最佳做法是什么? 凭证需要存储在App.config(或模拟)中; 我宁愿没有用明文挂掉密码。 由于密码经常更改,因此无法在密码中构建或以其他方式烘焙二进制文件。

同样的问题适用于Powershell。 我需要进行经过身份validation的请求,但我不希望脚本以纯文本格式包含用于请求的凭据。

不能归功于答案:但这里有一篇名为“在.NET App Config中加密密码”的博客文章,其中包含完整代码。

http://weblogs.asp.net/jgalloway/archive/2008/04/13/encrypting-passwords-in-a-net-app-config-file.aspx

对于像这样的东西,我总是参考Keith Brown的“Windows开发人员Windows安全指南”一书。

完整文本在http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook.HomePage上在线

您想要的特定部分(存储秘密)位于http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook/HowToStoreSecretsOnAMachine.html

选项#1 :使用ProtectSection()方法加密App.config中Web.config文件的部分。 这适用于Web和桌面应用程序以及依赖于使用加密部分复制Web.config文件的Web场。

深入介绍MSDN教程,包括使用RSA提供程序:

  • 使用受保护的配置加密配置信息 :

例:

 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); } 

使用DPAPI提供程序的旧方法:

  • 如何:使用DPAPI加密ASP.NET 2.0中的配置节

要加密:

 aspnet_regiis -pe "connectionStrings" -app "/SampleApplication" -prov "RsaProtectedConfigurationProvider" 

要解密:

 aspnet_regiis -pd "connectionStrings" -app "/SampleApplication" 
  • 加密/解密命令参考

未加密的部分:

      

加密部分:

         RSA Key   RXO/zmmy3sR0iOJoF4ooxkFxwelVYpT0riwP2mYpR3FU+r6BPfvsqb384pohivkyNY7Dm4lPgR2bE9F7k6TblLVJFvnQu7p7d/yjnhzgHwWKMqb0M0t0Y8DOwogkDDXFxs1UxIhtknc+2a7UGtGh6Di3N572qxdfmGfQc7ZbwNE=      KMNKBuV9nOid8pUvdNLY5I8R7BaEGncjkwYgshW8ClKjrXSM7zeIRmAy/cTaniu8Rfk92KVkEK83+UlQd+GQ6pycO3eM8DTM5kCyLcEiJa5XUAQv4KITBNBN6fBXsWrGuEyUDWZYm6Eijl8DqRDb11i+StkBLlHPyyhbnCAsXdz5CaqVuG0obEy2xmnGQ6G3Mzr74j4ifxnyvRq7levA2sBR4lhE5M80Cd5yKEJktcPWZYM99TmyO3KYjtmRW/Ws/XO3z9z1b1KohE5Ok/YX1YV0+Uk4/yuZo0Bjk+rErG505YMfRVtxSJ4ee418ZMfp4vOaqzKrSkHPie3zIR7SuVUeYPFZbcV65BKCUlT4EtPLgi8CHu8bMBQkdWxOnQEIBeY+TerAee/SiBCrA8M/n9bpLlRJkUb+URiGLoaj+XHym//fmCclAcveKlba6vKrcbqhEjsnY2F522yaTHcc1+wXUWqif7rSIPhc0+MT1hB1SZjd8dmPgtZUyzcL51DoChy+hZ4vLzE=      

选项#1a您可以将此加密移动到您的应用中,而不是使用aspnet_regiis执行加密。 它只检测您需要保护的部分是否加密,如果不加密,则会加密它们。 在开发过程中您需要一个选项,以避免在生产之前运行此代码。

  • 例子

选项#2加密配置文件中的字符串,并使用SecureString()临时存储解密的字符串。 根据您使用的字符串API是否支持SecureString,这可能会或可能不会为您提供更多的攻击面里程。

  • 例子