使用Java实现AES加密解密

1. 介绍

AES,高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。严格地说,AES和Rijndael加密法并不完全一样(虽然在实际应用中二者可以互换),因为Rijndael加密法可以支持更大范围的区块和密钥长度。AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特。而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256比特为上限。AES有5种加密模式,分别是ECB、CBC、CTR、OFB、CFB。有5种填充方式,分别是PKCS5Padding、PKCS7Padding、ZeroPadding、ISO10126、Ansix923。

这里提供一个在线进行AES加密解密:http://tool.chacuo.net/cryptaes

2. 具体实现

加密后对数据的输出采用2种方式:Base64、Hex,其中Base64使用的是Android SDK里面的API,具体代码如下:

package com.fantasy.blogdemo.crypto.utils;

import android.util.Base64;

import com.fantasy.blogdemo.utils.ConvertUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加解密工具类
 * <pre>
 *     author  : Fantasy
 *     version : 1.0, 2019-07-12
 *     since   : 1.0, 2019-07-12
 * </pre>
 */
public class AESUtils {
    private static final String CHARSET = "UTF-8";

    /**
     * 加密,输出Base64字符串密文
     *
     * @param data           明文
     * @param key            密钥
     * @param transformation 类型,格式为:加密算法/加密模式/填充方式,举例:AES/CBC/PKCS5Padding,
     *                       相关取值可以查看下列两个文档:
     *                       <ul>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/api">JavaSE 8 API</a>
     *                       中的 javax.crypto.Cipher</li>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
     *                       Standard Algorithm Name Documentation</a></li>
     *                       </ul>
     * @param iv             偏移量,ECB模式不需要,传null
     * @return 密文
     * @throws Exception 异常
     */
    public static String encryptBase64(String data, String key, String transformation, String iv) throws Exception {
        return Base64.encodeToString(handle(data.getBytes(CHARSET), key, transformation, iv, true), Base64.NO_WRAP);
    }

    /**
     * 解密,密文为Base64字符串
     *
     * @param data           密文
     * @param key            密钥
     * @param transformation 类型,格式为:加密算法/加密模式/填充方式,举例:AES/CBC/PKCS5Padding,
     *                       相关取值可以查看下列两个文档:
     *                       <ul>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/api">JavaSE 8 API</a>
     *                       中的 javax.crypto.Cipher</li>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
     *                       Standard Algorithm Name Documentation</a></li>
     *                       </ul>
     * @param iv             偏移量,ECB模式不需要,传null
     * @return 明文
     * @throws Exception 异常
     */
    public static String decryptBase64(String data, String key, String transformation, String iv) throws Exception {
        return new String(handle(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv, false), CHARSET);
    }

    /**
     * 加密,输出十六进制字符串密文
     *
     * @param data           明文
     * @param key            密钥
     * @param transformation 类型,格式为:加密算法/加密模式/填充方式,举例:AES/CBC/PKCS5Padding,
     *                       相关取值可以查看下列两个文档:
     *                       <ul>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/api">JavaSE 8 API</a>
     *                       中的 javax.crypto.Cipher</li>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
     *                       Standard Algorithm Name Documentation</a></li>
     *                       </ul>
     * @param iv             偏移量,ECB模式不需要,传null
     * @return 密文
     * @throws Exception 异常
     */
    public static String encryptHex(String data, String key, String transformation, String iv) throws Exception {
        return ConvertUtils.bytesToHexString(handle(data.getBytes(CHARSET), key, transformation, iv, true));
    }

    /**
     * 解密,密文为十六进制字符串
     *
     * @param data           密文
     * @param key            密钥
     * @param transformation 类型,格式为:加密算法/加密模式/填充方式,举例:AES/CBC/PKCS5Padding,
     *                       相关取值可以查看下列两个文档:
     *                       <ul>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/api">JavaSE 8 API</a>
     *                       中的 javax.crypto.Cipher</li>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
     *                       Standard Algorithm Name Documentation</a></li>
     *                       </ul>
     * @param iv             偏移量,ECB模式不需要,传null
     * @return 明文
     * @throws Exception 异常
     */
    public static String decryptHex(String data, String key, String transformation, String iv) throws Exception {
        return new String(handle(ConvertUtils.hexStringToBytes(data), key, transformation, iv, false), CHARSET);
    }

    /**
     * 处理数据,加密或解密
     *
     * @param data           数据
     * @param key            密钥
     * @param transformation 类型,格式为:加密算法/加密模式/填充方式,举例:<i>AES/CBC/PKCS5Padding</i>。<br/>
     *                       相关取值可以查看下列两个文档:
     *                       <ul>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/api">JavaSE 8 API</a>
     *                       中的 javax.crypto.Cipher</li>
     *                       <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
     *                       Standard Algorithm Name Documentation</a></li>
     *                       </ul>
     * @param iv             偏移量,ECB模式不需要,传null
     * @param isEncrypt      如果是加密,则为true;如果为解密,则为false
     * @return 加密后或解密后的字节数组
     * @throws Exception 异常
     */
    private static byte[] handle(byte[] data, String key, String transformation, String iv,
                                 boolean isEncrypt) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET), "AES"); // 构造密钥
        Cipher cipher = Cipher.getInstance(transformation);
        if (iv == null || iv.length() == 0) {
            cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey);
        } else {
            IvParameterSpec ips = new IvParameterSpec(iv.getBytes(CHARSET));
            cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey, ips);
        }
        return cipher.doFinal(data);
    }

}

3.使用方式

这里以"AES/CBC/PKCS5Padding"模式为例

String transformation = "AES/CBC/PKCS5Padding";
String key = "QSfg26hg433BV42adsfDKdJN234SD523"; // 密钥长度16位、24位、32位
String iv = "d480IfADFd39f0NK"; // IV偏移量的长度必须为16位
String data = "blogDemo123"; // 待加密的数据

// 加密结果:QXvBCdQDgTB446IOFukkPA==
String result1 = AESUtils.encryptBase64(data, key, transformation, iv);

// 解密结果:blogDemo123
String result2 = AESUtils.decryptBase64(result1, key, transformation, iv);

想看更多例子可以到我的GitHub上面看看BlogDemo

发布了43 篇原创文章 · 获赞 34 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Fantasy_Lin_/article/details/95616813