【发布时间】:2020-12-03 00:55:57
【问题描述】:
我尝试在 C# 中解密的数据是使用 Nodejs 中的 AES-256 算法加密的,代码如下。
const crypto = require('crypto');
const validator = require('validator');
const algorithm = 'aes256';
const inputEncoding = 'utf8';
const outputEncoding = 'hex';
const iv = crypto.randomBytes(16)
function encrypt(key,text) {
key = processKey(key);
let cipher = crypto.createCipheriv(algorithm, key, iv);
let ciphered = cipher.update(text, inputEncoding, outputEncoding);
ciphered += cipher.final(outputEncoding);
return ciphered;
}
现在我提供了长度为 32 的加密数据,如“1234567304e07a5d2e93fbeefd0e417e”和长度为 32 的密钥,如“123456673959499f9d37623168b2c977”。
我正在尝试使用下面的 c# 代码进行解密,并收到错误消息,因为“要解密的数据长度无效”。请告知。
public static string Decrypt(string combinedString, string keyString)
{
string plainText;
byte[] combinedData = StringToByteArray(combinedString);
Aes aes = Aes.Create();
aes.Key = Encoding.UTF8.GetBytes(keyString);
byte[] iv = new byte[aes.BlockSize / 8];
byte[] cipherText = new byte[combinedData.Length - iv.Length];
Array.Copy(combinedData, iv, iv.Length);
Array.Copy(combinedData, iv.Length, cipherText, 0, cipherText.Length);
aes.IV = iv;
aes.Mode = CipherMode.CBC;
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream(cipherText))
{
using (CryptoStream cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
plainText = sr.ReadToEnd();
}
}
return plainText;
}
}
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
下面是 Node.js 中的解密代码,可以正常工作
const crypto = require('../functions/crypto');
const assert = require('assert');
const { v4: uuidv4 } = require('uuid');
describe('crypto module', function() {
it('should work', function(done) {
const toHash = 'Octomate';
const hashKey = uuidv4();
const hash = crypto.encrypt(hashKey, toHash);
const decrypted = crypto.decrypt(hashKey, hash);
assert.strictEqual(toHash, decrypted);
done();
});
});
【问题讨论】:
-
请检查这里,同样的错误 - stackoverflow.com/questions/22466858/…
-
NodeJS 代码中缺少
processKey方法。如果发布一组完整的测试数据(密钥、IV、明文和密文)也会很有帮助。在任何情况下,NodeJS 代码都缺少 C# 代码中假定的 IV 和密文的连接。 -
此外,NodeJS 代码中的密文是十六进制编码的,而 C# 代码需要 Base64 编码的密文。从NodeJS代码中我也不清楚为什么密文应该以
qwerty开头,就像你的例子一样。 -
@Topaco 我故意用随机字母篡改密文,我尝试转换十六进制字符串而不是base64,现在输出为空。
-
IV 和密文的连接仍然缺失(见我的第一条评论)。在十六进制编码的情况下,这很简单:
let ciphered = iv.toString(outputEncoding); ciphered += cipher.update(text, inputEncoding, outputEncoding); ciphered += cipher.final(outputEncoding);和const outputEncoding = 'hex';。如果是 Base64 编码(最初用于 C# 代码),则改为:let ciphered = Buffer.concat([iv, cipher.update(text, inputEncoding), cipher.final()]).toString(outputEncoding);和const outputEncoding = 'base64';。
标签: c# node.js .net encryption cryptography