TripleDes CBC Nodejs实现麻烦

时间:2017-09-21 21:05:54

标签: node.js cryptography 3des 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'));

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

Note that the result should be 59 30 20 02 a5 8c dd 5e, but my code gives me 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

NIST的每个Permutation Operation Known Answer Test效果都很好,但其他一些例子(包括其中一个图片)都失败了

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

1 个答案:

答案 0 :(得分:2)

这个网站在一段时间内给我带来了一些麻烦,这里是它在内部使用的实现,将密钥扩展为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

所以例如它对3DES的期望长度是24个字节;如果你恰好输入这样的15个字节(112233445566778899aabbccddeeff),那就像你输入的那样(112233445566778899aabbccddeeff00)

<强>步骤2

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

key =key + key.substring(0,8);

这是将要使用3DES加密函数

的关键

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

key = key + (MD5(key)).substring(0,8);

<强>摘要

如果您输入密钥112233445566778899AABBCCDDEEFF,则该工具中的

与输入112233445566778899AABBCCDDEEFF00的情况相同,就像您输入112233445566778899AABBCCDDEEFF001122334455667788一样,为了解决您的问题,您应该为您的功能提供完成你给该网站的24个字节的密钥,你肯定会得到相同的结果,因为nodejs可能与openssl做同样的事情来扩展密钥(使用md5)

<强> PS 如果您正在使用cbc模式,那么尝试将IV指定为8字节的\ x00,如此“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);