2013-04-05 134 views
1

我已经使用高级加密标准(AES)在将数据存储到数据库之前加密我的数据。 据我的理解,如果我更改算法的“共享秘密”部分,我必须相应地更新所有存储的数据。 有没有其他方式让我的管理员用户有机会更新密钥,而无需更新存储数据的大量数据?更改AES加密中的共享密钥

以下是我使用的加密代码:

public static string EncryptStringAES(string plainText, string sharedSecret) 
    { 
     if (string.IsNullOrEmpty(plainText)) 
      throw new ArgumentNullException("plainText"); 
     if (string.IsNullOrEmpty(sharedSecret)) 
      throw new ArgumentNullException("sharedSecret"); 

     string outStr = null;      // Encrypted string to return 
     RijndaelManaged aesAlg = null;    // RijndaelManaged object used to encrypt the data. 

     try 
     { 
      // generate the key from the shared secret and the salt 
      Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt); 

      // Create a RijndaelManaged object 
      aesAlg = new RijndaelManaged(); 
      aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); 

      // Create a decryptor to perform the stream transform. 
      ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 

      // Create the streams used for encryption. 
      using (MemoryStream msEncrypt = new MemoryStream()) 
      { 
       // prepend the IV 
       msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int)); 
       msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length); 
       using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
       { 
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
        { 
         //Write all data to the stream. 
         swEncrypt.Write(plainText); 
        } 
       } 
       outStr = Convert.ToBase64String(msEncrypt.ToArray()); 
      } 
     } 
     finally 
     { 
      // Clear the RijndaelManaged object. 
      if (aesAlg != null) 
       aesAlg.Clear(); 
     } 

     // Return the encrypted bytes from the memory stream. 
     return outStr; 
    } 

回答

1

如果你的数据是使用一个密钥(“键”),那么唯一的方法来改变密钥(加密,使得它可以用例如“密钥B”解密)将使用“密钥A”解密所有数据,然后使用“密钥B”对其重新加密。

我相信用于避免此问题的一般技术是使用强大的“主密钥”加密数据,然后使用用户密钥加密主密钥。因此,更改密码只需要使用旧密钥和新密钥(分别)对主密钥进行解密和重新加密,而数据本身保持不变。

您没有提及您实际使用的数据库,但可能值得注意的是,许多数据库服务器都支持自动数据加密,因此存储在磁盘上的数据是加密格式并且无法解密并且除非您是授权用户才能访问。

如果您正在使用的数据库服务器支持此功能,则值得进行调查。透明,您将不再需要担心在您的代码中手动加密/解密,并且它可能已经支持密钥更改以及数据恢复功能(如果您的用户忘记密码等)

+1

谢谢我做了一些研究,并在SQL Server中使用主密钥阅读了透明数据加密。我仍然不确定我能否在客户端更改主密钥。 – Afflatus 2013-04-05 08:18:59

1

我移植了Keyczar framework to C#,这两个密钥集都允许您旋转密钥(仅使用新密钥加密,仍旧使用旧密码解密),并为密钥集提供password encryption

创建密钥集:

:> KeyczarTool.exe create --location="path_to_keyset" --purpose="crypt" 
:> KeyczarTool.exe addkey --location="path_to_keyset" --status="primary" --size="256" --password 
Please enter password: 
Please re-enter password: 

加密:

Func<string> passwordCallback =()=> Console.ReadLine(); //whatever you need to prompt 

using(var keySet = new KeySet("path_to_keyset")) 
using(var pbeKeySet = new PbeKeySet(keySet, passwordCallback)) 
using(var encrypter = new Encrypter(pbeKeySet)){ 
{ 
    return encrypter.Encrypt(plaintext); 
} 

解密:

using(var keySet = new KeySet("path_to_keyset")) 
using(var pbeKeySet = new PbeKeySet(keySet, passwordCallback)) 
using(var crypter = new Crypter(pbeKeySet)){ 
{ 
    return crypter.Encrypt(plaintext); 
} 

当然,如果你需要非交互式的加密和解密你应该去与regular usage keyczar,或者你甚至可以有key set to encrypt another key set如果你需要额外的分离。