对于应用程序进行加密保护,AES算法被广泛使用。但是在使用Java和PHP进行AES加解密时,很多人都会遇到一些困难。本文就来介绍一下如何实现Java和PHP的完美对接AES加解密。

在进行AES加解密时,我们需要注意以下几个方面:

  1. 确定加密算法模式、密钥长度、补码方式、解密串编码方式等参数
  2. 密钥处理,是否需要进行算法处理
  3. 在Java中,加密算法模式和补码方式需要写完整参数格式

首先,我们需要了解AES加解密的基础知识。无论用哪种语言实现AES加解密,首要考虑的是加密算法模式、密钥长度、补码方式和解密串编码方式等几个参数。确认好这些参数之后,基本上不会出现什么意外情况。

但是不出意外的还是出现意外了,Java使用Cipher cipher = Cipher.getInstance(AES);初始化对象的时候,算法模式和补码方式是什么?不一定所有人都知道,不熟悉java的人只能翻文档或者各种尝试,我现在就直接给出答案 AES = AES/ECB/PKCS5Padding。其他的都需要写完整参数格式例如:AES/CBC/PKCS5Padding等等,写完整参数的,我们可以直接看出来。

算法模式和补码方式确定好之后,用php只要确定好算法模式、补码方式即可。

另外需要注意的就是密钥是否做了算法处理,比如我之前碰到的java的代码里key做了SHA1PRNG算法处理,那么再php里同样做一次SHA1PRNG算法处理即可,下面贴出php代码和java代码

【php代码】

//密钥,根据实际情况来决定是否需要做base64_decode
$keySource = base64_decode("a2V5LXpoZXNoaWtleS1qaXVzaGlrZXk=");

//key做SHA1PRNG算法处理,根据实际情况决定是否处理
$key= substr(openssl_digest(openssl_digest($keySource, 'sha1', true), 'sha1', true), 0, 16);

$content = "ABC123";
$cipher_algo="aes-128-ecb";

//加密
function aes_encrypt($content, $key) {
    $encryptContent = openssl_encrypt(
    $content,//要加/解密的内容
    $cipher_algo,//加密模式: 可以通过openssl_get_cipher_methods()获取有效密码方式列表
    $key,//加密密钥[密码]
    OPENSSL_RAW_DATA,//数据格式选项(可选)【选项有:】:0,OPENSSL_RAW_DATA=1,OPENSSL_ZERO_PADDING=2,OPENSSL_NO_PADDING=3;它有着很重要的作用:0:默认模式,自动进行 pkcs7 补位,同时自动进行 base64 编,1:OPENSSL_RAW_DATA,自动进行 pkcs7 补位, 但是不自动进行 base64 编码2:OPENSSL_ZERO_PADDING,需要自己进行 pkcs7 补位,同时自动进行 base64 编码
    '');
    $encryptContent = base64_encode($encryptContent);
    return $encryptContent;
}
//解密
function aes_decrypt($content, $key) {
    $decryptContent = openssl_decrypt(
    base64_decode($content),//要加/解密的内容
    $cipher_algo,//加密模式: 可以通过openssl_get_cipher_methods()获取有效密码方式列表
    $key,//加密密钥[密码]
    OPENSSL_RAW_DATA,//数据格式选项(可选)【选项有:】:0,OPENSSL_RAW_DATA=1,OPENSSL_ZERO_PADDING=2,OPENSSL_NO_PADDING=3;它有着很重要的作用:0:默认模式,自动进行 pkcs7 补位,同时自动进行 base64 编,1:OPENSSL_RAW_DATA,自动进行 pkcs7 补位, 但是不自动进行 base64 编码2:OPENSSL_ZERO_PADDING,需要自己进行 pkcs7 补位,同时自动进行 base64 编码
    '');
    return $decryptContent;
}

【java代码】

private static final String ENCRYPT_KEY = "a2V5LXpoZXNoaWtleS1qaXVzaGlrZXk=";

    public static String encrypt(String value) {
        return null==value ? null : aesEncrypt(value, ENCRYPT_KEY);
    }

    public static String decrypt(String value) {
        return null==value ? null : aesDecrypt(value, ENCRYPT_KEY);
    }

    private static String aesEncrypt(String value, String encryptKey) {
        try {
            String key = encryptKey(encryptKey);
            if (null == key) {
                return null;
            } else {
                KeyGenerator kgen = KeyGenerator.getInstance("AES");
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(key.getBytes());
                kgen.init(128, secureRandom);
                Cipher cipher = Cipher.getInstance("AES");//默认 AES = AES/ECB/PKCS5Padding
                cipher.init(1, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
                byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
                byte[] resultBytes = cipher.doFinal(bytes);
                return base64Encode(resultBytes);
            }
        } catch (Exception e) {
            log.error("encrypt error", AESUtils.class, new Object[]{e});
            return null;
        }
    }

    private static String aesDecrypt(String value, String encryptKey) {
        try {
            String key = encryptKey(encryptKey);
            if (null == key) {
                return null;
            } else {
                byte[] bytes = base64Decode(value);
                KeyGenerator kgen = KeyGenerator.getInstance("AES");
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(key.getBytes());
                kgen.init(128, secureRandom);
                Cipher cipher = Cipher.getInstance("AES");//默认 AES = AES/ECB/PKCS5Padding
                cipher.init(2, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
                byte[] result = cipher.doFinal(bytes);
                return new String(result, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            log.error("encrypt error", AESUtils.class, new Object[]{e});
            return null;
        }
    }

    private static String base64Encode(byte[] bytes) {
        return new String(Base64.encodeBase64(bytes), StandardCharsets.UTF_8);
    }

    private static byte[] base64Decode(String base64Value) {
        byte[] decode = base64Value.getBytes(StandardCharsets.UTF_8);
        return null != decode ? Base64.decodeBase64(decode) : new byte[0];
    }

    private static String encryptKey(String key) {
        return EmptyUtils.isEmpty(base64Decode(key)) ? null : new String(base64Decode(key), StandardCharsets.UTF_8);
    }