TripleDes CBC Nodejs 实现问题

TripleDes CBC Nodejs implementation throuble

我需要在 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-域-tools.com的结果是:

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

我错过了什么?

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

const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
    let shortkey = Buffer.from(inputkey, keyformat);
    let key = Buffer.alloc(24);
    key.fill('[=11=]');
    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 都很好,但其他几个示例(包括图像之一)都失败了

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

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

步骤 1

它首先检查输入的密钥是否具有预期的长度,(您可以在该站点的底部找到一个 table,告诉每个加密算法的密钥长度) 如果没有,它将以 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个字节以获得所需的24个字节的密钥通过 3DES,像这样

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

总结

在该工具中,如果您输入密钥 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('[=13=]');
    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);