将 JavaScript 解密重构为 C# - AES 128
Refactor JavaScript decryption into C# - AES 128
我需要进行解密消息并将其转换为 C# 的工作 JavaScript。我有解密信息(下面的“解密”变量),看起来像:AES-128:<salt>:<iv>:<key>
。这是 JavaScript:
function decodeString(message, decrypt) {
var parts = decrypt.split(':', 4);
var salt = CryptoJS.enc.Hex.parse(parts[1]);
var iv = CryptoJS.enc.Hex.parse(parts[2]);
var key = CryptoJS.PBKDF2(parts[3], salt, { keySize: 128/32, iterations: 100 });
try {
message = message.replace(/\s+/g, '');
var d = CryptoJS.AES.decrypt(message, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
message = d.toString(CryptoJS.enc.Utf8);
} catch (e) {
console.error("Encountered a problem decrypting and encrypted page!");
console.log(e);
}
return(message);
}
这是我在 C# 中的内容,但我在调用 CreateDecryptor 时遇到异常。
using System.Security.Cryptography;
private string DecodeString(string message, string decrypt)
{
string[] parts = decrypt.ToString().Split(':');
byte[] salt = Encoding.UTF8.GetBytes(parts[1]);
byte[] iv = Encoding.UTF8.GetBytes(parts[2]);
var pbkdf2 = new Rfc2898DeriveBytes(parts[3], salt, 100);
int numKeyBytes = 128; // Not sure this is correct
byte[] key = pbkdf2.GetBytes(numKeyBytes);
string plainText = null;
using (AesManaged aes = new AesManaged())
{
aes.KeySize = numKeyBytes; // Not sure if this is correct
aes.BlockSize = 128; // Defaults to 128, but not sure this is correct
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
try
{
// The below line has the following exception:
// The specified key is not a valid size for this algorithm.
// Parameter name: key
using (var decrypter = aes.CreateDecryptor(key, iv))
using (var plainTextStream = new MemoryStream())
{
using (var decrypterStream = new CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write))
using (var binaryWriter = new BinaryWriter(decrypterStream))
{
string encryptedText = Regex.Replace(message, @"\s+", "");
binaryWriter.Write(encryptedText);
}
byte[] plainTextBytes = plainTextStream.ToArray();
plainText = Encoding.UTF8.GetString(plainTextBytes);
}
}
catch (Exception ex)
{
log.Error("Unable to decrypt message.", ex);
}
return plainText;
}
}
如有任何建议,我们将不胜感激!
C#代码中存在以下问题:
- Salt 和 IV 必须进行十六进制解码(而不是 UTF8 编码)。
numKeyBytes
以字节为单位指定密钥大小,因此对于 AES-128 是 16(而不是 128)。
aes.KeySize
以位为单位指定密钥大小,因此是 numKeyBytes * 8
(而不是 numKeyBytes
),但也可以省略。
- 对于
aes.BlockSize
、aes.Mode
和aes.Padding
,使用默认值(128、CBC、PKCS7),因此不需要明确指定。
encryptedText
必须进行Base64解码。
一个可能的实现是:
private string Decrypt(string message, string decrypt)
{
string[] parts = decrypt.ToString().Split(':');
byte[] salt = StringToByteArray(parts[1]); // Hex decode salt
byte[] iv = StringToByteArray(parts[2]); // Hex dedoce IV
var pbkdf2 = new Rfc2898DeriveBytes(parts[3], salt, 100);
int numKeyBytes = 16; // AES-128 key size in bytes: 16
byte[] key = pbkdf2.GetBytes(numKeyBytes);
string plainText = null;
using (AesManaged aes = new AesManaged())
{
aes.KeySize = 192;
try
{
string encryptedText = Regex.Replace(message, @"\s+", "");
using (var decrypter = aes.CreateDecryptor(key, iv))
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(encryptedText))) // Base64 decode ciphertext
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decrypter, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plainText = srDecrypt.ReadToEnd();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Unable to decrypt message.", ex);
}
return plainText;
}
}
其中 StringToByteArray()
来自 here.
我将 Stream 部分更改为类似于 this example,但原始实现也能正常工作,因此此更改是可选的。
测试:数据的两个代码return
message = "YhyXEjjNAnRUUONwVzlha59tRoWkeEwTkOtSKOicRd/iBKkGgIp+DeWmvEXxAU53";
decrypt = "AES-128:30313233343536373839303132333435:35343332313039383736353433323130:my passphrase";
明文:
The quick brown fox jumps over the lazy dog
我需要进行解密消息并将其转换为 C# 的工作 JavaScript。我有解密信息(下面的“解密”变量),看起来像:AES-128:<salt>:<iv>:<key>
。这是 JavaScript:
function decodeString(message, decrypt) {
var parts = decrypt.split(':', 4);
var salt = CryptoJS.enc.Hex.parse(parts[1]);
var iv = CryptoJS.enc.Hex.parse(parts[2]);
var key = CryptoJS.PBKDF2(parts[3], salt, { keySize: 128/32, iterations: 100 });
try {
message = message.replace(/\s+/g, '');
var d = CryptoJS.AES.decrypt(message, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
message = d.toString(CryptoJS.enc.Utf8);
} catch (e) {
console.error("Encountered a problem decrypting and encrypted page!");
console.log(e);
}
return(message);
}
这是我在 C# 中的内容,但我在调用 CreateDecryptor 时遇到异常。
using System.Security.Cryptography;
private string DecodeString(string message, string decrypt)
{
string[] parts = decrypt.ToString().Split(':');
byte[] salt = Encoding.UTF8.GetBytes(parts[1]);
byte[] iv = Encoding.UTF8.GetBytes(parts[2]);
var pbkdf2 = new Rfc2898DeriveBytes(parts[3], salt, 100);
int numKeyBytes = 128; // Not sure this is correct
byte[] key = pbkdf2.GetBytes(numKeyBytes);
string plainText = null;
using (AesManaged aes = new AesManaged())
{
aes.KeySize = numKeyBytes; // Not sure if this is correct
aes.BlockSize = 128; // Defaults to 128, but not sure this is correct
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
try
{
// The below line has the following exception:
// The specified key is not a valid size for this algorithm.
// Parameter name: key
using (var decrypter = aes.CreateDecryptor(key, iv))
using (var plainTextStream = new MemoryStream())
{
using (var decrypterStream = new CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write))
using (var binaryWriter = new BinaryWriter(decrypterStream))
{
string encryptedText = Regex.Replace(message, @"\s+", "");
binaryWriter.Write(encryptedText);
}
byte[] plainTextBytes = plainTextStream.ToArray();
plainText = Encoding.UTF8.GetString(plainTextBytes);
}
}
catch (Exception ex)
{
log.Error("Unable to decrypt message.", ex);
}
return plainText;
}
}
如有任何建议,我们将不胜感激!
C#代码中存在以下问题:
- Salt 和 IV 必须进行十六进制解码(而不是 UTF8 编码)。
numKeyBytes
以字节为单位指定密钥大小,因此对于 AES-128 是 16(而不是 128)。aes.KeySize
以位为单位指定密钥大小,因此是numKeyBytes * 8
(而不是numKeyBytes
),但也可以省略。- 对于
aes.BlockSize
、aes.Mode
和aes.Padding
,使用默认值(128、CBC、PKCS7),因此不需要明确指定。 encryptedText
必须进行Base64解码。
一个可能的实现是:
private string Decrypt(string message, string decrypt)
{
string[] parts = decrypt.ToString().Split(':');
byte[] salt = StringToByteArray(parts[1]); // Hex decode salt
byte[] iv = StringToByteArray(parts[2]); // Hex dedoce IV
var pbkdf2 = new Rfc2898DeriveBytes(parts[3], salt, 100);
int numKeyBytes = 16; // AES-128 key size in bytes: 16
byte[] key = pbkdf2.GetBytes(numKeyBytes);
string plainText = null;
using (AesManaged aes = new AesManaged())
{
aes.KeySize = 192;
try
{
string encryptedText = Regex.Replace(message, @"\s+", "");
using (var decrypter = aes.CreateDecryptor(key, iv))
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(encryptedText))) // Base64 decode ciphertext
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decrypter, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plainText = srDecrypt.ReadToEnd();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Unable to decrypt message.", ex);
}
return plainText;
}
}
其中 StringToByteArray()
来自 here.
我将 Stream 部分更改为类似于 this example,但原始实现也能正常工作,因此此更改是可选的。
测试:数据的两个代码return
message = "YhyXEjjNAnRUUONwVzlha59tRoWkeEwTkOtSKOicRd/iBKkGgIp+DeWmvEXxAU53";
decrypt = "AES-128:30313233343536373839303132333435:35343332313039383736353433323130:my passphrase";
明文:
The quick brown fox jumps over the lazy dog