如何使用此代码进行加密和解密使用java spring boot

问题描述 投票:0回答:1

我需要你的帮助,如何在 Spring Boot 中使用 CryptoJS 库。在我的客户端中使用来自https://stackoverflow.com/a/27582253的这个库 但我很难找到解密的解决方案。例如,在我的客户中,有一个像这样的损坏:

var encData  = {"ct":"d97K/kt03Inh9wYp90iyNwefnaTwMAeQXTjOwJR+gU0=","iv":"4101e6c0938e312952ea24f19306cfb2","s":"615cc2b4480e260a"}

对于

public_key = S!ZcdNb4XXcw_jXbHQqiFsHp6

那么如何在服务器端使用Spring Boot解密encData?

我一直在尝试使用

javax.crypto
但总是出现错误
Wrong IV length: must be 16 bytes long

    public static String decrypt(String passphrase, String jsonString) throws Exception {
        JsonObject jsonObject = new Gson().fromJson(jsonString, JsonObject.class);
        String saltHex = jsonObject.get("s").getAsString();
        String ctBase64 = jsonObject.get("ct").getAsString();
        String ivHex = jsonObject.get("iv").getAsString();
        System.out.println(passphrase);

        byte[] salt = hexStringToByteArray(saltHex);
        byte[] ct = Base64.getDecoder().decode(ctBase64);
        byte[] iv = hexStringToByteArray(ivHex);

        //String concatedPassphrase = passphrase + new String(salt, StandardCharsets.UTF_8);
        String concatedPassphrase = passphrase + byteArrayToString(salt);
        System.out.println(concatedPassphrase);
        byte[] md5 = md5(concatedPassphrase.getBytes(StandardCharsets.UTF_8));

        for (int i = 1; i < 3; i++) {
            md5 = md5(concatArrays(md5, concatedPassphrase.getBytes(StandardCharsets.UTF_8)));
        }

        byte[] key = Arrays.copyOf(md5, 32);
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
            byte[] decryptedData = cipher.doFinal(ct);
            return new String(decryptedData, StandardCharsets.UTF_8);
        } catch (Exception e) {
            //e.printStackTrace();
            return e.getMessage();
        }
    }

有人可以帮助我吗?

java spring-boot encryption aes
1个回答
0
投票

您错误地移植了密钥导出函数。正确的是例如:

...
byte[] concatedPassphrase = concatArrays(passphrase.getBytes(StandardCharsets.UTF_8), salt);
byte[] md5 = md5(concatedPassphrase);
byte[] result = md5;
for (int i = 1; i < 3; i++) {
    md5 = md5(concatArrays(md5, concatedPassphrase));
    result = concatArrays(result, md5);
}
byte[] key = Arrays.copyOf(result, 32);
...

通过此更改,解密有效。


请注意,密钥派生函数应实现 OpenSSL 专有密钥派生函数

EVP_BytesToKey()
(至少此处需要的部分功能)。作为用户定义实现的替代方案,也可以使用
EVP_BytesToKey()
的 BouncyCastle 实现(如果在您的环境中可行):

import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
...
OpenSSLPBEParametersGenerator pbeGenerator = new OpenSSLPBEParametersGenerator(new MD5Digest()); 
pbeGenerator.init(passphrase.getBytes(StandardCharsets.UTF_8), salt);
ParametersWithIV parameters = (ParametersWithIV) pbeGenerator.generateDerivedParameters(256, 0); // keySize, ivSize in bits
byte[] key = ((KeyParameter)parameters.getParameters()).getKey();

提示:BouncyCastle 还提供各种编码器(例如用于十六进制编码/解码)。


安全性:请注意,今天

EVP_BytesToKey()
被认为是不安全的。更可靠的密钥导出函数是 Argon2 或至少 PBKDF2(与随机盐结合)。

© www.soinside.com 2019 - 2024. All rights reserved.