如何存储用于加密文件的密钥

时间:2012-01-16 13:10:21

标签: c# encryption cryptography aes rijndael

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

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

但是我应该如何保留用于加密文件的密钥?我也希望程序从Windows开始,而不需要让用户再次输入密码。

4 个答案:

答案 0 :(得分:14)

我建议避免使用非对称加密来加密文件。与同等强度的对称加密算法相比,非对称加密明显更加昂贵(计算上)。对于加密大文件,我建议任何一天使用AES over RSA。

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

DPAPI提供ProtectedMemoryProtectedData。前者允许你保护内存中的秘密,后者可以保护持久存储到磁盘的秘密。 API负责加密&为您解密,并(取决于指定的范围)将保护您的数据不被其他用户或其他计算机访问/解密。

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

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

一个缺点是同一用户也执行的恶意应用程序可能会获得密钥。为了防止这种情况,必须在Protect&中提供额外的熵(实际上是盐)。 Unprotect。但是,实现这一点可能会偏离您的目标 - 因为现在您需要提示用户提供类似密码的内容。

另外:有趣的阅读:

你也可以从Backblaze找到这篇有趣的读物。虽然他们没有解释他们如何支持您的方案(云提供商无法破译的加密上传 - 只有他们提供此类服务): http://blog.backblaze.com/2008/11/12/how-to-make-strong-encryption-easy-to-use/

免责声明:我是一名满意的Backblaze客户,但与其服务无关。

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

答案 1 :(得分:4)

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

您还可以使用CspParameters(以及正确的标记)和RSACryptoServiceProvider让Windows(实际上是CryptoAPI)保护密钥。根据您的标记,您可以将密钥用于用户的已记录(因此它将作为安全作为用户登录密码)。

答案 2 :(得分:1)

DPAPI旨在解决这一挑战。

答案 3 :(得分:0)

我同意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;
}