Here is my code:
const crypto = require('crypto')
let enterJS = 'h';
let enterStr = null;
enterStr = encrypt(enterJS, 'des-ecb').toUpperCase();
console.log("===============>>>> ENTER STR : " + enterStr);
function encrypt(plaintext, algorithm) {
var keyStr = "imtestKey";
var key = new Buffer(keyStr);
var cipher = crypto.createCipher(algorithm, key);
cipher.setAutoPadding(true);
var ciph = cipher.update(plaintext, 'ascii');
var ciphf = cipher.final();
return ciph.toString('hex') + ciphf.toString('hex');
}
But the result I got is:
===============>>>> ENTER STR : 16CE7F2DEB9BB56D
which the right result I test on this web: http://tool.chacuo.net/cryptdes
des-mode:ecb
fill-mode:pkcs7padding
password:imtestKey
output:hex
The right result (the same with my java code) is
832e52ebd3fb9059
My node version is v8.9.0, how can I get the right result?
This is my java code:
import java.lang.StringBuilder;
import javax.crypto.Cipher;
import java.security.SecureRandom;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
public class Test {
public static void main(String[] args) {
String js = "h";
try {
byte[] bs = encrypt(js.getBytes(), "imtestKey".getBytes());
System.out.println(byte2hex(bs));
} catch(Exception ex) {
}
}
public static byte[] encrypt(byte[] src, byte[] key) throws Exception {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
return cipher.doFinal(src);
}
public static String byte2hex(byte[] b) {
StringBuilder sb = new StringBuilder();
String stmp = "";
for(int n = 0; b != null && n < b.length; ++n) {
stmp = Integer.toHexString(b[n] & 255);
if (stmp.length() == 1) {
sb.append("0").append(stmp);
} else {
sb.append(stmp);
}
}
return sb.toString().toUpperCase();
}
}
Security aspects aside (as has been pointed out, DES and ECB, as well as no key derivation is insecure), you are using a deprecated crypto.createCipher()
function which derives a key from the provided password.
The implementation of
crypto.createCipher()
derives keys using the OpenSSL functionEVP_BytesToKey
with the digest algorithm set to MD5, one iteration, and no salt. The lack of salt allows dictionary attacks as the same password always creates the same key. The low iteration count and non-cryptographically secure hash algorithm allow passwords to be tested very rapidly.
Use crypto.createCipheriv()
instead, which uses the provided key as-is:
const crypto = require('crypto')
let enterJS = 'h';
let enterStr = null;
function encrypt(plaintext, algorithm) {
var keyStr = "imtestKey";
var key = Buffer.alloc(8, keyStr);
var cipher = crypto.createCipheriv(algorithm, key, Buffer.alloc(0));
cipher.setAutoPadding(true);
var ciph = cipher.update(Buffer.from(plaintext));
var ciphf = cipher.final();
return Buffer.concat([ciph, ciphf]).toString('hex');
}
enterStr = encrypt(enterJS, 'des-ecb').toUpperCase();
console.log("===============>>>> ENTER STR : " + enterStr);
The createCipheriv
API will reject your 9-byte long key, because DES requires an 8-byte key. I made a workaround to take the first 8 bytes from the provided password as the key and now it's printing your desired result.
Output:
===============>>>> ENTER STR : 832E52EBD3FB9059