2013-04-05 131 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如果你需要額外的分離。