无法解密节点js文本i Java AES-256-GCM获取标记不匹配

无法解密节点js文本i Java AES-256-GCM获取标记不匹配,java,node.js,encryption,aes-gcm,Java,Node.js,Encryption,Aes Gcm,我能够分别加密和解密节点和java代码,但在尝试解密java中的节点文本时,会发现标记不匹配!我正在尝试加密和解密一个简单的Hello World文本 节点js代码我有: const buffer = require('buffer'); const crypto = require('crypto'); // Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib. const aes256gcm = (k

我能够分别加密和解密节点和java代码,但在尝试解密java中的节点文本时,会发现标记不匹配!我正在尝试加密和解密一个简单的
Hello World
文本

节点js代码我有:

const buffer = require('buffer');
const crypto = require('crypto');

// Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib.
const aes256gcm = (key) => {
  const ALGO = 'aes-256-gcm';

  // encrypt returns base64-encoded ciphertext
  const encrypt = (str) => {
    // Hint: the `iv` should be unique (but not necessarily random).
    // `randomBytes` here are (relatively) slow but convenient for
    // demonstration.
    const iv = new Buffer(crypto.randomBytes(16), 'utf8');
    const cipher = crypto.createCipheriv(ALGO, key, iv);

    // Hint: Larger inputs (it's GCM, after all!) should use the stream API
    let enc = cipher.update(str, 'utf8', 'base64');
    enc += cipher.final('base64');
    console.log(enc);
    return [enc, iv, cipher.getAuthTag()];

  };

  // decrypt decodes base64-encoded ciphertext into a utf8-encoded string
  const decrypt = (enc, iv, authTag) => {
    const decipher = crypto.createDecipheriv(ALGO, key, iv);
    decipher.setAuthTag(authTag);
    let str = decipher.update(enc, 'base64', 'utf8');
    str += decipher.final('utf8');

    return str;
  };

  return {
    encrypt,
    decrypt,
  };
};

const KEY = new Buffer('fTjWnZr4u7x!z%C*F-JaNdRgUkXp2s5v', 'utf8');

const aesCipher = aes256gcm(KEY);

const [encrypted, iv, authTag] = aesCipher.encrypt('Hello World');
const decrypted = aesCipher.decrypt(encrypted, iv, authTag);

console.log(decrypted); // 'hello, world'
private final static int GCM_IV_LENGTH = 12;
private final static int GCM_TAG_LENGTH = 16;
private static String decrypt(String encrypted, SecretKey skey) throws Exception {
    byte[] decoded = Base64.getDecoder().decode(encrypted);

    byte[] iv = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);

    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
    cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);

    byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);

    String result = new String(ciphertext, "UTF8");

    return result;
}
还有我的java代码:

const buffer = require('buffer');
const crypto = require('crypto');

// Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib.
const aes256gcm = (key) => {
  const ALGO = 'aes-256-gcm';

  // encrypt returns base64-encoded ciphertext
  const encrypt = (str) => {
    // Hint: the `iv` should be unique (but not necessarily random).
    // `randomBytes` here are (relatively) slow but convenient for
    // demonstration.
    const iv = new Buffer(crypto.randomBytes(16), 'utf8');
    const cipher = crypto.createCipheriv(ALGO, key, iv);

    // Hint: Larger inputs (it's GCM, after all!) should use the stream API
    let enc = cipher.update(str, 'utf8', 'base64');
    enc += cipher.final('base64');
    console.log(enc);
    return [enc, iv, cipher.getAuthTag()];

  };

  // decrypt decodes base64-encoded ciphertext into a utf8-encoded string
  const decrypt = (enc, iv, authTag) => {
    const decipher = crypto.createDecipheriv(ALGO, key, iv);
    decipher.setAuthTag(authTag);
    let str = decipher.update(enc, 'base64', 'utf8');
    str += decipher.final('utf8');

    return str;
  };

  return {
    encrypt,
    decrypt,
  };
};

const KEY = new Buffer('fTjWnZr4u7x!z%C*F-JaNdRgUkXp2s5v', 'utf8');

const aesCipher = aes256gcm(KEY);

const [encrypted, iv, authTag] = aesCipher.encrypt('Hello World');
const decrypted = aesCipher.decrypt(encrypted, iv, authTag);

console.log(decrypted); // 'hello, world'
private final static int GCM_IV_LENGTH = 12;
private final static int GCM_TAG_LENGTH = 16;
private static String decrypt(String encrypted, SecretKey skey) throws Exception {
    byte[] decoded = Base64.getDecoder().decode(encrypted);

    byte[] iv = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);

    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
    cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);

    byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);

    String result = new String(ciphertext, "UTF8");

    return result;
}
java执行代码的主要方法是

public static void main(String[] args) throws Exception {
    String byte_key="fTjWnZr4u7x!z%C*F-JaNdRgUkXp2s5v";
    SecretKey key = new SecretKeySpec(byte_key.getBytes(), "AES");        
    System.out.println("foo "+ decrypt("1cbKXSnEWixxFi0=", key));

}

我想我在这两个代码中遗漏了一些东西

必须使用相同的IV/nonce。对于GCM,长度应为
12
字节。Java中是这样,但NodeJS代码中不是这样。此外,NodeJS代码中的
encrypt
返回
3
值:ciphertext、IV和tag,而Java代码中的
decrypt
需要一个字符串(稍后进行Base64解码)。你还没有发布转换!一种可能是在NodeJS代码IV中,在二进制级别按此顺序连接密文和标记,然后对结果进行Base64编码。注意:Java希望密文和标记连接在一起(按此顺序)。