【问题标题】:How to store the key used to encrypt files如何存储用于加密文件的密钥
【发布时间】:2012-01-16 13:10:21
【问题描述】:

我正在使用一个应用程序将文件备份到“云”:) 我想在存储文件之前对其进行加密。我已经介绍了那部分,但是由于此应用程序将监视文件夹以进行更改并上传更改的文件,因此我需要存储用于加密文件的密钥。这个想法是用户提供密码并生成密钥。

目前我正在使用 .NET Framework 进行加密。我正在使用 RijndaelManaged 类来加密/解密,并使用 PasswordDeriveBytes 类来获取密钥。

但是我应该如何保存用于加密文件的密钥?我还希望程序以 Windows 启动,而不需要让用户再次输入密码。

【问题讨论】:

标签: c# encryption cryptography aes rijndael


【解决方案1】:

我建议避免使用非对称加密来加密您的文件。非对称加密(在计算上)比同等强度的对称加密算法要昂贵得多。对于加密大文件,我建议任何时候都使用 AES over RSA。

至于您的问题 - Gaurav 提到的数据保护 API (DPAPI) 是您在 Windows 上的最佳选择。 How to: Use Data Protection

DPAPI 提供ProtectedMemoryProtectedData。前者允许您保护内存中的秘密,后者为持久保存到磁盘的秘密提供保护。 API 为您处理加密和解密,并且(取决于指定的范围)将保护您的数据不被其他用户或其他机器访问/解密。

要在您的场景中使用 DPAPI,我建议获取用户密码,生成对称加密密钥(例如 PasswordDeriveBytes),使用 DPAPI 存储该密钥并限制对当前用户的访问。

您的应用程序可以使用该密钥来加密所有上传。您的应用程序无需重新提示用户即可获取密钥,并且用户可以在新系统上重新生成密钥。

一个缺点是同样由同一用户执行的恶意应用程序可能会获得密钥。为了防止这种情况,必须在ProtectUnprotect 中提供额外的熵(实际上是盐)。然而,实现这一点可能会偏离您的目标 - 因为现在您需要提示用户输入一些看起来很像密码的东西。

另外:有趣的阅读:

您还可能会发现 Backblaze 的这篇文章很有趣。虽然他们没有解释他们如何支持您的方案(云提供商无法解密的加密上传 - 只有他们提供这样的服务): http://blog.backblaze.com/2008/11/12/how-to-make-strong-encryption-easy-to-use/

免责声明:我是一名满意的 Backblaze 客户,但与他们的服务没有任何关系。

PS:请务必花时间标记可接受的答案。社区会奖励你。

【讨论】:

  • 谢谢Tails,非常详尽的回答。经过几次测试,这似乎完全符合我的需要:)
  • 这个答案的一个很好的提示是,如果应用程序用户更改他/她的窗口,受保护的数据(这里是密钥)将没有用,所以如果数据非常重要并且可能会更改窗口,最好使用普通加密方法保留密钥,以便能够在这种情况下对其进行解密(例如,您可以为密钥 enc/dec 算法提供恒定密码)。
【解决方案2】:

我建议您像我描述的here 那样使用非对称加密。这将允许您只有一个私钥来保护(和备份),即使每个文件都将使用不同的对称密钥进行加密。

您还可以让 Windows(实际上是 CryptoAPI)保护使用 CspParameters(和正确的标志)和 RSACryptoServiceProvider 的密钥。根据您的标志,您可以让 登录 用户使用密钥(因此它与用户登录密码一样安全)。

【讨论】:

    【解决方案3】:

    DPAPI 旨在解决这一挑战。

    【讨论】:

      【解决方案4】:

      我同意 DPAPI 的建议。下面是一些代码来演示如何使用 ProtectedData 类。这与您的确切情况并不完全相关,但您可以推断。

      byte[] GetEncryptionKey()
      {
          var path = Path.Combine(
              Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
              AppDomain.CurrentDomain.FriendlyName,
              "nothing interesting... move along",
              "top secret encryption key");
      
          Debug.WriteLine("Encryption Key File: " + path);
      
          var file = new FileInfo(path);
          if (!file.Directory.Exists)
              file.Directory.Create();
      
          // determine if current user of machine
          // or any user of machine can decrypt the key
          var scope = DataProtectionScope.CurrentUser;
      
          // make it a bit tougher to decrypt 
          var entropy = Encoding.UTF8.GetBytes("correct horse battery staple :)");
      
          if (file.Exists)
          {
              return ProtectedData.Unprotect(
                  File.ReadAllBytes(path), entropy, scope);       
          }
      
          // generate key
          byte[] key;
          using(var rng = RNGCryptoServiceProvider.Create())
              key = rng.GetBytes(1024);
      
          // encrypt the key
          var encrypted = ProtectedData.Protect(key, entropy, scope);
      
          // save for later use   
          File.WriteAllBytes(path, encrypted);
      
          return key;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多