正确使用 AesCryptoServiceProvider
Correct AesCryptoServiceProvider usage
我正在尝试编写一些直接的加密例程。以下是我根据网络搜索得出的结论。
public string Encrypt(string plainText)
{
byte[] encrypted;
// Create an AesCryptoServiceProvider object
// with the specified key and IV.
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
msEncrypt.WriteByte((byte)aesAlg.Key.Length);
msEncrypt.Write(aesAlg.Key, 0, aesAlg.Key.Length);
msEncrypt.WriteByte((byte)aesAlg.IV.Length);
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);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
public string Decrypt(string cipherText)
{
string plaintext = null;
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
{
int l = msDecrypt.ReadByte();
byte[] key = new byte[l];
msDecrypt.Read(key, 0, l);
l = msDecrypt.ReadByte();
byte[] IV = new byte[l];
msDecrypt.Read(IV, 0, l);
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(key, IV);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
return plaintext;
}
两个问题:
- 首先,我发现的大多数示例都对
Key
和 IV
进行了硬编码。所以我正在做的是将它写入加密字节。这将使我的加密数据更大。有没有更好的方法?
- 此外,我没有使用任何密码。会使用密码来生成自定义
Key
吗?而且,如果是这样,我怎么知道该密钥需要多长时间?
First, most of the examples I found hard coded the Key and IV. So what I'm doing is writing it to the encrypted bytes. This will make my encrypted data larger. Is there a better way?
显然您不应该将密钥写入未受保护的流,因为密钥需要共享或提前建立并保密。这种秘密密钥的共享可以通过多种方式执行,从密钥协商到密钥派生、棘轮等。
Also, I'm not using any password. Would one use a password to generate a custom Key? And, if so, how would I know how long that key needed to be?
有这个可能。但是,请提醒自己密码通常没有那么强,因此如果可以避免基于密码的加密 (PBE),那么这样做可能是个好主意。
如果您从密码中导出 密钥,您应该使用基于密码的密钥导出函数(有时也称为密码散列)。在 C# 中,有一个名为 Rfc2898DeriveBytes
的 PBKDF2 实现(很糟糕)。到目前为止,这也不是最先进的,但它应该足够了——如果你设置了足够高的迭代次数的话。
当您从人类记住的密码中导出密钥时,128 位就足够了。几乎没有比用于派生密钥的密码更容易找到密钥的方法了。
我正在尝试编写一些直接的加密例程。以下是我根据网络搜索得出的结论。
public string Encrypt(string plainText)
{
byte[] encrypted;
// Create an AesCryptoServiceProvider object
// with the specified key and IV.
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
msEncrypt.WriteByte((byte)aesAlg.Key.Length);
msEncrypt.Write(aesAlg.Key, 0, aesAlg.Key.Length);
msEncrypt.WriteByte((byte)aesAlg.IV.Length);
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);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
public string Decrypt(string cipherText)
{
string plaintext = null;
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
{
int l = msDecrypt.ReadByte();
byte[] key = new byte[l];
msDecrypt.Read(key, 0, l);
l = msDecrypt.ReadByte();
byte[] IV = new byte[l];
msDecrypt.Read(IV, 0, l);
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(key, IV);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
return plaintext;
}
两个问题:
- 首先,我发现的大多数示例都对
Key
和IV
进行了硬编码。所以我正在做的是将它写入加密字节。这将使我的加密数据更大。有没有更好的方法? - 此外,我没有使用任何密码。会使用密码来生成自定义
Key
吗?而且,如果是这样,我怎么知道该密钥需要多长时间?
First, most of the examples I found hard coded the Key and IV. So what I'm doing is writing it to the encrypted bytes. This will make my encrypted data larger. Is there a better way?
显然您不应该将密钥写入未受保护的流,因为密钥需要共享或提前建立并保密。这种秘密密钥的共享可以通过多种方式执行,从密钥协商到密钥派生、棘轮等。
Also, I'm not using any password. Would one use a password to generate a custom Key? And, if so, how would I know how long that key needed to be?
有这个可能。但是,请提醒自己密码通常没有那么强,因此如果可以避免基于密码的加密 (PBE),那么这样做可能是个好主意。
如果您从密码中导出 密钥,您应该使用基于密码的密钥导出函数(有时也称为密码散列)。在 C# 中,有一个名为 Rfc2898DeriveBytes
的 PBKDF2 实现(很糟糕)。到目前为止,这也不是最先进的,但它应该足够了——如果你设置了足够高的迭代次数的话。
当您从人类记住的密码中导出密钥时,128 位就足够了。几乎没有比用于派生密钥的密码更容易找到密钥的方法了。