AES加密从Java到Node.js

发布于 2025-02-08 06:59:21 字数 2582 浏览 1 评论 0原文

我需要使用 aes/eax/nopadding 在 bouncycastle 提供商 node.js 中复制 java 加密代码。遗产Java解密仍需要解密加密的值,因此盐和IV字节需要保持相同的长度。在 node.js 代码中,我能够正确生成盐和秘密密钥。但是我有一个问题。与 Bouncycastle 的等效算法 aes/eax/nopadding 是什么?

现有Java:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.SecureRandom;
import java.text.Normalizer;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;

public byte[] encrypt(byte[] plaintext, char[] password) {
    byte[] saltBytes = "SaltString1234!".getBytes("UTF-8");
           
    final byte[] salt = new byte[16];
    System.arraycopy(saltBytes, 0, salt, 0, 16);
    
    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    
    random.setSeed(System.currentTimeMillis());
    byte[] iv = new byte[8]; // 
    random.nextBytes(iv); 

    String normalizedPassword = Normalizer.normalize(new String(password), Normalizer.Form.NFC);
    char[] currentPassword = normalizedPassword.toCharArray();
    PBEKeySpec keySpec = new PBEKeySpec(currentPassword, salt, 1000, 128);
    SecretKey derivedKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec); 
    SecretKey secretKey = new SecretKeySpec(derivedKey.getEncoded(), "AES");
    
    Provider provider = new BouncyCastleProvider();
    Cipher cipher = newCipher("AES/EAX/NoPadding", provider);
    
    final IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
    
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParamSpec);
    
    return cipher.doFinal(plaintext);
}

new Node.js代码:

const crypto = require('crypto');

function encrypt(plaintext, password) {
    const salt = Buffer.from('SaltString1234!', 'utf8').subarray(0,16);

    const secretKey = crypto.pbkdf2Sync(password.normalize('NFC'), salt, 1000, 16, 'sha1');

    const iv = crypto.randomBytes(8);

    const cipher = crypto.createCipheriv(
            'aes-128-gcm'/* What algorithm be equivilent to AES/EAX/NoPadding with BouncyCastle? */,
            secretKey,
            iv
        );
 
    const ciphertextWithTag = Buffer.concat([
        iv,
        cipher.update(plaintext, 'utf8'),
        cipher.final(),
        cipher.getAuthTag()
    ]);
 
    return ciphertextWithTag;
}

I need to replicate Java encryption code using AES/EAX/NoPadding with BouncyCastle provider in node.js. The encrypted value will still need to be decrypted by the legacy Java decryption, so the salt and iv bytes need to stay the same length. In the node.js code I am able to generate the salt and secret key correctly. But I have an issue. What is equivalent algorithm to AES/EAX/NoPadding with BouncyCastle?

Existing Java:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.SecureRandom;
import java.text.Normalizer;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;

public byte[] encrypt(byte[] plaintext, char[] password) {
    byte[] saltBytes = "SaltString1234!".getBytes("UTF-8");
           
    final byte[] salt = new byte[16];
    System.arraycopy(saltBytes, 0, salt, 0, 16);
    
    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    
    random.setSeed(System.currentTimeMillis());
    byte[] iv = new byte[8]; // 
    random.nextBytes(iv); 

    String normalizedPassword = Normalizer.normalize(new String(password), Normalizer.Form.NFC);
    char[] currentPassword = normalizedPassword.toCharArray();
    PBEKeySpec keySpec = new PBEKeySpec(currentPassword, salt, 1000, 128);
    SecretKey derivedKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec); 
    SecretKey secretKey = new SecretKeySpec(derivedKey.getEncoded(), "AES");
    
    Provider provider = new BouncyCastleProvider();
    Cipher cipher = newCipher("AES/EAX/NoPadding", provider);
    
    final IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
    
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParamSpec);
    
    return cipher.doFinal(plaintext);
}

New node.js code:

const crypto = require('crypto');

function encrypt(plaintext, password) {
    const salt = Buffer.from('SaltString1234!', 'utf8').subarray(0,16);

    const secretKey = crypto.pbkdf2Sync(password.normalize('NFC'), salt, 1000, 16, 'sha1');

    const iv = crypto.randomBytes(8);

    const cipher = crypto.createCipheriv(
            'aes-128-gcm'/* What algorithm be equivilent to AES/EAX/NoPadding with BouncyCastle? */,
            secretKey,
            iv
        );
 
    const ciphertextWithTag = Buffer.concat([
        iv,
        cipher.update(plaintext, 'utf8'),
        cipher.final(),
        cipher.getAuthTag()
    ]);
 
    return ciphertextWithTag;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文