Encryption 如何保护AesCryptoServiceProvider';是rgbKey吗?

Encryption 如何保护AesCryptoServiceProvider';是rgbKey吗?,encryption,key,protection,dpapi,aescryptoserviceprovider,Encryption,Key,Protection,Dpapi,Aescryptoserviceprovider,我们有一个表,用于保存用户/密码和一些其他数据。每个记录的密码字段都必须加密。我们决定使用AESCryptServiceProvider进行加密,并一次性手动创建rgbKey。然后对所有用户密码进行加密,并将记录插入表中,其中的密码字段使用rgbKey加密 我们在负载均衡器后面有几个服务器,每个服务器都应该读取这些记录并可以解密密码字段值。开始时,我们将base64StringFormat的rgbKey放入我们的dll(API)中,同样,所有服务器都将使用此API,并可以解密加密值 但是,在dl

我们有一个表,用于保存用户/密码和一些其他数据。每个记录的密码字段都必须加密。我们决定使用AESCryptServiceProvider进行加密,并一次性手动创建rgbKey。然后对所有用户密码进行加密,并将记录插入表中,其中的密码字段使用rgbKey加密

我们在负载均衡器后面有几个服务器,每个服务器都应该读取这些记录并可以解密密码字段值。开始时,我们将base64StringFormat的rgbKey放入我们的dll(API)中,同样,所有服务器都将使用此API,并可以解密加密值

但是,在dll文件中保留rgbKey是非常不安全的。我们讨论了是否将密钥保留在DPAPI中。在解密时,在我们的任何服务器上,我们都将从DPAPI获取密钥并成功解密加密值

我认为我可以在任何一台服务器上以当前用户模式生成一次受保护的密钥,然后将其保存在我们的公共dll中。每个使用公共dll的服务器,将此受保护的密钥(字节[])提供给具有相同用户的DPAPI,都可以获得不受保护的密钥值。但是,它仅在受保护的机器上工作,在其他机器上,它会给出错误:“密钥在指定状态下无效。”

我的问题是如何保护我的永久rgbKey,以便从所有机器访问它?看看下面类似的测试控制台应用程序,我的方法有什么问题? 我给出了测试控制台应用程序的示例代码:

首先,我在本地计算机上运行PDPAPI()函数:

    static void PDPAPI() {
        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
        byte[] rgbKey = encoding.GetBytes( "MyRgbKey" );
        byte[] protectedData = ProtectedData.Protect( rgbKey, null, DataProtectionScope.CurrentUser );
        string base64ProtectedData = Convert.ToBase64String( protectedData );
        Console.WriteLine( "base64ProtectedData:{0}", base64ProtectedData );            
    }
然后硬编码地将从上述执行中获得的base64ProtectedData值添加到我的UDPAPI()函数中,重新生成解决方案:

    static void UDPAPI() {
        string base64ProtectedData = "****";
        byte[] protectedData = Convert.FromBase64String( base64ProtectedData );
        byte[] unProtectedData = ProtectedData.Unprotect( protectedData, null, DataProtectionScope.CurrentUser );
        string base64unProtectedData = Convert.ToBase64String( unProtectedData );
        Console.WriteLine( "base64unProtectedData:{0}", base64unProtectedData );
    }            

现在,如果我在本地计算机上运行UDPAPI()函数,它会成功地解除数据保护,但是如果我将控制台应用程序迁移到任何其他服务器,并使用网络用户登录该服务器,控制台应用程序将给出错误“密钥在指定状态下无效”。

诚实地说,对于密码加密,如果使用单向散列,然后不使用密码的明文,只对用户输入进行散列并进行比较,则不会出现密钥存储问题。在C#中使用的典型对象是PBKDF2()。有关其他选项,请参见

密钥存储问题总是很难解决,DPAPI是一个相当不错的选择,它可以保护密钥不受同一台计算机上其他用户的攻击,并且比将密钥存储在DLL中要好得多,但是要了解它在做什么,它正在使用运行的任何windows用户的密码哈希进行加密(实际上,它还做了很多工作,从密码散列中进行密钥派生、轮换等),这就是为什么您不能直接在服务器上使用从本地计算机加密的数据。要使用DPAPI,您必须在每台服务器上分别加密密钥(这不是一件坏事)

最好不要硬编码您的密钥,不是因为它可以访问,而是因为它更容易在需要时更改,或者在不同的设置下更改。通常,如果没有专用硬件,您最多只能将密钥与数据分开。加密密钥会使事情变得更困难,但您需要仅仅添加另一个攻击者也必须访问的密钥,并没有理想的解决方案


如果您希望有一种简单的方法可以随时间更改密钥,我已经移植了,它具有旋转密钥所需的机制,这样您在加密新数据时仍然可以解密旧数据,但是它在密钥存储可访问性方面并没有提供任何更安全的功能。

jbtule,谢谢您的回复。我同意您对advanta的看法ge不希望对输入案例使用哈希,只需比较值。然而,在我的案例中,没有用户输入,但需要先前加密的解密值。似乎使用DPAPI,在每台服务器上分别加密主密钥是不可避免的。