Skip to content

Instantly share code, notes, and snippets.

@qzaidi
Last active June 1, 2020 22:09
Show Gist options
  • Save qzaidi/5401800 to your computer and use it in GitHub Desktop.
Save qzaidi/5401800 to your computer and use it in GitHub Desktop.
Emulates Java's insecure PBEWITHMD5ANDDES with node.js crypto. Useful for interop with old java programs.
"use strict";
/*
* Emulates Java's PBEWITHMD5ANDDES for node.js
*/
var crypto = require('crypto');
var pbewithmd5anddes = {
KDF: function(password,salt,iterations) {
var pwd = new Buffer(password,'utf-8');
var key = Buffer.concat([pwd, salt]);
var i;
for (i = 0; i < iterations; i+=1) {
key = crypto.createHash("md5").update(key).digest();
}
return key;
},
getKeyIV: function(password,salt,iterations) {
var key = this.KDF(password,salt,iterations);
var keybuf = new Buffer(key,'binary').slice(0,8);
var ivbuf = new Buffer(key,'binary').slice(8,16);
return [ keybuf, ivbuf ];
},
encrypt: function(payload,password,salt,iterations,cb) {
var kiv = this.getKeyIV(password,salt,iterations);
var cipher = crypto.createCipheriv('des', kiv[0],kiv[1]);
var encrypted = [];
encrypted.push(cipher.update(payload,'utf-8','hex'));
encrypted.push(cipher.final('hex'));
return cb(undefined,new Buffer(encrypted.join(''),'hex').toString('base64'));
},
decrypt: function(payload,password,salt,iterations,cb) {
var encryptedBuffer = new Buffer(payload,'base64');
var kiv = this.getKeyIV(password,salt,iterations);
var decipher = crypto.createDecipheriv('des', kiv[0],kiv[1]);
var decrypted = [];
decrypted.push(decipher.update(encryptedBuffer));
decrypted.push(decipher.final());
return cb(undefined, decrypted.join(''));
}
};
module.exports = pbewithmd5anddes;
/* ---------------- TEST CODE ---------------- */
(function() {
if (require.main === module) {
var password = 'test';
var iterations = 19;
var salt = new Buffer('d99bce325735e303','hex');
pbewithmd5anddes.encrypt('helloworld',password,salt,iterations,function(err,msg) {
console.log('encrypted: ' + msg);
// eat your own dogfood
pbewithmd5anddes.decrypt(msg,password,salt,iterations,function(err,msg) {
console.log('decrypted: ' + msg);
});
});
}
}());
@neilhan
Copy link

neilhan commented Jan 12, 2016

Thanks for sharing.

@NinhvanLuyen
Copy link

i have a codes below
public class Class_EncryptedDecrypted {

private final String key = "ezeon8547";
private Cipher ecipher, dcipher;
private final byte[] salt = {
    (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
    (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
};
private final int iterationCount = 19;

public String Encrypted(String plainText) {
    if (plainText != null && !plainText.isEmpty()) {
        try {
            //Key generation for enc and desc
            KeySpec keySpec = new PBEKeySpec(key.toCharArray(), salt, iterationCount);
            SecretKey scr_key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
            // Prepare the parameter to the ciphers
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

            //Enc process
            ecipher = Cipher.getInstance(scr_key.getAlgorithm());
            ecipher.init(Cipher.ENCRYPT_MODE, scr_key, paramSpec);
            String charSet = "UTF-8";
            byte[] in = plainText.getBytes(charSet);
            byte[] out = ecipher.doFinal(in);
            String encStr = new sun.misc.BASE64Encoder().encode(out);
            return encStr;
        } catch (NoSuchAlgorithmException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (InvalidKeySpecException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (NoSuchPaddingException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (InvalidKeyException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (InvalidAlgorithmParameterException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (UnsupportedEncodingException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (IllegalBlockSizeException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        } catch (BadPaddingException ex) {
            Class_InsertErrorApp.insertErrorApp("Encrypted", new Exception().getStackTrace()[0].getMethodName(), ex.toString());
        }
    }
    return null;
}

..////

//// how to convert var salt = new Buffer('d99bce325735e303','hex'); to --> private final byte[] salt = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
};

@justinpage
Copy link

@NinhvanLuyen you would do the following:

const salt = Buffer.from([0xA9, 0x9B, 0xC8, 0x32, 0x56, 0x35, 0xE3, 0x03]);

Notice I'm using the recommended Buffer.from([array]) instead of a constructor according to https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_array

@Alessio22
Copy link

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment