Java实现AES加解密

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.SecureRandom;
 
 
public class AESUtil {
    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
 
    /**
     * 指定随机字符串(密码)生成密钥
     *
     * @param randomKey 加解密的密码
     * @throws Exception
     */
    public static byte[] getSecretKey(String randomKey) throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM); //秘钥生成器,指定秘钥算法
 
        //初始化此密钥生成器,指定AES的秘钥长度为128
        if (StringUtils.isBlank(randomKey)) {   //不指定密码
            keyGenerator.init(128);
        } else {    //指定密码
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(randomKey.getBytes());
            keyGenerator.init(128, random);
        }
 
        SecretKey secretKey = keyGenerator.generateKey();   //生成密钥
        return secretKey.getEncoded();
    }
 
    /**
     * 加密
     *
     * @param data 待加密数据
     * @param key  密钥
     * @return byte[]   加密数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, Key key) throws Exception {
        return encrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
    }
 
    /**
     * 加密
     *
     * @param data 待加密数据
     * @param key  二进制密钥
     * @return byte[]   加密数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        return encrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
    }
 
    /**
     * 加密
     *
     * @param data            待加密数据
     * @param key             二进制密钥
     * @param cipherAlgorithm 加密算法/工作模式/填充方式
     * @return byte[]   加密数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, byte[] key, String cipherAlgorithm) throws Exception {
        Key k = toKey(key);
        return encrypt(data, k, cipherAlgorithm);
    }
 
    /**
     * 加密
     *
     * @param data            待加密数据
     * @param key             密钥
     * @param cipherAlgorithm 加密算法/工作模式/填充方式
     * @return byte[]   加密数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, Key key, String cipherAlgorithm) throws Exception {
        Cipher cipher = Cipher.getInstance(cipherAlgorithm);    //获取算法
        cipher.init(Cipher.ENCRYPT_MODE, key);                  //设置加密模式,并指定秘钥
        return cipher.doFinal(data);                            //加密数据
    }
 
    /**
     * 解密
     *
     * @param data 待解密数据
     * @param key  二进制密钥
     * @return byte[]   解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        return decrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
    }
 
    /**
     * 解密
     *
     * @param data 待解密数据
     * @param key  密钥
     * @return byte[]   解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, Key key) throws Exception {
        return decrypt(data, key, DEFAULT_CIPHER_ALGORITHM);
    }
 
    /**
     * 解密
     *
     * @param data            待解密数据
     * @param key             二进制密钥
     * @param cipherAlgorithm 加密算法/工作模式/填充方式
     * @return byte[]   解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key, String cipherAlgorithm) throws Exception {
        Key k = toKey(key);
        return decrypt(data, k, cipherAlgorithm);
    }
 
    /**
     * 解密
     *
     * @param data            待解密数据
     * @param key             密钥
     * @param cipherAlgorithm 加密算法/工作模式/填充方式
     * @return byte[]   解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, Key key, String cipherAlgorithm) throws Exception {
        Cipher cipher = Cipher.getInstance(cipherAlgorithm);     //获取算法
        cipher.init(Cipher.DECRYPT_MODE, key);                   //设置解密模式,并指定秘钥
        return cipher.doFinal(data);                             //解密数据
    }
 
    /**
     * 转换密钥
     *
     * @param secretKey 二进制密钥
     * @return 密钥
     */
    public static Key toKey(byte[] secretKey) {
        return new SecretKeySpec(secretKey, KEY_ALGORITHM);   //生成密钥
    }
 
 
    public static void main(String[] args) throws Exception {
        String password = "123456";     //加解密的密码
        byte[] secretKey = getSecretKey(password);
        Key key = toKey(secretKey);
 
        String data = "AES 对称加密算法";
        System.out.println("明文 :" + data);
 
        byte[] encryptData = encrypt(data.getBytes(), key);
        String encryptDataHex = Hex.encodeHexString(encryptData);   //把密文转为16进制
        System.out.println("加密 : " + encryptDataHex);
 
        byte[] decryptData = decrypt(Hex.decodeHex(encryptDataHex.toCharArray()), key);
        System.out.println("解密 : " + new String(decryptData));
    }
}
<think>好的,用户想用Java实现AES加解密的代码或教程。首先,我需要回忆JavaAES实现方式。记得Javajavax.crypto包里有相关的类,比如Cipher、KeyGenerator、SecretKey等。 用户可能需要基础的示例代码,所以先得准备一个完整的例子,包含加密和解密两部分。要注意密钥的生成方式,AES支持128、192、256位的密钥,但默认可能受限于JCE策略文件,如果密钥长度超过128,用户可能会遇到InvalidKeyException,这时候可能需要提到如何解除限制,比如安装JCE无限强度策略文件或者使用反射绕过,但后者不太安全,所以优先建议安装策略文件。 然后,工作模式的选择,比如CBC模式需要IV参数,而ECB模式不需要,但ECB不够安全,所以示例中使用CBC更合适。同时,需要处理填充方式,比如PKCS5Padding。在代码中,要生成IV并把它和加密后的数据一起存储,解密时再取出IV。 另外,用户的问题中提到过前端和后端兼容性的问题,引用[2]和[3]提到JavaScript和Java的兼容性问题,所以可能需要提醒用户注意前后端在模式、填充、密钥处理上保持一致,比如都使用CBC模式和PKCS5Padding,以及相同的密钥和IV生成方式。 还要注意编码问题,加密后的字节数组通常需要Base64编码,方便传输和存储。所以在示例中使用Base64编码器是必要的。 可能的问题包括密钥管理、异常处理、安全性建议等,比如提醒用户不要硬编码密钥,使用安全的密钥存储方式。此外,要提到不同模式的安全性,推荐使用CBC或GCM模式,避免使用ECB。 用户可能还会遇到异常,比如InvalidKeyException,这时候需要检查密钥长度是否正确,或者是否安装了正确的策略文件。引用[5]提到通过反射修改策略,但可能不推荐,应该优先安装JCE。 最后,生成相关问题,帮助用户深入理解,比如异常处理、不同模式和填充的影响、密钥存储的最佳实践等。</think>### Java实现AES加解密的代码示例 以下是基于AES-CBC模式(带填充)的完整加解密实现代码,包含密钥生成、加密和解密流程: ```java import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.Base64; public class AESExample { private static final String AES_CBC_PADDING = "AES/CBC/PKCS5Padding"; private static final int IV_LENGTH = 16; // IV长度需与块大小一致(AES块大小=128bit) // 生成AES密钥(128位) public static SecretKey generateKey() throws Exception { KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(128); // 若需256位密钥需安装JCE策略文件 return keyGen.generateKey(); } // 加密方法 public static String encrypt(String plaintext, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance(AES_CBC_PADDING); byte[] iv = new byte[IV_LENGTH]; new SecureRandom().nextBytes(iv); // 生成随机IV cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); byte[] combined = new byte[iv.length + ciphertext.length]; System.arraycopy(iv, 0, combined, 0, iv.length); System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length); return Base64.getEncoder().encodeToString(combined); } // 解密方法 public static String decrypt(String encryptedText, SecretKey key) throws Exception { byte[] combined = Base64.getDecoder().decode(encryptedText); byte[] iv = new byte[IV_LENGTH]; System.arraycopy(combined, 0, iv, 0, iv.length); Cipher cipher = Cipher.getInstance(AES_CBC_PADDING); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); byte[] ciphertext = new byte[combined.length - IV_LENGTH]; System.arraycopy(combined, IV_LENGTH, ciphertext, 0, ciphertext.length); return new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8); } public static void main(String[] args) throws Exception { SecretKey key = generateKey(); String original = "Hello AES加密测试"; String encrypted = encrypt(original, key); System.out.println("加密结果: " + encrypted); String decrypted = decrypt(encrypted, key); System.out.println("解密结果: " + decrypted); } } ``` #### 关键点说明 1. **工作模式选择**:使用CBC模式需要初始化向量(IV),示例中将IV与密文合并存储 2. **填充方式**:PKCS5Padding是Java标准填充方案,兼容性较好[^4] 3. **密钥长度**:默认支持128位,若需256位需安装JCE无限强度策略文件[^5] 4. **编码处理**:使用Base64编码避免二进制数据转换问题 #### 跨平台兼容性建议 若需与JavaScript交互,需确保以下参数一致: - 密钥生成算法(如PBKDF2) - 工作模式(如CBC) - 填充方式(如PKCS7) - IV传输方式(如预置或拼接) 具体实现可参考前端CryptoJS库与Java的配合使用[^2]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值