I am trying to encrypt in NodeJS.
But I am not able to achieve the same encrypted text in Node.
NodeJS code:
const Crypto = require('crypto');
const config = {
host: 'http://******',
appkey: 'app',
secret: "3b47a59e834bf11564f899586665a310", // length is 32
iv: "2192432927840278" // length is 16
}
function enCryptoAes (data, key, iv = '') {
let clearEncoding = 'utf8';
let cipherEncoding = 'base64';
let cipherChunks = [];
let algorithm = 'aes-128-cbc'
switch(key.length) {
case 16:
algorithm = 'aes-128-cbc'
break;
case 32:
algorithm = 'aes-256-cbc'
break;
}
let cipher = Crypto.createCipheriv(algorithm, key, iv);
cipher.setAutoPadding(true);
cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
cipherChunks.push(cipher.final(cipherEncoding));
return cipherChunks.join('');
}
function getParamsAesStr(params) {
let paramsArr = Object.keys(params).map(key => `${key}=${params[key]}`)
paramsArr = paramsArr.sort()
let signStr = Buffer.from(paramsArr.join('').toLowerCase(), 'utf-8').toString()
let sign = Crypto.createHmac('md5', config.secret).update(signStr).digest('hex')
let paramsStr = `${paramsArr.join('&')}&sign=${sign}`
let paramsAesStr = enCryptoAes(paramsStr, config.secret.slice(0, 16), config.iv)
paramsAesStr = Buffer.from(paramsStr, 'utf-8').toString('base64')
return paramsAesStr
}
Java code:
public class ApiParameterParser {
public static final String PARAMS_KEY = "param";
public static final String SIGN_KEY = "sign";
public static final String APPKEY_KEY = "appkey";
private static final String ENCODING = "UTF-8";
private static String secretKey = "3b47a59e834bf11564f899586665a310";
public static Map<String, Object> encodeParameters(Map params) {
if (params == null || params.size() == 0 || Strings.isNullOrEmpty(secretKey)) {
return null;
}
try {
String appkey = getParamString(params, APPKEY_KEY);
params.remove(APPKEY_KEY);
String sign = sign(params, secretKey);
params.put(SIGN_KEY, sign);
byte[] aesBytes = AESUtil.encryptByAES(
paramsToString(params, ENCODING).getBytes(ENCODING),
HMacMD5Util.hexStringToBytes(secretKey));
// base64
Base64 base64 = new Base64();
String base64Str = base64.encodeToString(aesBytes);
return base64Str;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] decryptByAES(byte[] data, byte[] secretKey) {
try {
byte[] result = null;
SecretKeySpec skey = new SecretKeySpec(processAesKey(secretKey), ENCRY_ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER_MODE);
cipher.init(Cipher.DECRYPT_MODE, skey, new IvParameterSpec(ivParameter.getBytes()));
result = cipher.doFinal(data);
return result;
} catch (Exception e) {
logger.error("AES error", e);
}
return null;
}
public static String paramsToString(Map<String, Object> params, String encoding) throws UnsupportedEncodingException {
if (params == null || params.size() == 0) {
return "";
}
Set<String> keys = params.keySet();
StringBuilder sb = new StringBuilder();
for (String k : keys) {
sb.append(k + "=" + URLEncoder.encode(getParamString(params, k), encoding) + "&");
}
return sb.toString().substring(0, sb.length() - 1);
}
public static String getParamString(Map params, String key) {
if (params == null || params.size() == 0) {
return "";
}
String buf = "";
if (params.get(key) instanceof String[]) {
buf = ((String[]) params.get(key))[0];
} else {
buf = String.valueOf(params.get(key));
}
return buf;
}
}
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESUtil {
private static String ivParameter = "2192432927840278";
private static final String ENCRY_ALGORITHM = "AES";
private static final String CIPHER_MODE = "AES/CBC/PKCS5Padding";
public static byte[] encryptByAES(byte[] data, byte[] secretKey) {
try {
byte[] result = null;
SecretKeySpec skey = new SecretKeySpec(processAesKey(secretKey), ENCRY_ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER_MODE);
cipher.init(Cipher.ENCRYPT_MODE, skey, new IvParameterSpec(ivParameter.getBytes()));
result = cipher.doFinal(data);
return result;
} catch (Exception e) {
logger.error("AES error", e);
}
return null;
}
private static byte[] processAesKey(byte[] key) {
if (key == null) {
return null;
}
int length = 16;
if (key.length == length) {
return key;
}
byte[] result = new byte[length];
if (key.length > length) {
System.arraycopy(key, 0, result, 0, length);
return result;
} else {
int i = 0;
for (byte item : key) {
result[i++] = item;
}
return result;
}
}
}
public class HMacMD5Util {
public static byte[] hexStringToBytes(String data) {
if (data == null || data.equals("")) {
return null;
}
data = data.toUpperCase();
int length = data.length() / 2;
char[] hexChars = data.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
}
When the value of params is query params:
{
pageNo: 1, pageSize: 10
}
The encrypted text general by my Node code is:
"cGFnZU5vPTEmcGFnZVNpemU9MTAmc2lnbj1kMzBhZGI0MGUxM2RlYTQzYzEzMDhkOTAzZTJkOWFjMw=="
getParamsAesStr({pageNo: 1, pageSize: 10})
I am getting a different encrypted text. I am not able to achieve the same result in NodeJs as they did in java.
And the encrypted text by Node can't decrypt by the java code ```decryptByAES`` right
What's wrong with my NodeJs code.