Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.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/NoPadding encrypt from node and decrypt on java,抛出AEADBadTagException:标记不匹配_Java_Node.js_Aes Gcm - Fatal编程技术网

AES/GCM/NoPadding encrypt from node and decrypt on java,抛出AEADBadTagException:标记不匹配

AES/GCM/NoPadding encrypt from node and decrypt on java,抛出AEADBadTagException:标记不匹配,java,node.js,aes-gcm,Java,Node.js,Aes Gcm,我想用NodeJS加密数据,然后用Java解密数据。我在网上搜索了很多例子,但没有找到合适的答案。 NodeJS代码如下: const crypto = require('crypto'); function encrypt(content) { const salt = crypto.randomBytes(cryptoConfig.saltLength); const iv = crypto.randomBytes(cryptoConfig.ivLength); c

我想用NodeJS加密数据,然后用Java解密数据。我在网上搜索了很多例子,但没有找到合适的答案。 NodeJS代码如下:

const crypto = require('crypto');

function encrypt(content) {
    const salt = crypto.randomBytes(cryptoConfig.saltLength);
    const iv = crypto.randomBytes(cryptoConfig.ivLength);
    const key = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt, cryptoConfig.iterations, 
    cryptoConfig.keyLength, cryptoConfig.digest);
    const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv);

    const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);

    const tag = cipher.getAuthTag();

    const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
    return encdata;
}

const cryptoConfig = {
    cipherAlgorithm: 'aes-256-gcm',
    masterKey: 'sfcpnnjFG6dULJfo1BEGqczpfN0SmwZ6bgKO5FcDRfI=',
    iterations: 65535,
    keyLength: 32,
    saltLength: 16,
    ivLength: 12,
    tagLength: 16,
    digest: 'sha512'
}
const encryptedData=encrypt('hello world'); log('encrypt data->',encryptedData)

JAVA代码:

private static final Charset UTF_8 = StandardCharsets.UTF_8;
private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";

private static final int TAG_LENGTH = 16;
private static final int IV_LENGTH = 12;
private static final int SALT_LENGTH = 16;
private static final int KEY_LENGTH = 16;
private static final int ITERATIONS = 65535;

public static String decrypt(String cipherContent, String password) throws Exception {
    byte[] decode = Base64.getDecoder().decode(cipherContent.getBytes(UTF_8));
    ByteBuffer bb = ByteBuffer.wrap(decode);
    byte[] salt = new byte[SALT_LENGTH];
    bb.get(salt);
    byte[] iv = new byte[IV_LENGTH];
    bb.get(iv);
    byte[] content = new byte[bb.remaining()];
    bb.get(content);

    Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
    SecretKey aesKeyFromPassword = getAESKeyFromPassword(password.toCharArray(), salt);
    cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH * 8, iv));

    byte[] plainText = cipher.doFinal(content);
    return new String(plainText, UTF_8);
}

private static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
        throws NoSuchAlgorithmException, InvalidKeySpecException {
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
    KeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_LENGTH * 8);
    SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
    return secret;
}

public static void main(String[] args) throws Exception {
    String masterKey = "sfcpnnjFG6dULJfo1BEGqczpfN0SmwZ6bgKO5FcDRfI=";
    String encryptedData = "<NodeJS return encryptedData>";
    String decryptedText = decrypt(encryptedData, masterKey);
    System.out.println("Decrypted: " + decryptedText));
}

如何更改以使此场景在代码中运行?代码中共有两个问题阻止您在NodeJ/Crypto和Java之间成功加密,但如果更改了两行代码,它将正常工作

NodeJs:在加密函数的末尾,您将解密所需的参数连接到一个更大的数组。因为Java需要一个
ciphertext:gcmTag
输入,所以应该更改行

const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
// ### put the auth tag at the end of encrypted
to
const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
Java:您要求AES GCM 256加密,这意味着您必须在两侧使用256/8=32字节长的密钥, 所以只要改变常数

private static final int KEY_LENGTH = 16; // ### key length for aes gcm 256 is 32 byte
to:
private static final int KEY_LENGTH = 32;
您可以在此处在线运行这两个代码:NodeJs:和Java:

以下是产出:

NodeJs:

AES GCMC 256 String encryption with PBKDF2 derived key
plaintext:   The quick brown fox jumps over the lazy dog
ciphertext:  InFN0Zz5MGLTOr5B0xFnvU1k2dPPZPSen7pCWiQguCEQe6KSBSAQjHtUvIeuA7jcl8fK7L63xbq+tsHe9HRYupp554tbEESjrCbsCh1lW2exWDp4YLQd
var crypto = require('crypto');

console.log('AES GCMC 256 String encryption with PBKDF2 derived key');

var plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext:  ', plaintext);

const cryptoConfig = {
    cipherAlgorithm: 'aes-256-gcm',
    masterKey: 'sfcpnnjFG6dULJfo1BEGqczpfN0SmwZ6bgKO5FcDRfI=',
    iterations: 65535,
    keyLength: 32,
    saltLength: 16,
    ivLength: 12,
    tagLength: 16,
    digest: 'sha512'
}

var ciphertext = encrypt(plaintext);
console.log('ciphertext: ', ciphertext);

function encrypt(content) {
    const salt = crypto.randomBytes(cryptoConfig.saltLength);
    const iv = crypto.randomBytes(cryptoConfig.ivLength);
    const key = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt, cryptoConfig.iterations,
    cryptoConfig.keyLength, cryptoConfig.digest);
    const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv);
    const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);
    const tag = cipher.getAuthTag();
    // ### put the auth tag at the end of encrypted
    //const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
    const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
    return encdata;
}
爪哇:

安全警告:代码没有异常处理,仅用于教育目的。

NodeJs:

AES GCMC 256 String encryption with PBKDF2 derived key
plaintext:   The quick brown fox jumps over the lazy dog
ciphertext:  InFN0Zz5MGLTOr5B0xFnvU1k2dPPZPSen7pCWiQguCEQe6KSBSAQjHtUvIeuA7jcl8fK7L63xbq+tsHe9HRYupp554tbEESjrCbsCh1lW2exWDp4YLQd
var crypto = require('crypto');

console.log('AES GCMC 256 String encryption with PBKDF2 derived key');

var plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext:  ', plaintext);

const cryptoConfig = {
    cipherAlgorithm: 'aes-256-gcm',
    masterKey: 'sfcpnnjFG6dULJfo1BEGqczpfN0SmwZ6bgKO5FcDRfI=',
    iterations: 65535,
    keyLength: 32,
    saltLength: 16,
    ivLength: 12,
    tagLength: 16,
    digest: 'sha512'
}

var ciphertext = encrypt(plaintext);
console.log('ciphertext: ', ciphertext);

function encrypt(content) {
    const salt = crypto.randomBytes(cryptoConfig.saltLength);
    const iv = crypto.randomBytes(cryptoConfig.ivLength);
    const key = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt, cryptoConfig.iterations,
    cryptoConfig.keyLength, cryptoConfig.digest);
    const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv);
    const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);
    const tag = cipher.getAuthTag();
    // ### put the auth tag at the end of encrypted
    //const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
    const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
    return encdata;
}
爪哇:


代码中总共有两个问题阻止您在NodeJS/Crypto和Java之间成功加密,但如果有两行代码发生了更改,它将正常工作

NodeJs:在加密函数的末尾,您将解密所需的参数连接到一个更大的数组。因为Java需要一个
ciphertext:gcmTag
输入,所以应该更改行

const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
// ### put the auth tag at the end of encrypted
to
const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
Java:您要求AES GCM 256加密,这意味着您必须在两侧使用256/8=32字节长的密钥, 所以只要改变常数

private static final int KEY_LENGTH = 16; // ### key length for aes gcm 256 is 32 byte
to:
private static final int KEY_LENGTH = 32;
您可以在此处在线运行这两个代码:NodeJs:和Java:

以下是产出:

NodeJs:

AES GCMC 256 String encryption with PBKDF2 derived key
plaintext:   The quick brown fox jumps over the lazy dog
ciphertext:  InFN0Zz5MGLTOr5B0xFnvU1k2dPPZPSen7pCWiQguCEQe6KSBSAQjHtUvIeuA7jcl8fK7L63xbq+tsHe9HRYupp554tbEESjrCbsCh1lW2exWDp4YLQd
var crypto = require('crypto');

console.log('AES GCMC 256 String encryption with PBKDF2 derived key');

var plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext:  ', plaintext);

const cryptoConfig = {
    cipherAlgorithm: 'aes-256-gcm',
    masterKey: 'sfcpnnjFG6dULJfo1BEGqczpfN0SmwZ6bgKO5FcDRfI=',
    iterations: 65535,
    keyLength: 32,
    saltLength: 16,
    ivLength: 12,
    tagLength: 16,
    digest: 'sha512'
}

var ciphertext = encrypt(plaintext);
console.log('ciphertext: ', ciphertext);

function encrypt(content) {
    const salt = crypto.randomBytes(cryptoConfig.saltLength);
    const iv = crypto.randomBytes(cryptoConfig.ivLength);
    const key = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt, cryptoConfig.iterations,
    cryptoConfig.keyLength, cryptoConfig.digest);
    const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv);
    const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);
    const tag = cipher.getAuthTag();
    // ### put the auth tag at the end of encrypted
    //const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
    const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
    return encdata;
}
爪哇:

安全警告:代码没有异常处理,仅用于教育目的。

NodeJs:

AES GCMC 256 String encryption with PBKDF2 derived key
plaintext:   The quick brown fox jumps over the lazy dog
ciphertext:  InFN0Zz5MGLTOr5B0xFnvU1k2dPPZPSen7pCWiQguCEQe6KSBSAQjHtUvIeuA7jcl8fK7L63xbq+tsHe9HRYupp554tbEESjrCbsCh1lW2exWDp4YLQd
var crypto = require('crypto');

console.log('AES GCMC 256 String encryption with PBKDF2 derived key');

var plaintext = 'The quick brown fox jumps over the lazy dog';
console.log('plaintext:  ', plaintext);

const cryptoConfig = {
    cipherAlgorithm: 'aes-256-gcm',
    masterKey: 'sfcpnnjFG6dULJfo1BEGqczpfN0SmwZ6bgKO5FcDRfI=',
    iterations: 65535,
    keyLength: 32,
    saltLength: 16,
    ivLength: 12,
    tagLength: 16,
    digest: 'sha512'
}

var ciphertext = encrypt(plaintext);
console.log('ciphertext: ', ciphertext);

function encrypt(content) {
    const salt = crypto.randomBytes(cryptoConfig.saltLength);
    const iv = crypto.randomBytes(cryptoConfig.ivLength);
    const key = crypto.pbkdf2Sync(cryptoConfig.masterKey, salt, cryptoConfig.iterations,
    cryptoConfig.keyLength, cryptoConfig.digest);
    const cipher = crypto.createCipheriv(cryptoConfig.cipherAlgorithm, key, iv);
    const encrypted = Buffer.concat([cipher.update(content, 'utf8'), cipher.final()]);
    const tag = cipher.getAuthTag();
    // ### put the auth tag at the end of encrypted
    //const encdata = Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
    const encdata = Buffer.concat([salt, iv, encrypted, tag]).toString('base64');
    return encdata;
}
爪哇: