TripleDes CBC Nodejs 实现问题

Ale*_*uez 2 3des cryptography node.js cbc-mode

我需要在 Nodejs 中复制http://tripledes.online-domain-tools.com/中 3DS CBC 加密的结果。

这是我的代码:

const crypto = require('crypto');
const cipher = crypto.createCipher('des-ede3-cbc', key);
password = Buffer.from('MYPASS', 'utf8');

let encrypted = [cipher.update(password)];
encrypted.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
console.log(encrypted.toString('hex'));
Run Code Online (Sandbox Code Playgroud)

Tripdes.online-domain-tools.com 的结果是:

请注意,结果应该是 59 30 20 02 a5 8c dd 5e,但我的代码给了我 33 97 d8 b0 e3 00 d1 53

请注意,结果应该是 59 30 20 02 a5 8c dd 5e,但我的代码给出了 33 97 d8 b0 e3 00 d1 53。

我缺少什么?

Edit2:根据您的建议,我更改了我的代码(还添加了一些根据 NIST 出版物的指南进行的测试):

const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
    let shortkey = Buffer.from(inputkey, keyformat);
    let key = Buffer.alloc(24);
    key.fill('\0');
    for (i = 0; i < shortkey.length; i++) {
        key[i] = shortkey[i];
    }
    let IV = Buffer.alloc(8);
    const cipher = crypto.createCipheriv('des-ede3-cbc', key, IV);
    password = Buffer.from(password, passwordformat);

    let encryptedArr = [cipher.update(password)];
    encryptedArr.push(cipher.final());
    encrypted = Buffer.concat(encryptedArr);
    return encrypted;
}

console.log(encrypt('1046913489980131','hex','0000000000000000','hex')); // works 
console.log(encrypt('1007103489988020','hex','0000000000000000','hex')); // works
console.log(encrypt('10071034C8980120','hex','0000000000000000','hex')); // works
console.log(encrypt('1046103489988020','hex','0000000000000000','hex')); // works
console.log(encrypt('MYKEY','utf8','MYPASS','utf8')); // fails
Run Code Online (Sandbox Code Playgroud)

NIST 的每个Permutation Operation Known Answer Test示例都运行良好,但其他几个示例(包括图像中的示例)却失败了

我使用这个可疑页面进行测试的原因是因为我的服务提供商正在使用它作为参考。

ach*_*ahe 5

这个网站给我带来了一些麻烦一段时间了,这里是它内部使用的实现,将密钥扩展为 24 字节!我要谈论三元组,但我想这也适用于该网站使用的其他算法

步骤1

它首先检查输入的密钥是否具有预期的长度(您可以在该站点底部找到一个表格,告知每个加密算法的密钥长度)如果没有,它将以如下字节0x00完成:

var key;// is a string containing the bytes wich will be used to encrypt  the msg
var nullByte = 0x00;
var padding_needed;
for (var i=key.length ;i < expected_key_length ; ++) 
{padding_needed =padding_needed + nullBute.tostring(16);  }
key = key + padding_needed
Run Code Online (Sandbox Code Playgroud)

例如,3DES 期望的长度是 24 个字节;如果你碰巧只输入了这样的 15 个字节 (112233445566778899aabbccddeeff) 就会像你输入了 (112233445566778899aabbccddeeff00)

第2步

在三元组的情况下,算法将 16 字节扩展为 24 字节密钥(这是算法所需的密钥长度),该站点有一个简单的方法来执行此操作,它复制前 8 个字节并将其附加到密钥的末尾像这样的键

key =key + key.substring(0,8);
Run Code Online (Sandbox Code Playgroud)

这就是将要提供给 3DES 加密函数使用的密钥

openssl 不使用这种简单的方法,例如,open ssl 使用密钥的 MD5 的前 8 个字节,并将它们附加到原始密钥的 16 个字节以获得 3DES 所需的 24 个字节密钥,如下所示

key = key + (MD5(key)).substring(0,8);
Run Code Online (Sandbox Code Playgroud)

概括

在该工具中,如果您输入的密钥112233445566778899AABBCCDDEEFF 与您输入的密钥相同112233445566778899AABBCCDDEEFF00,并且与您输入的密钥相同,112233445566778899AABBCCDDEEFF001122334455667788那么为了解决您的问题,您应该为您的函数提供您提供给该站点的完整 24 字节密钥,您肯定会得到相同的结果结果,因为nodejs可能正在做与openssl相同的事情来扩展密钥(使用md5)

PS 如果你使用的是cbc模式,这就是你的情况,尝试将IV指定为\x00的8个字节,就像这样“0000000000000000”,结果将是相同的!

这是您的代码的有效实现,您可以在站点中查看它

    const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
    let shortkey = Buffer.from(inputkey, keyformat);
    let key = Buffer.alloc(24);
    key.fill('\0');
    for (i = 0; i < shortkey.length; i++) {
        key[i] = shortkey[i];
    }
    let IV = Buffer.alloc(8);


    var expansionStart = shortkey.length>16?shortkey.length:16;
    for (i=expansionStart;i<24;i++){
        key[i]=key[i-expansionStart];
    } 
    console.log(key);
    const cipher = crypto.createCipheriv('des-ede3-cbc', key, IV);
    password = Buffer.from(password, passwordformat);

    let encryptedArr = [cipher.update(password)];
    encryptedArr.push(cipher.final());
    encrypted = Buffer.concat(encryptedArr);
    return encrypted;
    }
    var enc = encrypt("112233445566778899AABBCCDDEEFF","hex","password","utf8");
    console.log(enc);
Run Code Online (Sandbox Code Playgroud)