风也温柔

计算机科学知识库

java简单加密解密算法-AES算法详解

  AES算法详解
  认识AES 什么是AES
  密码学中的高级加密标准( ,AES),又称加密法,是美国联邦政府采用的一种区块加密标准。
  AES简介
  这个标准用来替代原先的DES(Data ),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一 [1] 。
  该算法为比利时密码学家Joan 和 所设计,结合两位作者的名字,以之名命之java简单加密解密算法-AES算法详解,投稿高级加密标准的甄选流程。(的发音近于 “Rhine doll”。)
  AES的加密模式及个模式加密的优缺点
  AES的分组长度是,三种可选密钥长度,和,轮数分别为10、12和14
  常见五中工作模式:
  ECB (,电子密码本)
  优点:简单、可并行计算、误差不传递
  缺点:不能隐藏明文模式(比如图像加密轮廓仍在)、主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
  用途:需要并行加密的应用
  CBC ( Block ,密码分组链接)∶
  优点:不容易主动攻击(误差传递)、适合长报文,是SSL、IPSec标准
  缺点:无法并行、误差传递
  用途:长报文传输,SSL和IPSec
  CFB (,密码反馈)︰
  优点:不容易主动攻击(误差传递),分组转变为流模式,可加密小于分组数据缺点:无法并行、误差传递
  OFB (,输出反馈)︰
  优点:分组转为流模式、可加密小于分组数据
  缺点:主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
  用途:通信信道质量不高时使用,比如卫星通信
  CTR (,计数器模式)∶
  描述:计算器模式不常见,在CTR模式中,有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次。
  优点:并行、一次一密、不传递误差
  缺点:主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
  总结
  分组模式: ECB、CBC和CTR;
  流模式: CFB、OFB
  传递误差: CBC、CFB
  不传递误差: ECB、OFB和CTR
  可并行: ECB、CTR
  不可并行: CBC、OFB、CFB
  AES算法加密过程 明文块的生成
  我们输入的明文会被分割成大小相同的明文块,一个明文块大小为16字节、128位,如果最后一块小于16k那就需要涉及填充和链加密模式了。
  假设明文块为:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  上述明文块按照顺序,从上往下,从左到右变换成以下明文矩阵
  0 4 8 12
  1 5 9 13
  2 6 10 14
  3 7 11 15
  每个位置占8位,第n个字节对应的位置(i , j)可以按以下方式计算
  i = n%4;
  j = n/4;(向下取整)
  n = i + 4j;
  同样的,密钥也是16字节 128位
  加密的基本步骤
  在这里插入图片描述
  其中的明文矩阵为字节表示的4x4的矩阵,而状态矩阵是将明文矩阵转为十六进制后的矩阵。
  初始变换
  一个明文块16k 转变成 4 X 4(16进制)的矩阵,与子密钥生成的初始矩阵4 X 4(16进制),做一个异或。
  拓展轮密钥 拓展原因及使用顺序
  由于后续要做10轮加密操作,每轮都要使用一个4X4的矩阵。那么单单一个子密钥生成的4X4的矩阵自然是不够的,所以需要对密钥做扩展。也就是把4X4字节的子密钥 ——> 4X43轮密钥,从4列扩展为44列(这里需要注意的是: 初始变换已经用了第0列到第三列,所以10轮加密从第4列开始取)
  比如第i轮(i ∈ [1,10])加密,使用第4i到 4i + 3列的数据作为子密钥矩阵。第1轮,使用第4列,到第4 + 3列,最后一轮使用第40列,到43列作为密钥矩阵。
  生成规则
  假设i是我们要生成的扩展子密钥列数,如果 i 为四的倍数,那么该列:Wi = Wi-4 ⊕ T(Wi-1)
  其中T函数表示三个操作:
  字循环
  将Wi-1列赋值到 Wi上,列【b0, b1, b2 ,b3】更改为 【b1 , b2 , b3 , b0】(注意,这里是列,应该是竖起来的,我这里为了方便所以是横的)
  字节代换
  使用S盒代换,与下面的S_Box一致
  轮常量异或
  与同轮(第一轮和常量矩阵第一列 第二轮和常量矩阵第二列),给定的矩阵进行同列⊕。可以看出每列对应的i为:4 8 12 16 20 24 28 32 36 40
  在这里插入图片描述
  当i不是四的倍数时:Wi = Wi-4 ⊕ Wi-1java简单加密解密算法,只做一个异或。
  9轮中间变换 字节代换
  S-box的替换。比如00,表示用 第0行 第0列 对应的是0x63 ,所以00替换成63。 这里的0x表示的是十六进制。
  在这里插入图片描述
  行移位
  除开第一行java简单加密解密算法,第二行往左移动一位,第二行往左移动第二位,第三行往左移动第三位。(只算明文列数4–也就是128字节)
  列混合
  在这里插入图片描述
  左乘一个给定的 4 X 4矩阵,进行单个结果有限域上的二元运算(GF2^8)
  可以点这里详细了解X乘运算.
  轮密钥加
  与密钥扩展得到的10轮密钥中的一组逐字节做异或(与对应位置上的数据做一个异或)。比如明文状态矩阵为4列(即明文块占128位 16字节),第 i 轮选取轮密钥的W[ 4 i ] ~ W[ 4 i + 3]。 比如第一轮 i=1.那么取的轮密钥矩阵中的是4 ~ 7列。
  最后一轮变换
  与前九轮相比 最后一轮没有列混合,其他三位操作一样。
  密文矩阵转为密文
  然后将得到的密文矩阵转为密文状态矩阵再转为密文输出。
  简单使用Java封装的AES算法 使用到的类及其基本的方法
  JDK链接,有兴趣的自己详细了解。下文只介绍简单使用涉及到类以及方法。
  .class
  该类提供了一个对称密钥生成器的功能。
   //生成一个AES算法的密钥生成器

    KeyGenerator kg = KeyGenerator.getInstance("AES");
    //使用给定字节数组生成安全随机密码对象,并用该对象初始化该密钥生成器(生成密钥长度为128位)
    kg.init(128, new SecureRandom(rule.getBytes("UTF-8")));
    //生成一个种子密钥。
    SecretKey ruleKey = kg.generateKey();

  .class
  该接口的目的是为所有密钥(不同算法的密钥)接口分组。
  .class
  它可以用于从字节数组构造一个 。
   //从给定的字节数组构造一个aes密钥 skCode为给定的字节数组 按AES算法生成密钥

    SecretKey aesKey = new SecretKeySpec(skCode , "AES");

  .class
  该类提供主要的加密、解密操作。
   //获取实例

    Cipher cp = Cipher.getInstance("AES");
    //用密钥初始化此密码  其中前一个参数表示加密(设置为:Cipher.DECRYPT_MODE就是解密) aesKey为密钥
    cp.init(Cipher.ENCRYPT_MODE , aesKey);
    //需要加密的字符串的字节数组
    byte[] contenCode = text.getBytes("UTF-8");
    //加密后得到的是字节数组
    byte[] enCode = cp.doFinal(contenCode);

  Java中AES算法的简单使用 简单使用
   /*

         * @description 加解密整合到一个方法中来
         * @author 三文鱼
         * @date 9:41 2022/3/18
         * @param rule 自己设置的密钥
         * @param text 需要加密的明文或者解密的密文
         * @param encrypt true表示加密 false表示解密
         * @return java.lang.String 返回加密或者解密过的字符串
         **/
        public static String getContrary(String rule , String text , boolean encrypt ) throws Exception {
            String result = "";
            try{
                //生成一个AES算法的密钥生成器
                KeyGenerator kg = KeyGenerator.getInstance("AES");
                //使用给定的随机源(可以看作你自己设置的密码,但对于程序而言,你输入的只是一个生成密钥的”种子“)
                // 初始化该密钥生成器(生成密钥长度为128位)
                kg.init(128, new SecureRandom(rule.getBytes("UTF-8")));
                //生成一个种子密钥。
                SecretKey ruleKey = kg.generateKey();
                //获取其主要编码格式的密钥
                byte[] skCode = ruleKey.getEncoded();
                //从给定的字节数组构造一个aes密钥
                SecretKey aesKey = new SecretKeySpec(skCode , "AES");
                //该类提供加密和解密的加密密码的功能。 它构成了Java加密扩展(JCE)框架的核心。
                Cipher cp = Cipher.getInstance("AES");
                //判断是否是加密
                if(encrypt) {
                    //用密钥初始化
                    cp.init(Cipher.ENCRYPT_MODE , aesKey);
                    byte[] contenCode = text.getBytes("UTF-8");
                    //加密
                    byte[] enCode = cp.doFinal(contenCode);
                    //按照base64编码
                    result = new BASE64Encoder().encode(enCode);
                }else{
                    cp.init(Cipher.DECRYPT_MODE , aesKey);
                    //将密文按照base64解码
                    byte[] enCode = new BASE64Decoder().decodeBuffer(text);
                    //解密生成明文字节数组
                    byte[] decryptCode = cp.doFinal(enCode);
                    //明文字节数组生成明文
                    result = new String(decryptCode , "UTF-8");
                }
                return result;
            }catch (Exception ex) {
                ex.printStackTrace();
            }
            return null;
        }

  参考资料
  可厉害的土豆: AES加密过程详解| 对称加密| -128| 密码学| 信息安全
  我有一个小脑瓜 :
  百度百科: AES
  百度文库: AES加密模式优缺点及用途

  文章来源:https://blog.csdn.net/qq_44717657/article/details/123543438