1.AES简介

        AES的全称是Advanced Encryption Standard,意思是高级加密标准。它的出现主要是为了取代DES加密算法的,因为我们都知道DES算法的密钥长度是56Bit,因此算法的理论安全强度是2的56次方。但二十世纪中后期正是计算机飞速发展的阶段,元器件制造工艺的进步使得计算机的处理能力越来越强,虽然出现了3DES的加密方法,但由于它的加密时间是DES算法的3倍多,64Bit的分组大小相对较小,所以还是不能满足人们对安全性的要求。于是1997年1月2号,美国国家标准技术研究所宣布希望征集高级加密标准,用以取代DES。AES也得到了全世界很多密码工作者的响应,先后有很多人提交了自己设计的算法。最终有5个候选算法进入最后一轮:Rijndael,Serpent,Twofish,RC6和MARS。最终经过安全性分析、软硬件性能评估等严格的步骤,Rijndael算法获胜。

        在密码标准征集中,所有AES候选提交方案都必须满足以下标准:

  • 分组大小为128位的分组密码。
  • 必须支持三种密码标准:128位、192位和256位。
  • 比提交的其他算法更安全。
  • 在软件和硬件实现上都很高效。

        AES密码与分组密码Rijndael基本上完全一致,Rijndael分组大小和密钥大小都可以为128位、192位和256位。然而AES只要求分组大小为128位,因此只有分组长度为128Bit的Rijndael才称为AES算法。本文只对分组大小128位,密钥长度也为128位的Rijndael算法进行分析。密钥长度为192位和256位的处理方式和128位的处理方式类似,只不过密钥长度每增加64位,算法的循环次数就增加2轮,128位循环10轮、192位循环12轮、256位循环14轮。

2.AES具体数学知识

        略....感兴趣同学可以自行查资料

3.AES加解密重要构成

1.密钥

        密钥是AES算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥。AES支持三种长度的密钥:128位,192位,256位。平时大家所说的AES128,AES192,AES256,实际上就是指的AES算法对不同长度密钥的使用。

2.填充

        要想了解填充的概念,我们先要了解AES的分组加密特性。什么是分组加密呢?我们来看看下面这张图:AES算法在对明文加密的时候,并不是把整个明文一股脑加密成一整段密文,而是把明文拆分成一个个独立的明文块,每一个明文块长度128bit。这些明文块经过AES加密器的复杂处理,生成一个个独立的密文块,这些密文块拼接在一起,就是最终的AES加密结果。假如一段明文长度是192bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit。这时候怎么办呢?就需要对明文块进行填充(Padding)。

        填充涉及以下三种填充模式:

NoPadding:

        不做任何填充,但是要求明文必须是16字节的整数倍。

PKCS5Padding(默认):

        如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6}

ISO10126Padding:

        如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数。比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,G,$,6}

4.Java代码Demo

接口api代码如下:简单AES加解密Demo——带你了解AES-LMLPHP

controller层:

简单AES加解密Demo——带你了解AES-LMLPHP 

service接口:简单AES加解密Demo——带你了解AES-LMLPHP 

impl实现类:简单AES加解密Demo——带你了解AES-LMLPHP 

工具类:

package com.example.demo.utils;

import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;


@Component
public class AESUtil {
    private static final String IV = "3412566146136412";
    private static final String ENCODING = "UTF-8";
    private static final String SECRET_KEY = "1234234234234112";

    /**
    * AES Decrypt Method
    *
     * @param ciphertext the text need to decrypt
     * @return cleartext
    * */
    public static String decrypt(String ciphertext) {
        byte[] buffer;
        byte[] bytes = Base64.getDecoder().decode(ciphertext);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8));
        SecretKeySpec secretKeySpec = new SecretKeySpec(AESUtil.SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
        Cipher cipher;
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec);
            buffer = cipher.doFinal(bytes);
            return new String(buffer,ENCODING);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES Encrypt Method
     *
     * @param cleartext the text need to decrypt
     * @return ciphertext
     * */
    public static String encrypt(String cleartext){
        try{
            byte[] raw = AESUtil.SECRET_KEY.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(AESUtil.IV.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivParameterSpec);
            byte[] bytes = cipher.doFinal(cleartext.getBytes(StandardCharsets.UTF_8));
            return new BASE64Encoder().encode(bytes);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

 测试类:简单AES加解密Demo——带你了解AES-LMLPHP

得到结果如下:简单AES加解密Demo——带你了解AES-LMLPHP 

启动服务,我们用postman验证 
简单AES加解密Demo——带你了解AES-LMLPHP

前方介绍文字摘自知乎:密码学基础:AES加密算法 - 知乎

什么是AES加密?详解AES加密算法原理流程 - 知乎 

代码原创手打不易 ,谢谢关注

06-07 17:50