node.js - Nodejs javascript implementation of PBEWithMD5AndTripleDES/CBC/PKCS5Padding -
in order write simple nodejs app talking server written in java have implement following functionality nodejs.
public class crypto { cipher decipher; byte[] salt = { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x0a, (byte) 0x0b, (byte) 0x0c, (byte) 0x0d }; int iterationcount = 10; public crypto(string pass) { try { keyspec keyspec = new pbekeyspec(pass.tochararray(), salt, iterationcount); secretkey key = secretkeyfactory.getinstance( "pbewithmd5andtripledes").generatesecret(keyspec); ecipher = cipher.getinstance("pbewithmd5andtripledes/cbc/pkcs5padding"); algorithmparameterspec paramspec = new pbeparameterspec(salt, iterationcount); decipher.init(cipher.decrypt_mode, key, paramspec); } catch (exception ex) { } } }
i use crypto
module of nodejs
var crypto = require('crypto'), pass = new buffer(wek), salt = new buffer([0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d]) password = 'mysecretpassword' key = crypto.pbkdf2(pass, salt, 10, 256) cipher, encrypted; cipher = crypto.createcipher('des-ede-cbc', key); encrypted = cipher.update(new buffer('the secred information'));
after sending encrypted information server, can't decrypt message decipher
object listed in java code sample above. think main problem md5
part. can't figure out how implement crypto
nodejs
module. has idea how solve problem? or ther other module or library achieve that?
edit: tried module nodejs: node-forge
forge = require('node-forge') var numiterations = 10, keylength = 24, password = forge.util.createbuffer('mysecretpassword'), salt = new forge.util.bytebuffer(new uint8array([0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d])), derivedkey = forge.pkcs5.pbkdf2(password, salt.getbytes(), numiterations, keylength, forge.md.md5.create()) iv = {}; // todo... ??? var cipher = forge.des.createencryptioncipher(derivedkey); cipher.start(iv); cipher.update('the secred information'); cipher.finish(); var encrypted = cipher.output;
but have several problems/questions:
- do use correct algorithm in javascript?
- is
salt
calculation match java implementation? - how can determine
keylength
used in java implementation? - how
initialization vector
generated in java implementation? in last code samplenode-forge
i have provideiv
oncipher.start(iv)
. in java code can't see how done. in opinioniv
must same on client , server or incorrect?
i reverse engineered desede part of key derivation function found @ com.sun.crypto.provider.pbes1core#derivecipherkey();
we use jasypt encryption library in java server , our node.js server able encrypt , decrypt this. hope helps (written in es2015, runs in node v4.0.0 , up):
'use strict'; var crypto = require('crypto'); class encryption { constructor() { this.privatekey = new buffer('<your password>', 'utf-8'); } encrypt(message) { var salt = crypto.randombytes(8); var key = this._generatekey(this.privatekey, salt); var cipher = crypto.createcipheriv('des-ede3-cbc', this._subbuf(key, 0, 24), this._subbuf(key, 24)); var result = cipher.update(message, 'utf-8', 'hex'); return salt.tostring('hex') + result + cipher.final('hex'); } decrypt(message) { var salt = new buffer(message.substr(0, 16), 'hex'); var key = this._generatekey(this.privatekey, salt); message = message.substr(16); var decipher = crypto.createdecipheriv('des-ede3-cbc', this._subbuf(key, 0, 24), this._subbuf(key, 24)); var result = decipher.update(message, 'hex', 'utf-8'); return result + decipher.final('utf-8'); } _generatekey(password, salt) { if (!(password instanceof buffer)) { throw new error('password needs buffer'); } if (!(salt instanceof buffer) || salt.length != 8) { throw new error('salt needs 8 byte buffer'); } var iterations; for(iterations = 0; iterations < 4 && salt[iterations] == salt[iterations + 4]; ++iterations) {} if(iterations == 4) { for(iterations = 0; iterations < 2; ++iterations) { var tmp = salt[iterations]; salt[iterations] = salt[3 - iterations]; salt[2] = tmp; // seems error have live } } var result = new buffer(32); for(iterations = 0; iterations < 2; ++iterations) { var intermediate = new buffer(salt.length / 2); (let = 0; < salt.length / 2; i++) { intermediate[i] = salt[iterations * (salt.length / 2) + i]; } for(let = 0; < 1000; ++i) { var hash = crypto.createhash('md5'); hash.update(intermediate); hash.update(password); intermediate = hash.digest(); } (let = 0; i<intermediate.length; i++) { result[i + (iterations * 16)] = intermediate[i]; } } return result; } _subbuf(buffer, start, length) { if (!length) { length = buffer.length - start; } var result = new buffer(length, 'hex'); (let = 0; < length; i++) { result[i] = buffer[i + start] } return result; } }
to explain little what's going on:
- encrypted messages returned in hex format, else might fit implementation better.
- the _generatekey() direct copy java source.
- the keys used 32 byte length , assume first 24 bytes keys tripledes , last 8 salt
- the generated message prefixed random generated salt used encrypt message.
- depending on security settings of jvm might possible not using des-ede3 (cbc seems fixed setting). should double check if works setup.
some code clean might necessary here, should @ least started in right direction.
Comments
Post a Comment