解决密码学结果差异
我有一个不错的课程来加密和解密数据。我可以通过此字符串将其传递:
var thisIsATest = "This is a test.";
当我解密数据时,我会回来:
var thisIsDecrypted = "This is a test.\0";
我们俩都理解这些基本上是同一件事,但它仍然不会通过我的单位测试。
首先,我将显示单位测试:
var privateKey = Encryption.GetPrivateKey();
var password = new byte[] { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
var salt = Salt.CreateSalt();
var passPhrase = Encryption.PasswordAndSalt(password, salt);
var thisIsATest = "This is a test.";
var clearArray = Encoding.UTF8.GetBytes(thisIsATest);
var cypherArray = Encryption.Encrypt(clearArray, passPhrase, privateKey);
var decryptedArray = Encryption.Decrypt(cypherArray, passPhrase, privateKey);
var thisIsDecrypted = Encoding.UTF8.GetString(decryptedArray);
//Assert
Assert.IsTrue(thisIsATest == thisIsDecrypted);
这是我的代码,解密:
public static byte[] Decrypt(byte[] cypherBytes, byte[] passPhrase, byte[] privateKey)
{
var result = new byte[] { };
using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
{
using (var decryptor = rijndael.CreateDecryptor(passPhrase, privateKey))
{
using (var ms = new MemoryStream(cypherBytes))
{
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
result = new byte[cypherBytes.Length];
var readCount = cs.Read(result, 0, result.Length);
}
}
}
rijndael.Clear();
}
return result;
}
加密:
public static byte[] Encrypt(byte[] clearBytes, byte[] passPhrase, byte[] privateKey)
{
var result = new byte[] { };
using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
{
using (var encryptor = rijndael.CreateEncryptor(passPhrase, privateKey))
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.FlushFinalBlock();
}
result = ms.ToArray();
}
}
rijndael.Clear();
}
return result;
}
passwordandsalt:
public const int INITIALIZATION_VECTOR_SIZE = 32;
public static byte[] PasswordAndSalt(byte[] password, byte[] salt)
{
var result = new byte[] { };
using (var pwd = new PasswordDeriveBytes(password, salt))
{
result = pwd.GetBytes(INITIALIZATION_VECTOR_SIZE);
}
return result;
}
is paddingmode.pkcs7 导致我的缓冲区在最后获得\ 0
?
解决!
在下面使用Maarten的答案,我能够重写解密方法以成功工作如下:
public static byte[] Decrypt(byte[] cypherBytes, byte[] passPhrase, byte[] privateKey)
{
var result = new byte[] { };
using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
{
using (var decryptor = rijndael.CreateDecryptor(passPhrase, privateKey))
{
using (var ms = new MemoryStream(cypherBytes))
{
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
var array = new byte[cypherBytes.Length];
var readCount = cs.Read(array, 0, array.Length);
result = new byte[readCount];
Array.Copy(array, result, readCount);
}
}
}
rijndael.Clear();
}
return result;
}
I have a nice class to encrypt and decrypt data. I can pass it this string:
var thisIsATest = "This is a test.";
When I decrypt the data, I get this back:
var thisIsDecrypted = "This is a test.\0";
We both understand that those are basically the same thing, but it still will not pass my unit test.
First I will show the unit test:
var privateKey = Encryption.GetPrivateKey();
var password = new byte[] { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
var salt = Salt.CreateSalt();
var passPhrase = Encryption.PasswordAndSalt(password, salt);
var thisIsATest = "This is a test.";
var clearArray = Encoding.UTF8.GetBytes(thisIsATest);
var cypherArray = Encryption.Encrypt(clearArray, passPhrase, privateKey);
var decryptedArray = Encryption.Decrypt(cypherArray, passPhrase, privateKey);
var thisIsDecrypted = Encoding.UTF8.GetString(decryptedArray);
//Assert
Assert.IsTrue(thisIsATest == thisIsDecrypted);
Here are my code, Decrypt:
public static byte[] Decrypt(byte[] cypherBytes, byte[] passPhrase, byte[] privateKey)
{
var result = new byte[] { };
using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
{
using (var decryptor = rijndael.CreateDecryptor(passPhrase, privateKey))
{
using (var ms = new MemoryStream(cypherBytes))
{
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
result = new byte[cypherBytes.Length];
var readCount = cs.Read(result, 0, result.Length);
}
}
}
rijndael.Clear();
}
return result;
}
Encrypt:
public static byte[] Encrypt(byte[] clearBytes, byte[] passPhrase, byte[] privateKey)
{
var result = new byte[] { };
using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
{
using (var encryptor = rijndael.CreateEncryptor(passPhrase, privateKey))
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.FlushFinalBlock();
}
result = ms.ToArray();
}
}
rijndael.Clear();
}
return result;
}
And PasswordAndSalt:
public const int INITIALIZATION_VECTOR_SIZE = 32;
public static byte[] PasswordAndSalt(byte[] password, byte[] salt)
{
var result = new byte[] { };
using (var pwd = new PasswordDeriveBytes(password, salt))
{
result = pwd.GetBytes(INITIALIZATION_VECTOR_SIZE);
}
return result;
}
Is PaddingMode.PKCS7 causing my buffer to get the the \0
on the end?
Resolved!
Using Maarten's answer below, I was able to rewrite the Decrypt method to work successfully as follows:
public static byte[] Decrypt(byte[] cypherBytes, byte[] passPhrase, byte[] privateKey)
{
var result = new byte[] { };
using (var rijndael = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
{
using (var decryptor = rijndael.CreateDecryptor(passPhrase, privateKey))
{
using (var ms = new MemoryStream(cypherBytes))
{
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
var array = new byte[cypherBytes.Length];
var readCount = cs.Read(array, 0, array.Length);
result = new byte[readCount];
Array.Copy(array, result, readCount);
}
}
}
rijndael.Clear();
}
return result;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
错误的问题:您自己设置了缓冲区的大小。最后一个字节永远不会被人填充。
您为什么假设使用填充的CBC模式假设明文的大小与密文的大小相同?您不应忽略
readCount
,然后仅将缓冲区的最左侧部分用作明文。具有PKCS#7填充的CBC模式将使用1到N字节填充,其中N是该算法的块大小。对于AES始终是16个字节。因此,您的缓冲区将始终在您当前的代码中被过度尺寸。
Wrong question: you are yourself setting the size of the buffer. The last byte is simply never populated.
Why do you assume for CBC mode with padding that the plaintext is the same size as the ciphertext? You should not ignore the
readCount
, and then only use the leftmost part of the buffer as plaintext.CBC mode with PKCS#7 padding will pad with 1 to N bytes, where N is the block size of the algorithm. For AES N is always 16 bytes. So your buffer will always be over-dimensioned in your current code.