使用 C# 和 CryptoJS 的不同加密结果
Different encryption results using C# and CryptoJS
我在用 C# 编写的服务器应用程序中使用 AES 加密了一些数据。我使用预定义密钥(32 字节)和 IV(16 字节),例如...
Key: 81fe1681..6a451c1c
IV: e83c..ae76
这是我用来加密数据的 C# 代码:
async Task<byte[]> Encrypt(string privateKey, string pin, byte[] data)
{
using (var sha = SHA256.Create())
{
byte[] keyHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{privateKey}"));
byte[] pinHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
using (Aes aes = Aes.Create())
{
byte[] key = keyHash.Slice(0, aes.Key.Length);
byte[] iv = pinHash.Slice(0, aes.IV.Length);
using (ICryptoTransform transform = aes.CreateEncryptor(key, iv))
using (var stream = new MemoryStream())
using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
await cryptStream.WriteAsync(data, 0, data.Length);
await cryptStream.FlushAsync();
return stream.ToArray();
}
}
}
}
加密的结果数据看起来像...
534c..28f5
现在,我想使用 CryptoJS 解密客户端应用程序中的数据。我使用完全相同的密钥和IV信息,但解密似乎失败了......至少解密结果总是空的。
所以,我在客户端加密数据(当然相同的密钥和IV),结果密文不同;更准确地说,它是相同的,但最后有更多数据...
534c..28f5bbd5..ac0e
如果我在服务器上加密数据,我在最后得到的附加数据是什么?
如果我在客户端解密已经加密的密文,解密就成功了。顺便提一下,mode和padding在server端和client端都是默认的,分别是CBC
和Pkcs7
;密钥大小应为 256
。这是我用来解密已被服务器加密的数据的代码:
let keyHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(privateKey));
let key: WordArray = CryptoJS.lib.WordArray.create(keyHash.words.slice(0, 8), 32);
let pinHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(pin));
let iv: WordArray = CryptoJS.lib.WordArray.create(pinHash.words.slice(0, 4), 16);
let cfg: CryptoJS.lib.IBlockCipherCfg = { iv: iv };
let paramsData: CryptoJS.lib.CipherParamsData = {
ciphertext: cipherBuffer
};
let decrypted: WordArray = CryptoJS.AES.decrypt(paramsData, key, cfg);
对于写入,块的刷新存在问题。 FlushFinalBlock()
不同于 Flush()
(或 FlushAsync()
)。你必须两者都做,或者简单地处理 CryptoStream
。这将解决代码未写入最后一个数据块的问题。
async static Task<byte[]> Encrypt(string privateKey, string pin, byte[] data)
{
using (var sha = SHA256.Create())
{
byte[] keyHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{privateKey}"));
byte[] pinHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
using (Aes aes = Aes.Create())
{
byte[] key = keyHash.Slice(0, aes.Key.Length);
byte[] iv = pinHash.Slice(0, aes.IV.Length);
Trace.WriteLine($"Key length: { key.Length }, iv length: { iv.Length }, block mode: { aes.Mode }, padding: { aes.Padding }");
using (var stream = new MemoryStream())
using (ICryptoTransform transform = aes.CreateEncryptor(key, iv))
{
using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
await cryptStream.WriteAsync(data, 0, data.Length);
}
return stream.ToArray();
}
}
}
}
打字稿代码好像可以解密
工作fiddle:https://jsfiddle.net/uj58twrr/3/
我在用 C# 编写的服务器应用程序中使用 AES 加密了一些数据。我使用预定义密钥(32 字节)和 IV(16 字节),例如...
Key: 81fe1681..6a451c1c
IV: e83c..ae76
这是我用来加密数据的 C# 代码:
async Task<byte[]> Encrypt(string privateKey, string pin, byte[] data)
{
using (var sha = SHA256.Create())
{
byte[] keyHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{privateKey}"));
byte[] pinHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
using (Aes aes = Aes.Create())
{
byte[] key = keyHash.Slice(0, aes.Key.Length);
byte[] iv = pinHash.Slice(0, aes.IV.Length);
using (ICryptoTransform transform = aes.CreateEncryptor(key, iv))
using (var stream = new MemoryStream())
using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
await cryptStream.WriteAsync(data, 0, data.Length);
await cryptStream.FlushAsync();
return stream.ToArray();
}
}
}
}
加密的结果数据看起来像...
534c..28f5
现在,我想使用 CryptoJS 解密客户端应用程序中的数据。我使用完全相同的密钥和IV信息,但解密似乎失败了......至少解密结果总是空的。
所以,我在客户端加密数据(当然相同的密钥和IV),结果密文不同;更准确地说,它是相同的,但最后有更多数据...
534c..28f5bbd5..ac0e
如果我在服务器上加密数据,我在最后得到的附加数据是什么?
如果我在客户端解密已经加密的密文,解密就成功了。顺便提一下,mode和padding在server端和client端都是默认的,分别是CBC
和Pkcs7
;密钥大小应为 256
。这是我用来解密已被服务器加密的数据的代码:
let keyHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(privateKey));
let key: WordArray = CryptoJS.lib.WordArray.create(keyHash.words.slice(0, 8), 32);
let pinHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(pin));
let iv: WordArray = CryptoJS.lib.WordArray.create(pinHash.words.slice(0, 4), 16);
let cfg: CryptoJS.lib.IBlockCipherCfg = { iv: iv };
let paramsData: CryptoJS.lib.CipherParamsData = {
ciphertext: cipherBuffer
};
let decrypted: WordArray = CryptoJS.AES.decrypt(paramsData, key, cfg);
对于写入,块的刷新存在问题。 FlushFinalBlock()
不同于 Flush()
(或 FlushAsync()
)。你必须两者都做,或者简单地处理 CryptoStream
。这将解决代码未写入最后一个数据块的问题。
async static Task<byte[]> Encrypt(string privateKey, string pin, byte[] data)
{
using (var sha = SHA256.Create())
{
byte[] keyHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{privateKey}"));
byte[] pinHash = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
using (Aes aes = Aes.Create())
{
byte[] key = keyHash.Slice(0, aes.Key.Length);
byte[] iv = pinHash.Slice(0, aes.IV.Length);
Trace.WriteLine($"Key length: { key.Length }, iv length: { iv.Length }, block mode: { aes.Mode }, padding: { aes.Padding }");
using (var stream = new MemoryStream())
using (ICryptoTransform transform = aes.CreateEncryptor(key, iv))
{
using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
await cryptStream.WriteAsync(data, 0, data.Length);
}
return stream.ToArray();
}
}
}
}
打字稿代码好像可以解密
工作fiddle:https://jsfiddle.net/uj58twrr/3/