我爲每個用戶生成隨機HMAC密鑰並將密鑰存儲在我們的數據庫中。如果用戶請求密鑰,用戶只能獲得密鑰,並且通常只是使用我們的API令牌(SWT)作爲BASE64編碼的不透明密鑰,而不必擔心它們的完整性。爲什麼我不能加密/解密數據庫存儲的HMAC密鑰?
我想在將密鑰存儲到我們的SQL Server數據庫之前對其進行加密,以防止密鑰泄露。它們的加密密鑰存儲在varbinary(MAX)列中。沒有加密,一切都很好。
我使用AES進行加密,隨機生成的IV存儲在加密值的開頭。
在我的單元測試中,使用簡單的字符串,一切都很好,但是,對於HMAC密鑰,解密值永遠不會與原始值匹配。如果我生成一個HMAC密鑰,加密它,將它存儲在數據庫中。當我檢索它時,解密它,並使用它們鍵來生成一個HMAC散列,它與原始HMAC散列值不匹配。
請參閱下面的加密/解密方法。
public static byte[] Encrypt(byte[] value)
{
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
{
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(_password, Encoding.ASCII.GetBytes(_salt));
aes.Key = key.GetBytes(aes.KeySize/8);
aes.GenerateIV();
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
using (var crypt = aes.CreateEncryptor(aes.Key, aes.IV))
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, crypt, CryptoStreamMode.Write))
{
cs.Write(aes.IV, 0, aes.IV.Length);
using (BinaryWriter bw = new BinaryWriter(cs))
{
bw.Write(value);
cs.FlushFinalBlock();
}
return ms.ToArray();
}
}
}
}
public static byte[] Decrypt(byte[] value)
{
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
{
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(_password, Encoding.ASCII.GetBytes(_salt));
aes.Key = key.GetBytes(aes.KeySize/8);
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
using (MemoryStream ms = new MemoryStream(value))
{
byte[] iv = new byte[aes.IV.Length];
ms.Read(iv, 0, aes.IV.Length);
aes.IV = iv;
using (var crypt = aes.CreateDecryptor(aes.Key, aes.IV))
using (CryptoStream cs = new CryptoStream(ms, crypt, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
return Encoding.ASCII.GetBytes(sr.ReadToEnd());
}
}
}
}
密碼和salt存儲在編譯爲代碼的常量字符串文字中。我意識到這並不理想,但現在是這樣。
你已經給出了一些代碼,但沒有說它不工作的方式... –
如果我生成一個HMAC密鑰,加密它,將它存儲在數據庫中。當我檢索它時,解密它,並使用它們鍵來生成一個HMAC散列,它與原始HMAC散列值不匹配。 –
那麼你是如何診斷問題的呢?你記錄了每個階段涉及的字節嗎? (在加密之前,在保存到數據庫之前進行加密之後,從數據庫中獲取之後但在解密之前,在解密之後......)基本上,您需要確切地確定造成問題的階段。 –