【问题标题】:Using RsaProtectedConfigurationProvider to perform encryption on strings not in a config file使用 RsaProtectedConfigurationProvider 对不在配置文件中的字符串执行加密
【发布时间】:2015-07-14 18:24:44
【问题描述】:

我的组织要求使用位于我们生产服务器上的特定 System.Configuration.RsaProtectedConfigurationProvider 对敏感连接字符串进行加密。但是,我有一个将连接字符串存储在数据库中的应用程序,我想使用相同的密钥对这些字符串执行加密。

我最初的想法是创建一个包含对加密提供程序的引用的虚拟配置文件,加载一些文本并执行加密,而无需将其写回磁盘。然后我可以将密码/明文从 xml 中提取出来:

DummyConfig.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <configSections>
  <section name="DummySection" type="virutalConfig.DummySect, virutalConfig, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
 </configSections>
 <DummySection />
 <configProtectedData>
  <providers>
   <add name="MyProvider"
    type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,&#xD;&#xA; Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,&#xD;&#xA; processorArchitecture=MSIL"
    keyContainerName="MyKeys"
    useMachineContainer="true" />
  </providers>
 </configProtectedData>
</configuration>

程序.cs:

class Program
    {
        static void Main(string[] args)
        {
            var fileMap = new ExeConfigurationFileMap
            {
                ExeConfigFilename = @"c:\virtconfigtest\DummyConfig.config"
            };

            var config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            var sect = config.GetSection("DummySection") as DummySect;
            sect.Inf = "this is some plaintext!";
            sect.SectionInformation.ProtectSection("MyProvider");
            //sect.SectionInformation.ForceSave = true;
            //config.Save();

            if (sect.SectionInformation.IsProtected)
            {
                Console.WriteLine("Section is protected. Raw XML:");
                Console.WriteLine(sect.SectionInformation.GetRawXml());
            }
            else
            {
                Console.WriteLine("Section is not protected. Raw XML:");
                Console.WriteLine(sect.SectionInformation.GetRawXml());
            }

            Console.ReadLine();
        }
    }

    public class DummySect : ConfigurationSection
    {
        public DummySect() { }

        [ConfigurationProperty("inf")]
        public string Inf
        {
            get { return (string)this["inf"]; }
            set { this["inf"] = value; }
        }
    }

不幸的是,GetRawXml() 只返回明文,即使要得到它,似乎也必须将配置文件写回磁盘。

我可以通过将磁盘上的文件作为 xml 文档读取来得到我想要的,但我宁愿不必这样做。无论如何,整个计划都是相当粗暴的,即使没有在混合中添加磁盘写入。我是否必须从提供商处检索 RSA 密钥才能执行此操作?如果有,怎么做?

【问题讨论】:

    标签: c# .net encryption configuration-files


    【解决方案1】:

    经过一些研究和反复试验,我最终弄清楚了如何做到这一点。

    配置文件的加密部分如下所示:

     <DummySection configProtectionProvider="MyProvider">
      <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>RsMpDD/wJmmpN+Mme+qFuRVm2Ddk759hWM7HaeAnW7xpfkCoC4ko7vDBmqylzQ0QAFL2wuR8u8Bsf+4xwn++Ru/GsEaYrGrcDMYJTuWElyHuxnw+5umqexQJye2R5uL/91alFVNV41HnSPlwuA+pgk14yHSWIflIyKFmUTx58vU=</CipherValue>
         </CipherData>
        </EncryptedKey>
       </KeyInfo>
       <CipherData>
        <CipherValue>lQI7gyQZ2HIIQUdKsp73HrYcebbOiO4dCriwCt5avfVTcxPZEHzaCfV52k+triRwq64uGVCNRpGUe5PCVEfbWwrPHaNaFzRp</CipherValue>
       </CipherData>
      </EncryptedData>
     </DummySection> 
    

    第一个密文块是用 RSA 加密的三重 DES 密钥。可以从以下目录中的文件中获取密钥对:C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

    第二部分用这个 DES 密钥加密,并在前面加上一个 64 位初始化向量。令人沮丧的是,它是用方法填充的:ISO10126

    下面是解密代码:

            var cspParameters = new CspParameters()
            {
                 KeyContainerName = "MyKeys",
                 Flags = CspProviderFlags.UseMachineKeyStore
            }; //refers to a file in the machine keys directory
    
            var rsaKey = new RSACryptoServiceProvider(cspParameters);
            var t1 =
                Convert.FromBase64String(
                    "RsMpDD/wJmmpN+Mme+qFuRVm2Ddk759hWM7HaeAnW7xpfkCoC4ko7vDBmqylzQ0QAFL2wuR8u8Bsf+4xwn++Ru/GsEaYrGrcDMYJTuWElyHuxnw+5umqexQJye2R5uL/91alFVNV41HnSPlwuA+pgk14yHSWIflIyKFmUTx58vU=");
            var t2 =
                Convert.FromBase64String(
                    "lQI7gyQZ2HIIQUdKsp73HrYcebbOiO4dCriwCt5avfVTcxPZEHzaCfV52k+triRwq64uGVCNRpGUe5PCVEfbWwrPHaNaFzRp");
            var desKey = rsaKey.Decrypt(t1, false); //get the des key
            var iv = t2.Take(8).ToArray(); //get the initialization vector
            var ct = t2.Skip(8).ToArray(); //get the actual ciphertext
    
            var desEnc = new TripleDESCryptoServiceProvider()
            {
                Padding = PaddingMode.ISO10126
            };
    
            var plaintext = Encoding.Default.GetString(desEnc.CreateDecryptor(desKey, iv).TransformFinalBlock(ct, 0, ct.Length));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 2012-03-13
      • 2020-06-25
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多