【问题标题】:Rewriting Java AES 256 GCM Encryption in Node.js (PBKDF2WithHmacSHA1)在 Node.js (PBKDF2WithHmacSHA1) 中重写 Java AES 256 GCM 加密
【发布时间】:2021-08-10 11:28:16
【问题描述】:

我在 java 中有以下代码用于加密纯文本:

private static final String SECRET_KEY = "SecKeyTest";
private static final String SALT = "thisIsSalt";



public String encrypt(String strToEncrypt) {
    try {
        byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        IvParameterSpec ivspec = new IvParameterSpec(iv);

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(SECRET_KEY.toCharArray(), SALT.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
        
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128 , iv);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmParameterSpec);
        return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8)));
    } catch (Exception e) {
        System.out.println("Error while encrypting: " + e.toString());
    }
    return null;
}

我必须使用 NodeJs 重写相同的内容,到目前为止我所做的:

const salt = "thisIsSalt";
const digest = 'sha256';
const aesSecretKey = "SecKeyTest";

module.exports = {

    encrypt: function (plainText){

        const key = crypto.pbkdf2Sync(aesSecretKey, salt, 65536, 32, digest); //key len 32bytes i.e 256bits
        const iv = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]);

        // AES 256 GCM Mode
        var cipher = crypto.createCipheriv('aes-256-gcm', key, iv);

        // encrypt the given text
        var encrypted = Buffer.concat([cipher.update(plainText, 'utf8'), cipher.final()]);

        // extract the auth tag
        var tag = cipher.getAuthTag();

        // generate output
        return Buffer.concat([Buffer.from(salt), iv, tag, encrypted]).toString('base64');
        
    }


};

对于输入:“你好”:

Java:rgCx2SDSqio15M+0lViNAzW/lUmz

节点:dGhpc0lzU2FsdAAAAAAAAAAAAAAAAAAAAADSqio15M+0lViNAzW/lUmzrgCx2SA=

【问题讨论】:

    标签: javascript java node.js pbkdf2 aes-gcm


    【解决方案1】:

    Java 代码按此顺序隐式连接密文和标记。因此,要在 NodeJS 代码中获得相同的结果,需要进行以下更改:

    return Buffer.concat([encrypted, tag]).toString('base64');
    

    但是,salt 和 IV 不应该是静态的,而应该为每个密钥派生和加密随机生成。由于解密需要 salt 和 IV 并且两者都不是秘密的,因此它们与密文和标签一起传递,通常也连接在一起,例如:salt |四 |密文 |标记。

    【讨论】:

    • 非常感谢!我同意它们不应该是静态的。但是那个java实现逻辑是由另一家合作公司完成的,因此我们需要匹配将数据发送到他们的端点的要求。
    • 你能告诉我,在从生成的加密 base64 解密二进制数据时拼接 auth 标签的索引范围是多少? @topaco
    • 谢谢我明白了.. ` let tag = bData.slice(bData.length - 16);让 text = bData.slice(0, bData.length - 16); `
    • @XenonCI - 如果bData 是 Base64 解码 数据,那是正确的:最后 16 个字节是标签,标签之前的其余部分是实际密文。
    • 是的 bdata 是 base64 解码数据。再次感谢!
    猜你喜欢
    • 2020-07-03
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2021-04-22
    • 2021-09-03
    相关资源
    最近更新 更多