无法解密使用AES-GCM-256在Java中加密的节点中的数据
我试图在node.js中创建一个API,该API将解密使用AES-GCM-256算法创建的输入,我使用JAVA中相同的算法对代码进行加密,但无法使用node.js对其进行解密 我尝试了很多方法,但可能在标记部分遇到了问题&我遇到了错误“不受支持的状态或无法验证数据” 我的Java代码: 导入java.security.SecureRandom; 导入java.util.array; 导入java.util.Base64; 导入javax.crypto.Cipher; 导入javax.crypto.KeyGenerator; 导入javax.crypto.SecretKey; 导入javax.crypto.spec.gcmpareterspec; 导入javax.crypto.spec.SecretKeySpec; 公共类AES256GCMAlgo{ 静态字符串明文=这是需要通过Java AES 256 GCM加密算法加密的明文; 公共静态最终int AES_密钥_大小=256; 公共静态最终整数GCM_IV_长度=12; 公共静态最终整数GCM_标签长度=16; 公共静态无效主字符串[]args引发异常 { KeyGenerator KeyGenerator=KeyGenerator.GetInstancees; keyGenerator.initAES_KEY_SIZE; //生成密钥 SecretKey key=keyGenerator.generateKey; 字节[]IV=新字节[GCM_IV_长度]; SecureRandom random=新SecureRandom; random.nextBytesIV; 字节[]编码=key.getEncoded; 字符串输出=Base64.getEncoder.withoutPadding.encodetostringecoded; System.out.println保密、安全!+输出; 字符串ivoutput=Base64.getEncoder.withoutPadding.encodeToStringIV; System.out.println保守ivoutput秘密,确保安全!+ivoutput; System.out.printlnOriginal Text:+纯文本; 字节[]密文=EncryptPlaintText.getBytes,密钥,IV; byte[]tagVal=Arrays.copyOfRangecipherText,cipherText.length-128/byte.SIZE,cipherText.length; System.out.printlencrypted Text:+Base64.getEncoder.encodetostringcipertext; System.out.printlnTag Text:+Base64.getEncoder.encodeToStringtagVal; 字符串输入=输出; 字节[]deencoded=Base64.getDecoder.decodeoutput; SecretKey aesKey=新SECRETKEYSPECDENCODE,AES; 字符串ivinput=ivoutput; 字节[]ivdeencoded=Base64.getDecoder.decodeivinput; String decryptedText=解密密文,aesKey,IVDEENCODE; System.out.printlnecryptedtext:+decryptedText; } 公共静态字节[]加密字节[]明文,SecretKey密钥,字节[]IV引发异常 { //获取密码实例 Cipher Cipher=Cipher.getInstanceAES/GCM/NoPadding; //创建SecretKeySpec SecretKeySpec keySpec=new SecretKeySpeckey.getEncoded,AES; //创建GCMPareterSpec GCMPParameterSpec GCMPParameterSpec=新GCMPParameterSpecGCM_标签长度*8,IV; //初始化加密模式的密码 cipher.initCipher.ENCRYPT_模式,keySpec,gcmParameterSpec; //执行加密 字节[]密文=cipher.doFinalplaintext; 返回密文; } 公共静态字符串解密字节[]密文,加密密钥,字节[]IV引发异常 { //获取密码实例 Cipher Cipher=Cipher.getInstanceAES/GCM/NoPadding; //创建SecretKeySpec SecretKeySpec keySpec=new SecretKeySpeckey.getEncoded,AES; //创建GCMPareterSpec GCMPParameterSpec GCMPParameterSpec=新GCMPParameterSpecGCM_标签长度*8,IV; //为解密模式初始化密码 cipher.initCipher.DECRYPT_模式,密钥规范,gcmParameterSpec; //执行解密 字节[]decryptedText=cipher.doFinalcipherText; 返回新的StringdecryptedText; } } mynode.js代码无法解密使用AES-GCM-256在Java中加密的节点中的数据,java,node.js,aes-gcm,Java,Node.js,Aes Gcm,我试图在node.js中创建一个API,该API将解密使用AES-GCM-256算法创建的输入,我使用JAVA中相同的算法对代码进行加密,但无法使用node.js对其进行解密 我尝试了很多方法,但可能在标记部分遇到了问题&我遇到了错误“不受支持的状态或无法验证数据” 我的Java代码: 导入java.security.SecureRandom; 导入java.util.array; 导入java.util.Base64; 导入javax.crypto.Cipher; 导入javax.crypto
const crypto = require('crypto');
// input created by running above program in java
const ed = 'OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMYjc/vXd1ha/cElMBzFaIp9g==='
const key = 'HuzPEZgzqKOo8VwlnYhNUaPWTWSVDRQ2bMtY6aJAp8I'
const iv = 'kg5ILA0826hrew5w'
const tag = 'jc/vXd1ha/cElMBzFaIp9g==' // last 16 bytes extracted in java
function decrypt(encrypted, ik, iiv, it) {
let bData = Buffer.from(encrypted, 'base64');
// console.log(bData.length,bData.length - 64)
let tag1 = Buffer.from(tag, 'base64');
// let tag1 = bData.slice((bData.length - 16),bData.length) // also tried slicing last 16 bytes of buffer
console.log('00000000',tag1.length)
let iv1 = Buffer.from(iiv, 'base64');
let key1 = new Buffer(ik, 'base64');
console.log('aaaaaaaaa')
let decipher = crypto.createDecipheriv('aes-256-gcm', key1, iv1)
console.log('bbbbbbbbbbbbb')
decipher.setAuthTag(tag1);
console.log('ccccccc')
let dec = decipher.update(encrypted, 'binary', 'utf8')
dec += decipher.final('utf8');
return dec;
}
console.log('devryptedddddd',decrypt(ed,key,iv,tag))
我应该在node.js的控制台中得到“这是一个需要通过Java AES 256 GCM加密算法加密的纯文本”,但我得到了“不受支持的状态或无法验证数据”错误。
请帮忙。您使用的“ed”不是该明文、键和IV的Java代码的输出。我得到的值是base64
OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMY3P713dYWv3BJTAcxWiKfY=
最后22个字符是不同的。但该值不是nodejs中使用的正确值;Java crypto将GCM标记作为密文的最后N个字节返回,您正确地将其复制到一个单独的变量中,但没有将其从密文中删除。要在nodejs中使用的正确密文位于base64中:
OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMQ==
短20个字符,最后3个字符不同
最后,您的节点执行bData=Buffer.fromencrypted“base64”,但
n忽略bData,并使用base64字符串作为二进制(它不是二进制)对.updateencrypted、“binary”、“utf8”进行解密。有了这两个变化:
const crypto = require('crypto');
const ed = 'OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMQ=='
const key = 'HuzPEZgzqKOo8VwlnYhNUaPWTWSVDRQ2bMtY6aJAp8I'
const iv = 'kg5ILA0826hrew5w'
const tag = 'jc/vXd1ha/cElMBzFaIp9g==' // last 16 bytes extracted in java
function decrypt(encrypted, ik, iiv, it) {
let bData = Buffer.from(encrypted, 'base64');
let tag1 = Buffer.from(tag, 'base64');
let iv1 = Buffer.from(iiv, 'base64');
let key1 = new Buffer(ik, 'base64');
let decipher = crypto.createDecipheriv('aes-256-gcm', key1, iv1)
decipher.setAuthTag(tag1);
let dec = decipher.update(bData, 'utf8')
dec += decipher.final('utf8');
return dec;
}
console.log(decrypt(ed,key,iv,tag))
我得到了正确的输出,但也得到了一个警告,用于key1的新缓冲区已被弃用;Buffer.from作为您用于其他变量的变量现在是首选。您使用的“ed”不是该明文、键和IV的Java代码的输出。我得到的值是base64
OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMY3P713dYWv3BJTAcxWiKfY=
最后22个字符是不同的。但该值不是nodejs中使用的正确值;Java crypto将GCM标记作为密文的最后N个字节返回,您正确地将其复制到一个单独的变量中,但没有将其从密文中删除。要在nodejs中使用的正确密文位于base64中:
OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMQ==
短20个字符,最后3个字符不同
最后,您的节点执行bData=Buffer.fromencrypted,'base64',但随后忽略bData,并使用base64字符串作为二进制(它不是二进制)来解密.updateencrypted,'binary','utf8'。有了这两个变化:
const crypto = require('crypto');
const ed = 'OGtANbvTLY6Cme2VNAxsiIhBLLwl29oVX7zC5DGmmq4hU/VqNKaGQuSp1Q8liQ94cW/B96OJoJJ2r67jRlQFI4qHCTWFU2qQ8QaNj6WehdVLsf5mDK2aMQ=='
const key = 'HuzPEZgzqKOo8VwlnYhNUaPWTWSVDRQ2bMtY6aJAp8I'
const iv = 'kg5ILA0826hrew5w'
const tag = 'jc/vXd1ha/cElMBzFaIp9g==' // last 16 bytes extracted in java
function decrypt(encrypted, ik, iiv, it) {
let bData = Buffer.from(encrypted, 'base64');
let tag1 = Buffer.from(tag, 'base64');
let iv1 = Buffer.from(iiv, 'base64');
let key1 = new Buffer(ik, 'base64');
let decipher = crypto.createDecipheriv('aes-256-gcm', key1, iv1)
decipher.setAuthTag(tag1);
let dec = decipher.update(bData, 'utf8')
dec += decipher.final('utf8');
return dec;
}
console.log(decrypt(ed,key,iv,tag))
我得到了正确的输出,但也得到了一个警告,用于key1的新缓冲区已被弃用;现在首选Buffer.from作为其他变量