我正在研究 VS2015 中的 CryptSharp SCrypt 实现。我需要加密/解密要作为电子邮件附件发送的文本文件。最初我使用的是 AES,但考虑到 HMAC-SHA1 已经过时,我选择使用 SCrypt 进行密码散列。但是,SCrypt 并没有公开数据加密本身的公共方法,那么将 SCrypt 散列密码传递给 AES,然后使用后者进行数据加密是否有意义?或者也许有更好的方法?
在这种情况下,我会想象这样的事情,但我需要找到一种方法来可靠地随机化 IV ...
private static Aes SetAes(string userName, string password)
{
var passBytes = Encoding.UTF8.GetBytes(password);
var saltBytes = Encoding.UTF8.GetBytes(userName);
var cost = 131072; // around 5 secs with block at 16(on Xeon 1241 v3)
var blockSize = 16; // 8 is default but might not suffice against modern GPUs(?)
var parallel = 1;
var maxThreads = (int?)null;
byte[] derivedKey = new byte[32]; // 256 bits
SCrypt.ComputeKey(passBytes, saltBytes, cost, blockSize, parallel, maxThreads, derivedKey);
Aes aes = new AesManaged();
aes.Padding = PaddingMode.PKCS7;
aes.Key = derivedKey;
byte[] IV = new byte[16];
Array.Copy(derivedKey, IV, 16); // how to reliably randomize the IV?
aes.IV = IV;
return aes;
}
然后进行文件加密:
internal static void EncryptText(string text, string userName, string password, string file)
{
// omitting argument checks for readability
using (Aes aes = SetAes(userName, password))
{
using (FileStream fileStream = new FileStream(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{
using (CryptoStream cryptoStream = new CryptoStream(fileStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(cryptoStream, text); // I'm using a class to wrap the text for serialization, not shown here for readability
}
}
}
}
尽管它似乎有效,但我不确定它是否有意义,所以非常感谢您的任何见解。
编辑:
按照 vcsjones 的建议,如果我理解正确的话,SetAes 函数会看起来像这样:
private static Aes SetAes(string userName, string password, byte[] IV = null)
{
var passBytes = Encoding.UTF8.GetBytes(password);
var saltBytes = Encoding.UTF8.GetBytes(userName);
var cost = 131072;
var blockSize = 16;
var parallel = 1;
var maxThreads = (int?)null;
byte[] derivedKey = new byte[32];
SCrypt.ComputeKey(passBytes, saltBytes, cost, blockSize, parallel, maxThreads, derivedKey);
Aes aes = new AesManaged();
aes.Padding = PaddingMode.PKCS7;
aes.Key = derivedKey;
if (IV == null) // when encrypting, generate IV
{
RandomNumberGenerator rn = RandomNumberGenerator.Create();
rn.GetBytes(aes.IV);
}
else aes.IV = IV; // when decrypting, read IV from file and pass it to aes through IV parameter for decryption
return aes;
}