我的工作是在工作场所创建一个内部文档管理系统。该任务的要求是对导入到系统中的文档进行加密,并且仅在最终用户请求时才对其解密。而且,最终用户将不知道用于解密的密码/密钥,系统必须完全自行处理加密和解密。
我想使用AES(没有真正的理由,这似乎是个不错的选择),所以我开始研究如何为AES生成和存储安全密钥。我找不到很多实现方法的方法,只是很多不要做的事情。我发现的唯一不错的方法是使用.NET密钥容器(https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-store-asymmetric-keys-in-a-key-container),但它是用于非对称密钥的。
所以我开始使用它,下面是结合使用RSA和AES的工作示例:
public static byte[] Encrypt(byte[] data, byte[] salt)
{
byte[] encrypted;
Rfc2898DeriveBytes deriveBytes;
// Sanity
if (data == null || data.Length <= 0)
throw new ArgumentNullException("data");
if (salt == null || salt.Length <= 0)
throw new ArgumentNullException("salt");
// Create AES object
using (Aes aes = Aes.Create())
{
deriveBytes = new Rfc2898DeriveBytes(GetKeyFromContainer(), salt, MAX_ITERATIONS);
aes.Key = deriveBytes.GetBytes(32);
aes.IV = salt;
ICryptoTransform cryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
}
encrypted = memoryStream.ToArray();
}
}
return encrypted;
}
public static byte[] Decrypt(byte[] data, byte[] salt)
{
byte[] decrypted;
Rfc2898DeriveBytes deriveBytes;
// Sanity
if (data == null || data.Length <= 0)
throw new ArgumentNullException("data");
if (salt == null || salt.Length <= 0)
throw new ArgumentNullException("salt");
// Create AES object
using (Aes aes = Aes.Create())
{
deriveBytes = new Rfc2898DeriveBytes(GetKeyFromContainer(), salt, MAX_ITERATIONS);
aes.Key = deriveBytes.GetBytes(32);
aes.IV = salt;
ICryptoTransform cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(data))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
decrypted = Encoding.Default.GetBytes(streamReader.ReadToEnd());
}
}
}
}
return decrypted;
}
private static byte[] GetKeyFromContainer()
{
CspParameters parameters;
RSACryptoServiceProvider rsaServiceProvider;
parameters = new CspParameters();
parameters.KeyContainerName = KEY_CONTAINER_NAME;
rsaServiceProvider = new RSACryptoServiceProvider(parameters);
return Encoding.Default.GetBytes(rsaServiceProvider.ToXmlString(true));
}
接下来的问题:
我在密码学方面经验不足,因此非常感谢您提供任何帮助或教育材料。