TripleDes CBC Nodejs实现问题
我需要在NodeJs中复制http://tripledes.online-domain-tools.com/中的3DS CBCencryption结果。
这是我的代码:
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的结果是:
注意结果应该是59 30 20 02 a5 8c dd 5e,但是我的代码给了我33 97 d8 b0 e3 00 d1 53。
我错过了什么?
编辑2:按照你的build议,我改变了我的代码(还添加了一些与NIST出版物的指导进行的testing):
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
每个Permutation Operation Known Answer Test
NIST的Permutation Operation Known Answer Test
工作很好,但其他几个例子(包括图像的一个)只是失败
我正在testing这个黑幕的原因是因为我的服务提供商正在使用它作为参考。
这个网站在一段时间内让我有些麻烦,好了,这里是它内部使用的实现来扩展一个24字节的密钥! 我要谈谈tripleind,但我想这将适用于本网站使用的其他algorithm
步骤1
它首先检查input的密钥是否具有它期望的长度(如果没有,则可以在该站点的底部find一个表,告诉每个encryptionalgorithm的密钥长度),如果它不会以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字节; 如果你碰巧input了这样的15个字节(112233445566778899aabbccddeeff),那就好像你input了(112233445566778899aabbccddeeff00)
第2步
在三联体的情况下,将16个字节扩展为24个字节的密钥(这是algorithm所需的密钥长度)的algorithm,这个站点有一个简单的方法来做,它复制前8个字节,并将其附加到这样的关键
key =key + key.substring(0,8);
这是3DESencryptionfunction将要使用的关键
openssl并不使用这个简单的方法,例如,open ssl使用密钥MD5的前8个字节,并将它们附加到原始密钥的16个字节,以获得3DES所需的24个字节的密钥,像这样
key = key + (MD5(key)).substring(0,8);
概要
在这个工具,如果你input密钥112233445566778899AABBCCDDEEFF
是一样的,如果你input112233445566778899AABBCCDDEEFF00
相同,如果你input112233445566778899AABBCCDDEEFF001122334455667788
如此解决你的问题,你应该给你的function,你给该网站的密钥的完整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);