当传递的字符串不是 16 字节时,我有加密模块进行字符串加密,我假设 cipher.update() 应该做一些填充并创建 16 字节字符串,但在调试 cipher.update 返回空字符串时不会发生这种情况,还有其他方法吗使用加密进行填充。
index.js
function paymentIdencryption(text)
const secret_key = "EiE0BVQle0xFjZvYOupKjFGHAcAwBaTjlZ7G7rryNos=";
const secretKeyWordArray = CCrypto.enc.Utf8.parse(secret_key);
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(secret_key, 'base64'), iv);
let encrypted = cipher.update(JSON.stringify(text), 'utf8', 'base64');
encrypted += cipher.final('base64');
const encryptedData = { iv: iv.toString('base64'), encrypted: encodeURIComponent(encrypted)};
return encryptedData.encrypted;
}
console.log(paymentIdencryption("1384220_8089105");
预期结果密钥大小:
GwJPNUfPXZZsuc0iqOFhn%2BYhMJKxXBUGl9g3iKqL8CE%3D
但它返回:jJtKhwjqS5N4ABIrZev8Ng%3D%3D
解密的Java代码
var imp = new JavaImporter(com.vordel.mime,org.json.simple.JSONObject,com.vordel.trace);
with(imp) {
function invoke(msg) {
var encodedKey = "${env.SPL.paymentMethodId.key}";
Trace.info ("env.SPL.paymentMethodId.key -- encodedKey = " + encodedKey);
var encodedPaymentInfo= msg.get("cvs.paymentMethodId");
var encryptedPaymentInfo = java.net.URLDecoder.decode(encodedPaymentInfo,"UTF-8");
var decodedKey = java.util.Base64.getDecoder().decode(encodedKey.getBytes("UTF-8"));
var decodedcipher = java.util.Base64.getDecoder().decode(encryptedPaymentInfo.getBytes("UTF-8"));
var cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
var secretKey = new javax.crypto.spec.SecretKeySpec(decodedKey, "AES");
var iv = new javax.crypto.spec.IvParameterSpec(decodedcipher,0,16);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE,secretKey,iv);
var decryptedPaymentInfo = cipher.doFinal(decodedcipher, 16, decodedcipher.length-16);
var paymentInfo = new java.lang.String(decryptedPaymentInfo,"UTF-8");
var patientId = paymentInfo.substring(paymentInfo.indexOf("_")+1, paymentInfo.length());
var paymentId = paymentInfo.substring(0, paymentInfo.indexOf("_"));
msg.put("cvs.spl.patientId",patientId);
msg.put("cvs.spl.paymentId",paymentId);
return true;
}
};
Java 代码对加密数据执行 URL 解码,然后进行 Base64 解码。结果的前 16 个字节用作 IV,其余的用作密文。
密钥是 Base64 解码的。
有了密钥和 IV,密文现在可以使用 CBC 模式下的 AES 和 PKCS#7 填充进行解密。
解密后的数据是用UTF-8解码的。
从结果字符串中提取
patientid
(_
之后的数据)和 paymentid
(_
之前的数据)。
由此可以确定加密的逻辑:
可能的 NodeJS 代码:
var crypto = require('crypto')
function paymentIdencryption(text) {
const secret_key = "EiE0BVQle0xFjZvYOupKjFGHAcAwBaTjlZ7G7rryNos=";
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(secret_key, 'base64'), iv);
const encrypted = Buffer.concat([iv, cipher.update(text, 'utf8'), cipher.final()]);
return encodeURIComponent(encrypted.toString('base64'))
}
console.log(paymentIdencryption("1384220_8089105"));
可能的输出(由于随机 IV,每次加密都会发生变化):
5I43wWYs84XQk9Pe0IMl4g%2B7s%2BgwcJrPsWo9gcX25y8%3D
用Java代码测试:
public class Main {
public static void main(String[] args) throws Exception {
var encodedPaymentInfo = "5I43wWYs84XQk9Pe0IMl4g%2B7s%2BgwcJrPsWo9gcX25y8%3D";
var encodedKey = "EiE0BVQle0xFjZvYOupKjFGHAcAwBaTjlZ7G7rryNos=";
var encryptedPaymentInfo = java.net.URLDecoder.decode(encodedPaymentInfo,"UTF-8");
var decodedKey = java.util.Base64.getDecoder().decode(encodedKey.getBytes("UTF-8"));
var decodedcipher = java.util.Base64.getDecoder().decode(encryptedPaymentInfo.getBytes("UTF-8"));
var cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
var secretKey = new javax.crypto.spec.SecretKeySpec(decodedKey, "AES");
var iv = new javax.crypto.spec.IvParameterSpec(decodedcipher,0,16);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE,secretKey,iv);
var decryptedPaymentInfo = cipher.doFinal(decodedcipher, 16, decodedcipher.length-16);
var paymentInfo = new java.lang.String(decryptedPaymentInfo,"UTF-8");
var patientId = paymentInfo.substring(paymentInfo.indexOf("_")+1, paymentInfo.length());
var paymentId = paymentInfo.substring(0, paymentInfo.indexOf("_"));
System.out.println("cvs.spl.patientId: " + patientId);
System.out.println("cvs.spl.paymentId: " + paymentId);
}
}
输出:
cvs.spl.patientId: 8089105
cvs.spl.paymentId: 1384220
等于原始纯文本的数据。