Ran*_*ger 2 c# encryption cryptography aes
我正在使用框架的对象编写一个用于加密/解密的简单库。方法如下:
public static byte[] Encrypt(byte[] key, byte[] vector, byte[] input)
{
if(key.Length == 0)
throw new ArgumentException("Cannot encrypt with empty key");
if (vector.Length == 0)
throw new ArgumentException("Cannot encrypt with empty vector");
if (input.Length == 0)
throw new ArgumentException("Cannot encrypt empty input");
var unencryptedBytes = input;
using(AesCryptoServiceProvider aes = new AesCryptoServiceProvider {Key = key, IV = vector})
using(ICryptoTransform encryptor = aes.CreateEncryptor())
using (MemoryStream ms = new MemoryStream())
using (CryptoStream writer = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
writer.Write(unencryptedBytes, 0, unencryptedBytes.Length);
writer.FlushFinalBlock();
var byteArray = ms.ToArray();
if(byteArray.Length == 0)
throw new Exception("Attempted to encrypt but encryption resulted in a byte array of 0 length.");
return byteArray;
}
}
public static byte[] Decrypt(byte[] key, byte[] vector, byte[] encrypted)
{
if (key.Length == 0)
throw new ArgumentException("Cannot encrypt with empty key");
if (vector.Length == 0)
throw new ArgumentException("Cannot encrypt with empty vector");
if (encrypted == null || encrypted.Length == 0)
throw new ArgumentException("Cannot decrypt empty or null byte array");
byte[] unencrypted;
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider { Key = key, IV = vector })
using (ICryptoTransform decryptor = aes.CreateDecryptor(key, vector))
using (MemoryStream ms = new MemoryStream(encrypted))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
cs.Read(encrypted, 0, encrypted.Length);
unencrypted = ms.ToArray();
}
return unencrypted;
}
Run Code Online (Sandbox Code Playgroud)
将其输入编码字符串,例如,如下所示:
var expected = "This is an example message";
var messageBytes = Encoding.UTF8.GetBytes(expected);
Run Code Online (Sandbox Code Playgroud)
进入(在本例中)26 个字节。加密后它留下 32 个字节,当它被转换回一个字符串时,它会在末尾附加随机字符,但在其他方面完全有效,如下所示:
"This is an example message?(4???"
Run Code Online (Sandbox Code Playgroud)
生成新的向量/密钥会更改附加到末尾的随机字符。
如何消除这种额外字节的行为?
编辑
包括请求的单元测试。
[TestMethod]
public void CanEncryptAndDecryptByteArray()
{
var expected = "This is an example message";
var messageBytes = Encoding.UTF8.GetBytes(expected);
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.GenerateIV();
aes.GenerateKey();
var byteKey = Convert.ToBase64String(aes.Key);
var vectorKey = Convert.ToBase64String(aes.IV);
var key = Convert.FromBase64String("Qcf+3VzYNAfPUCfBO/ePSxCLBLItkVfk8ajK86KYebs=");
var vector = Convert.FromBase64String("aJNKWP7M2D44jilby6BzGg==");
var encrypted = EncryptionManager.Encrypt(key, vector, messageBytes);
var decrypted = EncryptionManager.Decrypt(key, vector, encrypted);
var actual = Encoding.UTF8.GetString(decrypted);
Assert.AreEqual(expected, actual);
}
Run Code Online (Sandbox Code Playgroud)
垃圾字节是因为我们正在读取和写入同一个数组。
new MemoryStream(encrypted))
告诉 crypt 从encrypted
.
cs.Read(encrypted, 0, encrypted.Length);
告诉它写入encrypted
.
解决方案:
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider { Key = key, IV = vector })
using (ICryptoTransform decryptor = aes.CreateDecryptor(key, vector))
using (MemoryStream ms = new MemoryStream(encrypted))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
var decrypted = new byte[encrypted.Length];
var bytesRead = cs.Read(decrypted, 0, encrypted.Length);
return decrypted.Take(bytesRead).ToArray();
}
Run Code Online (Sandbox Code Playgroud)
请注意,我们bytesRead
取自数组,而不是完整数组,否则我们最终会得到空字节(字符串比较失败,但在编辑器中显示相同)
归档时间: |
|
查看次数: |
3186 次 |
最近记录: |