前端使用CryptoJS的AES解密,Java后端加密实现

前端使用CryptoJS的AES解密,Java后端加密实现。CryptoJS的AES输出使用的是openssl格式,所以处理起来有一些不一样,详细代码如下:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;

public class AesTest {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private static byte[] array_concat(final byte[] a, final byte[] b) {
        final byte[] c = new byte[a.length + b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }

    private static final String SALTED_STR = "Salted__";
    private static final byte[] SALTED_MAGIC = SALTED_STR.getBytes(US_ASCII);

    static String encrypt(String password, String clearText) throws Exception {
        final byte[] pass = password.getBytes(US_ASCII);
        final byte[] salt = (new SecureRandom()).generateSeed(8);
        final byte[] inBytes = clearText.getBytes(UTF_8);

        final byte[] passAndSalt = array_concat(pass, salt);
        byte[] hash = new byte[0];
        byte[] keyAndIv = new byte[0];
        for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
            final byte[] hashData = array_concat(hash, passAndSalt);
            final MessageDigest md = MessageDigest.getInstance("MD5");
            hash = md.digest(hashData);
            keyAndIv = array_concat(keyAndIv, hash);
        }

        final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
        final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
        final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");

        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
        byte[] data = cipher.doFinal(inBytes);
        data = array_concat(array_concat(SALTED_MAGIC, salt), data);
        return Base64.getEncoder().encodeToString(data);
    }


    public static void main(String[] args) throws Exception {
        String result = encrypt("8888999911112222", "上海");
        System.out.println(result);
    }
}

这段java代码等同于:

echo '上海' | openssl aes-256-cbc -k 8888999911112222 -base64

  因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制,比如不允许使用256位密钥的AES加解密,可以通过覆盖JCE策略文件解决这个问题。

  官方网站提供了JCE无限制权限策略文件的下载:
JDK8
JDK7

下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt,将这几个文件拷贝到指定目录覆盖即可。覆盖前请先备份。

  1. 如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security下
  2. 如果安装了JDK,将两个jar文件也放到%JDK_HOME%\jre\lib\security下

你可能感兴趣的:(java)