Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法解密使用AES-GCM-256在Java中加密的节点中的数据_Java_Node.js_Aes Gcm - Fatal编程技术网

无法解密使用AES-GCM-256在Java中加密的节点中的数据

无法解密使用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

我试图在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代码

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作为其他变量