问题
I am working with third party API in which I have to send data in aes-128 encrypted form. For help in encryption/decryption they have given me java code. I have tried to replicate it in Node.js but i am unable to apply same encrytion as pergive java code hence I am facing error.
The working code in java is -
public class AesCryptUtil {
Cipher ecipher;
/**
* Input a string that will be md5 hashed to create the key.
*
* @return void, cipher initialized
*/
public AesCryptUtil() {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
this.setupCrypto(kgen.generateKey());
} catch (Exception e) {
e.printStackTrace();
}
}
public AesCryptUtil(String key) {
SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
this.setupCrypto(skey);
}
private void setupCrypto(SecretKey key) {
// Create an 8-byte initialization vector
byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
try {
ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// CBC requires an initialization vector
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
} catch (Exception e) {
e.printStackTrace();
}
}
// Buffer used to transport the bytes from one stream to another
byte[] buf = new byte[1024];
public void encrypt(InputStream in, OutputStream out) {
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
/**
* Input is a string to encrypt.
*
* @return a Hex string of the byte array
*/
public String encrypt(String plaintext) {
try {
byte[] ciphertext = ecipher.doFinal(plaintext.getBytes("UTF-8"));
return this.byteToHex(ciphertext);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Input encrypted String represented in HEX
**/
private static byte[] getMD5(String input) {
try {
byte[] bytesOfMessage = input.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
return md.digest(bytesOfMessage);
} catch (Exception e) {
return null;
}
}
static final String HEXES = "0123456789ABCDEF";
public static String byteToHex(byte[] raw) {
if (raw == null) {
return null;
}
String result = "";
for (int i = 0; i < raw.length; i++) {
result += Integer.toString((raw[i] & 0xff) + 0x100, 16).substring(1);
return result;
}
public static byte[] hexToByte(String hexString) {
int len = hexString.length();
byte[] ba = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
ba[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return ba;
}
public static void main(String args[]) {
String result = null;
String err = null;
String key = "DEEA29E294D8B2241FB41EF254AAB86F";
String data = "<?xml version=" + "1.0" + " encoding=" + "UTF-8" + "?><xmltagopen></xmltagclose>";
String action = "enc";
if (key == null)
err = "error: no key";
else if (key.length() < 32)
err = "error: key length less than 32 bytes";
else if (data == null || action == null)
err = "error: no data";
else if (action == null)
err = "error: no action";
else if (!action.equals("enc") && !action.equals("dec"))
err = "error: invalid action";
if (err == null) {
try {
AesCryptUtil encrypter = new AesCryptUtil(key);
if (action.equals("enc"))
result = encrypter.encrypt(data);
else
result = encrypter.decrypt(data);
} catch (Exception e) {
err = "error : Exception in performing the requested operation : " + e;
}
}
if (result != null)
System.out.println(result);
else
System.out.println(err);
}
}
I have tried to do similar in node.js but it's not working and I am getting error message from api that encryption is not correct-
const xml = '<?xml version="1.0" encoding="UTF-8"?><xmltagopen</xmltagclose>';
let key = 'DEEA29E294D8B2241FB41EF254AAB86F';
let encodeKey = crypto.createHash('md5').update(key, 'utf8').digest("hex");
console.log(encodeKey);
let ivBuffer = new Buffer.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]);
let iv = ivBuffer.toString('hex');
let cipher = crypto.createCipher('aes-128-cbc', encodeKey, iv);
let encText = cipher.update(xml, 'utf8', 'hex');
encText += cipher.final('hex');
console.log(encText);
回答1:
The deprecated crypto.createCipher function, as described in API documentation, derives the encryption 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.
For example like this:
var crypto = require( 'crypto' );
var encryptionKey = Buffer.from('DEEA29E294D8B2241FB41EF254AAB86F', 'hex');
var iv = Buffer.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]);
// better: var iv = crypto.randomBytes(16);
var cipher = crypto.createCipheriv( 'aes-128-cbc', encryptionKey, iv );
var buf1 = cipher.update( Buffer.from(data) );
var buf2 = cipher.final();
var encrypted = Buffer.concat([buf1, buf2]);
来源:https://stackoverflow.com/questions/57123473/aes-128-cbc-encrytion-decryption-using-crypto-in-node-js-not-giving-same-result