【问题标题】:triple des encrypt c# and decrypt in javascript三重des加密c#并在javascript中解密
【发布时间】:2015-03-30 12:30:46
【问题描述】:

我有一个需要在 node.js 中解密的 C# 加密字符串。我目前正在使用 cryptoJS 作为解密器。

以下是最初在 C# 中加密字符串的代码:

CryptoAgent 构造函数使用 Guid 构建算法密钥和初始化向量。例如,“A925B4D6-A8D0-11E4-BA34-AC7BA1ACF56B”。

public CryptoAgent(Guid keyGuid)
    {
        _UseSymmetricEncryption = true;
        byte[] guidArr = keyGuid.ToByteArray();
        Array.Resize<byte>(ref guidArr, 24);
        _Key = (byte[])guidArr.Clone();
        Array.Reverse(guidArr);
        _IV = guidArr;
    }

加密方法非常简单。它采用纯文本并使用上面创建的密钥和 iv 加密数据,然后以 URL 友好字符串的形式返回。例如, “Email=testuser@gmail.com&ProductUserId=C4B80D7F-A8D0-11E4-BA34-AC7BA1ACF56B

private string EncryptSymmetric(string plainText)
    {
        if (string.IsNullOrEmpty(plainText))
        {
            throw new ArgumentNullException("The string to be encrypted cannot be null.");
        }
        ICryptoTransform transform;
        TripleDESCryptoServiceProvider csp = new TripleDESCryptoServiceProvider();
        transform = csp.CreateEncryptor(_Key, _IV);
        MemoryStream memoryStream = new MemoryStream();
        CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write);
        byte[] plaintextBytes = Encoding.Unicode.GetBytes(plainText);
        cryptoStream.Write(plaintextBytes, 0, plaintextBytes.Length);
        cryptoStream.FlushFinalBlock();
        byte[] encryptedData = memoryStream.GetBuffer();
        Console.WriteLine(csp.Mode);
        Console.WriteLine(csp.Padding);
        return UrlNormalize(Convert.ToBase64String(encryptedData, 0, (int)memoryStream.Length));
    }

生成的加密字符串如下:

ZuD6CIEY6b-sh9Q6DRh9SWE0YyC92Jmw1oplTqy7kjETXoNio42hoJxDmMr7V-Sp14aX9lwTxYBM_KjA bEevEE_7nUzC_C4nM13LHHbpg6aR8xO39RseQjpLCLYj5ZKKWiXZREqpvDBlvtF-F1VuqyAMA0ECYOD N8ZCcmmyIHuCpalcUkLZ0zZajwutIrtmmqg3VXQNT3E~​​m>

我的任务是接收此加密字符串并在 node.js 中解密该字符串并解析出两个参数以供进一步使用。以下是我的初始解密文件:

var CryptoJS = require("crypto-js");

var text = "Email=testuser@gmail.com&ProductUserId=C4B80D7F-A8D0-11E4-BA34-AC7BA1ACF56B";
var key = "A925B4D6-A8D0-11E4-BA34-AC7BA1ACF56B";
var useHashing = true;

if (useHashing){
   key = CryptoJS.MD5(key).toString();
   key = key + '0000000000000000';
}

var textWordArray = CryptoJS.enc.Utf16.parse(text);
var keyHex = CryptoJS.enc.Hex.parse(key);

var iv = reverseHexString(keyHex.toString());
var ivHex = CryptoJS.enc.Hex.parse(iv);

console.log('hexadecimal key: ' + keyHex + '\n');

console.log('hexadecimal iv: ' + ivHex + '\n');

var options = {
    mode: CryptoJS.mode.CBC, 
    padding: CryptoJS.pad.Pkcs7,
    iv: ivHex
};

var encrypted = CryptoJS.TripleDES.encrypt(textWordArray, keyHex, options);

var base64String = encrypted.toString();

console.log('base64: ' + base64String + '\n');

var decrypted = CryptoJS.TripleDES.decrypt( {
    ciphertext: CryptoJS.enc.Base64.parse(base64String)
}, keyHex, options);

console.log('decrypted: ' + decrypted.toString(CryptoJS.enc.Utf16));

function reverseHexString(hexStr) {
    var first32 = hexStr.substring(0, 32);
    var reverseFirst32 = first32.split("").reverse().join("").split("");

    var reverseHex = '0000000000000000';

    for (var i = 0; i < reverseFirst32.length; i+=2) {
        reverseHex += reverseFirst32[i+1];
        reverseHex += reverseFirst32[i];
    };

    return reverseHex;
}

我最初的解决方案导致解密失败并产生一行问号。

使用 C# 代码,我能够打印出 key 和 iv 值。我试图用 C# 打印的 key 和 iv 值替换 keyHex 和 ivHex Javascript 值,但解密仍然失败。

非常感谢您提供的任何帮助。

谢谢

【问题讨论】:

标签: javascript c# node.js cryptojs tripledes


【解决方案1】:

这不起作用的原因可能是密钥生成:您使用 ASCII 零而不是 \0,并且您有 16 个而不是 8 个(MD5 提供 16 个字节,而您想要一个 24 字节的 TDES 密钥)。这对密钥来说还不错,因为 CryptoJS 只会忽略额外的字节,但是由于您反转密钥以获取 IV,因此您会得到错误的 IV。

【讨论】:

  • 我不使用 C#,因此无法对其进行测试,但我建议您通过以十六进制或其他某种编码方式打印到控制台来检查两种语言之间的密钥和 IV 是否匹配。
  • 长话短说,我使用 C# encrypt 函数打印出正在使用的原始 Key 和 IV 值,并将它们硬编码到我的 node.js 解密文件中。最后一块拼图是使用 Utf16LE 编码而不是 Utf16。 @artjom-b 感谢您的帮助。减少零点让我走上了正确的道路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2014-02-26
相关资源
最近更新 更多