在节点 js 中通过 AES/GCM/NoPadding 算法使用密钥和 iv 加密有效负载并在 java 中解密
Encrypt payload using a key and iv by AES/GCM/NoPadding algorithm in node js and decrypt in java
我已使用 node.js 加密文件并在 JAVA 中解密。解密是在 JAVA 中使用 "AES/GCM/Nopadding" 算法完成的,它是第三方应用程序,因此我看不到 JAVA 代码。
我正在使用 "aes-128-gcm" 算法对 node.js 中的有效负载进行加密。
为此,我尝试模仿有效的 java 加密代码
我尝试过加密和节点伪造。
我正在获取输出,但在提交负载时出现错误 "Bad encryption - payload is not encrypted properly"。
请帮助我找出我在这段代码中做错了什么。
java
中的工作代码
public void encrypt(@NonNull final byte[] payload, @NonNull final byte[] key) throws GeneralSecurityException
{
SecretKeySpec codingKey = new SecretKeySpec(key, AES);
Cipher cipher = AEC_GCM_THREAD_CIPHER.get();
byte[] iv = new byte[cipher.getBlockSize()];
RANDOM.nextBytes(iv);
cipher.init(Cipher.ENCRYPT_MODE, codingKey, new IvParameterSpec(iv));
final byte[] encryptedPayload = cipher.doFinal(payload);
byte[] encryptMerchantKey = encryptMerchantKey(key);
String payloadFinal = encodeToUrlString(encryptedPayload); // final payload
String ivFinal = encodeToUrlString(iv); // final iv
String keyFinal = encodeToUrlString(encryptMerchantKey); // final key
System.out.println("Payload");
System.out.println(payloadFinal);
System.out.println("iv");
System.out.println(ivFinal);
System.out.println("key");
System.out.println(keyFinal);
}
我在节点 js 中尝试过的代码
function encrypt(payload) {
let key = forge.random.getBytesSync(16);
let iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({ iv: iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = forge.util.encode64(cipher.output.getBytes());
let tag = forge.util.encode64(cipher.mode.tag.getBytes());
let iv64 = forge.util.encode64(iv);
let encryptedPayload = encrypted+tag;
//RSA Encryption
encryptedkey = RSAencrypt(forge.util.encode64(key));
return {
"payload" : base64url.fromBase64(encryptedPayload) ,
"iv" : base64url.fromBase64(iv64).length,
"key" : base64url.fromBase64(encryptedkey)
};
}
RSA 描述工作正常,能够解密密钥。
aes加密的一些问题。如代码所示,我将身份验证标签和加密数据一起添加但没有用。
问题在于伪造缓冲区需要转换为节点缓冲区
此代码现在正在运行。谢谢@Maarten Bodewes 的建议。
function encrypt(payload) {
//initialize forge random buffer
var key = forge.random.getBytesSync(16);
var iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({iv : iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = cipher.output.data;
let tag = cipher.mode.tag.data;
let encryptedLoad = encrypted+tag;
// node buffer and forge buffer differ, so the forge buffer must be converted to node Buffer
iv = Buffer.from(iv, "binary");
encryptedLoad = Buffer.from(encryptedLoad, "binary");
//Calling RSA Encryption
encryptedKey = RSAencrypt(key);
return {
"payload" : base64url(encryptedLoad) ,
"iv" : base64url(iv),
"key" : base64url.fromBase64(encryptedKey)
};
}
我在angular和java里面有完整的加解密例子,你可以照着这个例子,根据你的情况修改
使用命令“npm install node-forge”安装 node-forge。
encrypt(msg, pass) {
const key = CryptoJS.lib.WordArray.random(8).toString();
const iv = CryptoJS.lib.WordArray.random(8).toString();
// encrypt some bytes using GCM mode
const cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({
iv: iv,
additionalData: 'nvn', // optional
tagLength: 128 // optional, defaults to 128 bits
});
cipher.update(forge.util.createBuffer(msg));
cipher.finish();
const encrypted = cipher.output;
const encodedB64 = forge.util.encode64(encrypted.data);
const tag = cipher.mode.tag;
const tagB64 = forge.util.encode64(tag.data);
// outputs encrypted hex
const trasmitmsg = key+iv+tagB64+encodedB64;
return trasmitmsg
}
我使用 CryptoJS 生成随机字符串,因为 node-forge 随机给出不可传输的字符串。
java 解密此传输消息的代码是
public String getDecrypt(String transmsg) throws Exception {
String keyString = transmsg.substring(0, 16);
String ivString = transmsg.substring(16, 32);
String additionalString = transmsg.substring(32, 56);
String cipherString = transmsg.substring(56);
byte[] keyBytes = keyString.getBytes();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
byte[] ivBytes = ivString.getBytes();
byte[] one = Base64.getDecoder().decode(cipherString);
byte[] two = Base64.getDecoder().decode(additionalString);
byte[] cipherText = ArrayUtils.addAll(one, two);
return decrypt(cipherText, key, ivBytes);
}
public static String decrypt(byte[] cipherText, SecretKey key, byte[] IV) throws Exception {
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH , IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
cipher.updateAAD("nvn".getBytes());
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
干杯!!!
我已使用 node.js 加密文件并在 JAVA 中解密。解密是在 JAVA 中使用 "AES/GCM/Nopadding" 算法完成的,它是第三方应用程序,因此我看不到 JAVA 代码。 我正在使用 "aes-128-gcm" 算法对 node.js 中的有效负载进行加密。 为此,我尝试模仿有效的 java 加密代码
我尝试过加密和节点伪造。 我正在获取输出,但在提交负载时出现错误 "Bad encryption - payload is not encrypted properly"。
请帮助我找出我在这段代码中做错了什么。
java
中的工作代码public void encrypt(@NonNull final byte[] payload, @NonNull final byte[] key) throws GeneralSecurityException
{
SecretKeySpec codingKey = new SecretKeySpec(key, AES);
Cipher cipher = AEC_GCM_THREAD_CIPHER.get();
byte[] iv = new byte[cipher.getBlockSize()];
RANDOM.nextBytes(iv);
cipher.init(Cipher.ENCRYPT_MODE, codingKey, new IvParameterSpec(iv));
final byte[] encryptedPayload = cipher.doFinal(payload);
byte[] encryptMerchantKey = encryptMerchantKey(key);
String payloadFinal = encodeToUrlString(encryptedPayload); // final payload
String ivFinal = encodeToUrlString(iv); // final iv
String keyFinal = encodeToUrlString(encryptMerchantKey); // final key
System.out.println("Payload");
System.out.println(payloadFinal);
System.out.println("iv");
System.out.println(ivFinal);
System.out.println("key");
System.out.println(keyFinal);
}
我在节点 js 中尝试过的代码
function encrypt(payload) {
let key = forge.random.getBytesSync(16);
let iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({ iv: iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = forge.util.encode64(cipher.output.getBytes());
let tag = forge.util.encode64(cipher.mode.tag.getBytes());
let iv64 = forge.util.encode64(iv);
let encryptedPayload = encrypted+tag;
//RSA Encryption
encryptedkey = RSAencrypt(forge.util.encode64(key));
return {
"payload" : base64url.fromBase64(encryptedPayload) ,
"iv" : base64url.fromBase64(iv64).length,
"key" : base64url.fromBase64(encryptedkey)
};
}
RSA 描述工作正常,能够解密密钥。 aes加密的一些问题。如代码所示,我将身份验证标签和加密数据一起添加但没有用。
问题在于伪造缓冲区需要转换为节点缓冲区 此代码现在正在运行。谢谢@Maarten Bodewes 的建议。
function encrypt(payload) {
//initialize forge random buffer
var key = forge.random.getBytesSync(16);
var iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({iv : iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = cipher.output.data;
let tag = cipher.mode.tag.data;
let encryptedLoad = encrypted+tag;
// node buffer and forge buffer differ, so the forge buffer must be converted to node Buffer
iv = Buffer.from(iv, "binary");
encryptedLoad = Buffer.from(encryptedLoad, "binary");
//Calling RSA Encryption
encryptedKey = RSAencrypt(key);
return {
"payload" : base64url(encryptedLoad) ,
"iv" : base64url(iv),
"key" : base64url.fromBase64(encryptedKey)
};
}
我在angular和java里面有完整的加解密例子,你可以照着这个例子,根据你的情况修改
使用命令“npm install node-forge”安装 node-forge。
encrypt(msg, pass) {
const key = CryptoJS.lib.WordArray.random(8).toString();
const iv = CryptoJS.lib.WordArray.random(8).toString();
// encrypt some bytes using GCM mode
const cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({
iv: iv,
additionalData: 'nvn', // optional
tagLength: 128 // optional, defaults to 128 bits
});
cipher.update(forge.util.createBuffer(msg));
cipher.finish();
const encrypted = cipher.output;
const encodedB64 = forge.util.encode64(encrypted.data);
const tag = cipher.mode.tag;
const tagB64 = forge.util.encode64(tag.data);
// outputs encrypted hex
const trasmitmsg = key+iv+tagB64+encodedB64;
return trasmitmsg
}
我使用 CryptoJS 生成随机字符串,因为 node-forge 随机给出不可传输的字符串。
java 解密此传输消息的代码是
public String getDecrypt(String transmsg) throws Exception {
String keyString = transmsg.substring(0, 16);
String ivString = transmsg.substring(16, 32);
String additionalString = transmsg.substring(32, 56);
String cipherString = transmsg.substring(56);
byte[] keyBytes = keyString.getBytes();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
byte[] ivBytes = ivString.getBytes();
byte[] one = Base64.getDecoder().decode(cipherString);
byte[] two = Base64.getDecoder().decode(additionalString);
byte[] cipherText = ArrayUtils.addAll(one, two);
return decrypt(cipherText, key, ivBytes);
}
public static String decrypt(byte[] cipherText, SecretKey key, byte[] IV) throws Exception {
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH , IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
cipher.updateAAD("nvn".getBytes());
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
干杯!!!