将加密从 AesCryptoServiceProvider 转换为 BouncyCastle
Convert encryption from AesCryptoServiceProvider to BouncyCastle
我在磁盘上使用 AesCryptoServiceProvider
加密了文件。
我需要将代码转换为 PCL(没有 class AesCryptoServiceProvider
)。所以我想使用 Bouncy Castle ( https://www.nuget.org/packages/Portable.BouncyCastle/ ) 在不更改加密的情况下读取和保存文件。并防止需要转换所有文件..
Key
是 32 个字节长。
IV
是 16 个字节长。
原代码如下:
private static byte[] Encrypt(string plainText, byte[] Key, byte[] IV)
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream outputStream = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
}
return outputStream.ToArray();
}
}
}
AesCryptoServiceProvider
的默认模式是 CBC
,填充类型为 PKCS7
,然后我尝试使用 classes CbcBlockCipher
和 Pkcs7Padding
.这是我最后一次尝试:
private static byte[] Encrypt(byte[] input, byte[] key, byte[] IV)
{
var keyParameter = new KeyParameter(key);
var parameters = new ParametersWithIV(keyParameter, IV);
var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new AesEngine()), new Pkcs7Padding());
cipher.Init(true, parameters);
var rsl = new byte[cipher.GetOutputSize(input.Length)];
var outOff = cipher.ProcessBytes(input, 0, input.Length, rsl, 0);
cipher.DoFinal(rsl, outOff);
return rsl;
}
文本 "test" 的原始结果是 8jykPv2OSILKjJwvgLRr1w==
,但新代码是 BaYeiuWSnRiHXBpwt19Dag==
。
那我想念什么?
感谢您的帮助!
更新#1:
这是 Key 和 IV 的值:
private static byte[] KEY = {98, 193, 95, 78, 211, 151, 118, 57, 179, 5, 85, 181, 133, 20, 94, 101, 184, 175, 94, 164, 150, 119, 75, 207, 189, 178, 21, 213, 13, 217, 174, 44};
private static byte[] IV = {1, 199, 179, 189, 160, 220, 229, 238, 179, 14, 255, 147, 187, 49, 179, 134 };
更新#2:
对于 Bouncy Castle,我将我的 plainText
转换为 input
并使用以下行:
var input = Encoding.Unicode.GetBytes(plainText);
差异来自那里...
问题是streamwriter的编码问题。当写入加密流时,它会带来相同的结果:
[TestMethod]
public void windows()
{
byte[] KEY = { 98, 193, 95, 78, 211, 151, 118, 57, 179, 5, 85, 181, 133, 20, 94, 101, 184, 175, 94, 164, 150, 119, 75, 207, 189, 178, 21, 213, 13, 217, 174, 44 };
byte[] IV = { 1, 199, 179, 189, 160, 220, 229, 238, 179, 14, 255, 147, 187, 49, 179, 134 };
byte[] input = System.Text.Encoding.UTF8.GetBytes("test");
string win = Convert.ToBase64String(Encrypt_win(input, KEY, IV));
string bc = Convert.ToBase64String(Encrypt_bc(input, KEY, IV));
Assert.AreEqual(win, "8jykPv2OSILKjJwvgLRr1w==");
Assert.AreEqual(bc, "8jykPv2OSILKjJwvgLRr1w==");
}
//private static byte[] Encrypt(string plainText, byte[] Key, byte[] IV)
private static byte[] Encrypt_win(byte[] input, byte[] Key, byte[] IV)
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream outputStream = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(input, 0, input.Length);
/*
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//swEncrypt.Write(plainText);
swEncrypt.Write(input);
}
*/
}
return outputStream.ToArray();
}
}
}
private static byte[] Encrypt_bc(byte[] input, byte[] key, byte[] IV)
{
var keyParameter = new KeyParameter(key);
var parameters = new ParametersWithIV(keyParameter, IV);
var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new AesEngine()), new Pkcs7Padding());
cipher.Init(true, parameters);
var rsl = new byte[cipher.GetOutputSize(input.Length)];
var outOff = cipher.ProcessBytes(input, 0, input.Length, rsl, 0);
cipher.DoFinal(rsl, outOff);
return rsl;
}
在使用 BouncyCastle 调用 Encrypt() 方法之前,我将字符串转换为 Encoding.Unicode.GetBytes(plainText);
而不是 Encoding.UTF8.GetBytes(plainText);
通过此修复,两种方法给出相同的结果!
我在磁盘上使用 AesCryptoServiceProvider
加密了文件。
我需要将代码转换为 PCL(没有 class AesCryptoServiceProvider
)。所以我想使用 Bouncy Castle ( https://www.nuget.org/packages/Portable.BouncyCastle/ ) 在不更改加密的情况下读取和保存文件。并防止需要转换所有文件..
Key
是 32 个字节长。
IV
是 16 个字节长。
原代码如下:
private static byte[] Encrypt(string plainText, byte[] Key, byte[] IV)
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream outputStream = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
}
return outputStream.ToArray();
}
}
}
AesCryptoServiceProvider
的默认模式是 CBC
,填充类型为 PKCS7
,然后我尝试使用 classes CbcBlockCipher
和 Pkcs7Padding
.这是我最后一次尝试:
private static byte[] Encrypt(byte[] input, byte[] key, byte[] IV)
{
var keyParameter = new KeyParameter(key);
var parameters = new ParametersWithIV(keyParameter, IV);
var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new AesEngine()), new Pkcs7Padding());
cipher.Init(true, parameters);
var rsl = new byte[cipher.GetOutputSize(input.Length)];
var outOff = cipher.ProcessBytes(input, 0, input.Length, rsl, 0);
cipher.DoFinal(rsl, outOff);
return rsl;
}
文本 "test" 的原始结果是 8jykPv2OSILKjJwvgLRr1w==
,但新代码是 BaYeiuWSnRiHXBpwt19Dag==
。
那我想念什么?
感谢您的帮助!
更新#1: 这是 Key 和 IV 的值:
private static byte[] KEY = {98, 193, 95, 78, 211, 151, 118, 57, 179, 5, 85, 181, 133, 20, 94, 101, 184, 175, 94, 164, 150, 119, 75, 207, 189, 178, 21, 213, 13, 217, 174, 44};
private static byte[] IV = {1, 199, 179, 189, 160, 220, 229, 238, 179, 14, 255, 147, 187, 49, 179, 134 };
更新#2:
对于 Bouncy Castle,我将我的 plainText
转换为 input
并使用以下行:
var input = Encoding.Unicode.GetBytes(plainText);
差异来自那里...
问题是streamwriter的编码问题。当写入加密流时,它会带来相同的结果:
[TestMethod]
public void windows()
{
byte[] KEY = { 98, 193, 95, 78, 211, 151, 118, 57, 179, 5, 85, 181, 133, 20, 94, 101, 184, 175, 94, 164, 150, 119, 75, 207, 189, 178, 21, 213, 13, 217, 174, 44 };
byte[] IV = { 1, 199, 179, 189, 160, 220, 229, 238, 179, 14, 255, 147, 187, 49, 179, 134 };
byte[] input = System.Text.Encoding.UTF8.GetBytes("test");
string win = Convert.ToBase64String(Encrypt_win(input, KEY, IV));
string bc = Convert.ToBase64String(Encrypt_bc(input, KEY, IV));
Assert.AreEqual(win, "8jykPv2OSILKjJwvgLRr1w==");
Assert.AreEqual(bc, "8jykPv2OSILKjJwvgLRr1w==");
}
//private static byte[] Encrypt(string plainText, byte[] Key, byte[] IV)
private static byte[] Encrypt_win(byte[] input, byte[] Key, byte[] IV)
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream outputStream = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(input, 0, input.Length);
/*
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//swEncrypt.Write(plainText);
swEncrypt.Write(input);
}
*/
}
return outputStream.ToArray();
}
}
}
private static byte[] Encrypt_bc(byte[] input, byte[] key, byte[] IV)
{
var keyParameter = new KeyParameter(key);
var parameters = new ParametersWithIV(keyParameter, IV);
var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new AesEngine()), new Pkcs7Padding());
cipher.Init(true, parameters);
var rsl = new byte[cipher.GetOutputSize(input.Length)];
var outOff = cipher.ProcessBytes(input, 0, input.Length, rsl, 0);
cipher.DoFinal(rsl, outOff);
return rsl;
}
在使用 BouncyCastle 调用 Encrypt() 方法之前,我将字符串转换为 Encoding.Unicode.GetBytes(plainText);
而不是 Encoding.UTF8.GetBytes(plainText);
通过此修复,两种方法给出相同的结果!