在.NET中进行AES加密,然后使用Node.js的crypto模块解密?

3
我将尝试在 Mono C# 中加密一些数据,发送到 NodeJS 服务器并在那里解密。我正在努力找出要使用哪些算法来匹配两者。
我发送的加密字符串使用 base64 编码。因此,在 JavaScript 中,我可以执行以下操作,其中我知道用于在 C# 应用程序中加密数据的密钥:
var decipher = crypto.createDecipher('aes192',binkey, biniv);
var dec = decipher.update(crypted,'base64','utf8');
dec += decipher.final('utf8');
console.log("dec", dec);

在Mono中,我使用以下代码创建Cypher:

using System.Security.Cryptography;
using (Aes aesAlg = Aes.Create("aes192"))

我需要传递正确的字符串给Aes.Create(),以便它使用相同的算法,但我找不到应该是什么。似乎"aes192"不正确。
我并不需要aes192,那只是一个尝试。如果有意义的话,请建议一种不同的加密方式。安全性不是很重要。
这里是.NET和Nodejs文档的链接: http://msdn.microsoft.com/en-us/library/system.security.cryptography.aes.aspx http://nodejs.org/api/crypto.html

在什么样的情况下你需要进行保护?我认为在这种情况下使用TLS可能更好。 - ntoskrnl
由于您的问题似乎是与 .net 有关,而不是 js。如何从 c# 开始使用 AES 然后 HMac 或 AES-GCM https://dev59.com/RHVC5IYBdhLWcg3wtzut#10366194,然后再解决您的 JS。 - jbtule
@ntoskrnl 我正在使用这个来实现许可证激活的挑战响应模式。 - Thijs Koerselman
@jbtule 在C#中进行加密/解密是可以的,使用参考示例代码即可。所以我已经有了一个加密字符串,只是在Node.js端无法解密。 - Thijs Koerselman
3个回答

1

这段代码适用于我的Node.js端,但请替换静态iv,否则aes加密将毫无意义。

var crypto = require('crypto');

function encrypt(data, key) {
    key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'),
        cipher = crypto.createCipheriv('aes-256-cbc', key.toString('binary'), str_repeat('\0', 16));
    cipher.update(data.toString(), 'utf8', 'base64');
    return cipher.final('base64');
}

function decipher(data, key) {
    key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'),
        decipher = crypto.createDecipheriv('aes-256-cbc', key.toString('binary'), str_repeat('\0', 16));
    decipher.update(data, 'base64', 'utf8');
    return decipher.final('utf8');
}

function str_repeat(input, multiplier) {
    var y = '';
    while (true) {
        if (multiplier & 1) {
            y += input;
        }
        multiplier >>= 1;
        if (multiplier) {
            input += input;
        } else {
            break;
        }
    }
    return y;
}

我希望这能帮到您。

注意:您需要提供一个 265 位,也就是 32 个字符的密钥才能使此算法正常工作。

可能的 .NET 解决方案:这可能会对您有所帮助 示例


太好了!我已经有一段时间没有试过这个了,但我仍然需要回到这个上面 :) - Thijs Koerselman
很高兴它能帮到你。 - Maximilian Walter

0

结果证明这是一个愚蠢的错误。我以为Node.js中的create函数可以接受可变参数数量。结果发现你需要调用createDecipheriv()。

仅供参考,您可以通过查看Aes对象中的这些属性轻松检查填充和模式。默认值为CBC和PKCS7。该填充也用于nodejs加密。因此,对于128位密钥大小,我的代码解密base64编码的字符串将是:

var crypto = require('crypto');
var binkey = new Buffer(key, 'base64');
var biniv = new Buffer(iv, 'base64');
var decipher = crypto.createDecipheriv('aes-128-cbc', binkey, biniv);
var decrypted = decipher.update(crypted,'base64','utf8');
decrypted += decipher.final('utf8');
console.log("decrypted", decrypted);

0

你只需要写 new AesManaged()
不需要调用 Create()

然后你需要设置 KeyIV,接着调用 CreateDecryptor() 并将其放入一个 CryptoStream 中。


好的,你可以用不同的代码编写方式,但我知道如何使用密钥和IV进行加密。我的问题是如何选择AES加密算法版本,以便在Node.js中进行解密匹配。还是我漏掉了什么? - Thijs Koerselman
与此同时,我已经了解到数字是密钥大小,并且您可以使用C#中的KeySize从aes对象查询它,结果为256字节。但是,当我在nodejs中尝试使用'aes-256-cbc'或'aes-256'时,我会收到此错误TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length。我将进一步调查... - Thijs Koerselman
@0x80 你需要匹配操作模式和填充方式两边。最好明确指定它们,以免依赖于实现特定的行为。 - ntoskrnl
CryptoStream 只在处理大量数据时有用,其中您不希望整个输入/输出保存在单个数组中。 - CodesInChaos
@ntoskrnl 有没有提示我在哪里/如何指定填充和操作模式的地方?例如,NodeJS加密模块似乎没有引用它们。 - Thijs Koerselman
@0x80 看起来你可以在 crypto.createCipher() 调用中指定操作模式(例如 crypto.createCipher('aes-128-cbc'))。你可以使用 crypto.getCiphers() 列出所有支持的算法。这些加密模块似乎默认使用 PKCS#7 填充。 - ntoskrnl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接