我在解析示例应用程序中的简单值时遇到问题。该值使用相同的示例应用程序加密。我已经列出了下面的代码。
当代码块完成时,结果是plain
是一个空字符串。没有例外。
string plain = null;
using (AesManaged alg = new AesManaged())
{
// Extract the initialization vector from the entire ciphertext
byte[] IV = new byte[alg.IV.Length];
Buffer.BlockCopy(cipherText, 0, IV, 0, alg.IV.Length);
alg.IV = IV;
alg.Key = GetKey();
ICryptoTransform transform = alg.CreateDecryptor();
// Extract the encrypted value from the entire ciphertext
byte[] encrypted = new byte[cipherText.Length - alg.IV.Length];
Buffer.BlockCopy(cipherText, alg.IV.Length, encrypted, 0, cipherText.Length - alg.IV.Length);
using (MemoryStream ms = new MemoryStream(encrypted))
{
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
{
using (StreamReader r = new StreamReader(cs))
{
cs.Flush();
plain = r.ReadToEnd();
}
}
}
}
我已经验证cipherText
(作为参数传递的32字节byte [])具有与加密产生的值相同的字节。 IV和Key也是逐字节的相同。注意:加密逻辑将IV加在加密值之前。这就是为什么第一行从代码块中提取它。
我还验证了encrypted
byte []的内容与加密例程中的内容相同。内容只有16个字节。
我已经验证了MemoryStream Position
中的ms
是0.在例程之后,它是16.所以看起来MemoryStream被读取了。我的怀疑是我错误地使用StreamReader
,但我看不出我犯了错误的地方。
我试图修改加密字节[]中的一个字节,然后按预期我得到一个CryptographicException
(填充无效)。因此,从加密的角度来看,似乎所有的都是我的IV,密钥和加密值。出于某种原因,也许它不会一直处理?
感谢您的任何见解。
为完整起见,下面的加密程序如下: byte [] encrypted = null;
using (AesManaged alg = new AesManaged())
{
System.Diagnostics.Debug.WriteLine("Key size: {0}", alg.KeySize);
alg.GenerateIV();
alg.Key = GetKey();
ICryptoTransform transform = alg.CreateEncryptor(alg.Key, alg.IV);
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
using (StreamWriter w = new StreamWriter(cs))
{
w.Write(plainText);
cs.FlushFinalBlock();
// Create a byte array big enough to hold the IV and the encrypted value
encrypted = new byte[alg.IV.Length + ms.Length];
// Copy the random generated initialization vector to the start of the encrypted bytes
Buffer.BlockCopy(alg.IV, 0, encrypted, 0, alg.IV.Length);
// Copy the encrypted value at the end
Buffer.BlockCopy(ms.ToArray(), 0, encrypted, alg.IV.Length, (int)ms.Length);
}
}
答案 0 :(得分:0)
我弄清楚了我犯的错误。我正在使用非常短的字符串进行测试,并且我认为加密的大小总是16个字节并不奇怪。
当我用更长的琴弦测试时,感觉不对。事实证明我的问题出现在加密逻辑中:除了StreamWriter
之外,我还需要刷新CryptoStream
。以下是我现在正在使用的加密和解密逻辑。
请注意,逻辑的另一个改进是我现在还在密钥生成期间生成随机盐,并且随机盐也被添加到加密字节[]。
private const int SaltLength = 8;
public class KeyPackage
{
public byte[] KeySalt { get; set; }
public byte[] Key { get; set; }
}
public KeyPackage GetKey()
{
// Read the password from the configuration
string Key = System.Configuration.ConfigurationManager.AppSettings["EncryptionKey"];
// Generate Key from the password stored in configuration using a random salt
using (Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(Key, SaltLength))
{
// Using AES-128, we need 128 / 8 bytes in the key
return new KeyPackage() { Key = db.GetBytes(128 / 8), KeySalt = db.Salt };
}
}
public byte[] GetKey(byte[] keySalt)
{
// Read the password from the configuration
string Key = System.Configuration.ConfigurationManager.AppSettings["EncryptionKey"];
// Generate Key from the password stored in configuration using the known salt
using (Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(Key, keySalt))
{
// Using AES-128, we need 128 / 8 bytes in the key
return db.GetBytes(128 / 8);
}
}
/// <summary>
/// Encrypts the specified plain text using the
/// encryption key found in the configuration file.
/// </summary>
/// <param name="plainText">The plain text to encrypted.</param>
/// <returns>The cipher text.</returns>
public byte[] Encrypt(string plainText)
{
byte[] encrypted = null;
using (AesManaged alg = new AesManaged())
{
System.Diagnostics.Debug.WriteLine("Key size: {0}", alg.KeySize);
alg.GenerateIV();
KeyPackage kp = GetKey();
alg.Key = kp.Key;
ICryptoTransform transform = alg.CreateEncryptor();
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
using (StreamWriter w = new StreamWriter(cs))
{
w.Write(plainText);
w.Flush(); // This was missing from my first post
cs.FlushFinalBlock();
// Create a byte array big enough to hold the IV and the encrypted value
encrypted = new byte[kp.KeySalt.Length + alg.IV.Length + ms.Length];
// Copy the random generated salt to the start of the encrypted bytes
Buffer.BlockCopy(kp.KeySalt, 0, encrypted, 0, kp.KeySalt.Length);
// Copy the random generated initialization vector to the start of the encrypted bytes
Buffer.BlockCopy(alg.IV, 0, encrypted, kp.KeySalt.Length, alg.IV.Length);
// Copy the encrypted value at the end
Buffer.BlockCopy(ms.ToArray(), 0, encrypted, alg.IV.Length + kp.KeySalt.Length, (int)ms.Length);
}
}
return encrypted;
}
/// <summary>
///
/// </summary>
/// <param name="cipherText"></param>
/// <returns></returns>
public string Decrypt(byte[] cipherText)
{
string plain = null;
using (AesManaged alg = new AesManaged())
{
// Extract the initialization vector from the entire ciphertext
byte[] IV = new byte[alg.IV.Length];
byte[] KeySalt = new byte[SaltLength];
Buffer.BlockCopy(cipherText, 0, KeySalt, 0, SaltLength);
Buffer.BlockCopy(cipherText, SaltLength, IV, 0, alg.IV.Length);
alg.IV = IV;
alg.Key= GetKey(KeySalt);
ICryptoTransform transform = alg.CreateDecryptor();
// Extract the encrypted value from the entire ciphertext
int ActualCipherLength = cipherText.Length - alg.IV.Length - SaltLength;
byte[] encrypted = new byte[ActualCipherLength];
Buffer.BlockCopy(cipherText, alg.IV.Length + SaltLength, encrypted, 0, ActualCipherLength);
using (MemoryStream ms = new MemoryStream(encrypted))
using (CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Read))
using (StreamReader r = new StreamReader(cs))
{
plain = r.ReadToEnd();
}
}
return plain;
}
}