如何在Java中解密已使用JS加密的字符串

How to decrypt in Java strings that have been encrypted using JS crypto

本文关键字:JS 加密 字符串 Java 解密      更新时间:2023-09-26

在Java中,使用javax.crypto.xxx,这个JS代码的等价物是什么?

    encryptString : function encryptString(str, password) {
        var cipher = crypto.createCipher("aes128", password);
        return cipher.update(str, "binary", "base64") +
            cipher.final("base64");
    },
    decryptString : function decryptString(str, password) {
        var desipher = crypto.createDecipher("aes128", password);
        return desipher.update(str, "base64", "binary") +
            desipher.final("binary");
    }

我将使用JS进行编码,然后使用Java进行解码,反之亦然。"str"answers"password"变量都是字符串,"password"的长度为16个字符。

看起来这个createCipher(算法,密码)方法使用了一些方法来生成原始密钥和IV,这不是全面的标准。我认为使用createCipheriv(算法,密钥,iv)将是一种更便携的方法。更多信息:http://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv我很快就会更新最新消息。

这就是分别使用Crypto和javax.Crypto在JS和Java中加密/解密的方法。

如果你不关心不同环境的互操作性,你可以很快在JS代码中使用createCypher(算法,密码),但它不是很便携,因为你不知道原始密钥和初始化向量是如何从密码中派生的。

将JS代码更改为使用createCipheriv(算法,密钥,iv),将为您提供可移植的加密/解密:

    encryptString : function encryptString(str, encryptionKey, iv) {
        var cipher = crypto.createCipheriv('aes-128-cbc', encryptionKey, iv);
        var cipherText = cipher.update(str, 'binary', 'base64');
        var cipherTextRemaining = cipher.final('base64');
        return cipherText + cipherTextRemaining;
    },
    decryptString : function decryptString(str, encryptionKey, iv) {
        var desipher = crypto.createDecipheriv('aes-128-cbc', encryptionKey, iv);
        var desipherText = desipher.update(str, 'base64', 'binary');
        var desipherTextRemaining = desipher.final('binary');
        return desipherText + desipherTextRemaining;
    },

这是做同样事情的等效Java代码:

public static String encryptString(String clearText, byte[] key, byte[] initialVector) throws Exception
{
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec secretKeySpecy = new SecretKeySpec(key, "AES");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpecy, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(clearText.getBytes());
    return new String(Base64.encodeBase64(encrypted, false));
}
public static String decryptString(String cipherText, byte[] key, byte[] initialVector) throws Exception
{
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec secretKeySpecy = new SecretKeySpec(key, "AES");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy, ivParameterSpec);
    return new String(cipher.doFinal(Base64.decodeBase64(cipherText)));
}

我们也遇到了类似的问题。所以我们想要的是在Java端加密voucherCode并将其发送到前端。确保凭证代码安全所需的加密。

现在在前端,第三方java脚本库需要这个voucherCode,这样它就可以通过解密来检索实际的voucherCCode

以下是我们所做的

在java端

import javax.xml.bind.DatatypeConverter;
    public class Controller{
     @RequestMapping("voucherCode")
     public String getVoucherCode{
       String voucherCode = voucherService.getVoucherCode()
             return  DatatypeConverter.printBase64Binary(voucherCode.getBytes("UTF-8"))
}
    }

因此,如果我们的凭证代码为50%关闭,那么上述代码将发送NTAlT0ZG作为50%关闭的编码值。

现在,一旦我们在前端有了编码的值。在javascript中,我们可以使用获得原始值

window.atob("NTAlT0ZG") // this will return 50%OFF

因此,通过这种方式,我们可以在java和java脚本之间进行加密/解密。

window对象提供了两种加密和解密的方法

 window.btoa("50%OFF") // returns NTAlT0ZG
    window.atob("NTAlT0ZG") // return original value as "50%OFF"