当前位置:首页 » 《资源分享》 » 正文

AES加密 — 详解_赵彦军

23 人参与  2021年11月01日 16:43  分类 : 《资源分享》  评论

点击全文阅读


转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/120285594
本文出自【赵彦军的博客】

文章目录

  • AES 简介
  • 对称加密
  • 加密模式
  • PKCS5Padding到底是什么?
  • 偏移量
  • 字符集
  • 实际工作中的加密流程
  • AES 加密/解密 注意的问题
  • 实战,AES加解密

AES 简介

  • DES 全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS)
  • AES 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。

为什么 DES 被废弃?

我们知道数据加密标准(Data Encryption Standard: DES)的密钥长度是56比特,因此算法的理论安全强度是2的56次方。但二十世纪中后期正是计算机飞速发展的阶段,元器件制造工艺的进步使得计算机的处理能力越来越强,DES将不能提供足够的安全性。

简单来说,DES标准的秘钥长度要求太短,安全性不够。

为什么AES算法被称为 Rijndael 算法?

1997年1月2号,美国国家标准技术研究所(National Institute of Standards and Technology: NIST)宣布希望征集高级加密标准(Advanced Encryption Standard: AES)[3],用以取代DES。AES得到了全世界很多密码工作者的响应,先后有很多人提交了自己设计的算法。最终有5个候选算法进入最后一轮:Rijndael,Serpent,Twofish,RC6和MARS,下图分别为其中的5位作者。最终经过安全性分析、软硬件性能评估等严格的步骤,Rijndael算法获胜。

为什么AES算法安全性高?

AES的区块长度固定为128位,密钥长度则可以是128 bit,192 bit 或256位 bit 。换算成字节长度,就是密码必须是 16个字节,24个字节,32个字节。AES密码的长度更长了,破解难度就增大了,所以就更安全。

对称加密

  • 对称加密 : 也就是加密秘钥和解密秘钥是一样的。
  • 非对称加密 : 也就是加密秘钥和解密秘钥是不一样的。

AES 是对称加密算法,优点:加密速度快;缺点:如果秘钥丢失,就容易解密密文,安全性相对比较差

RSA 是非对称加密算法 , 优点:安全 ;缺点:加密速度慢

AES加密需要:明文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)
AES解密需要:密文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)

AES的算法模式一般为 AES/CBC/PKCS5Padding

加密模式

AES的加密模式有以下几种

  • 电码本模式(ECB)
  • 密码分组链接模式(CBC)
  • 计算器模式(CTR)
  • 密码反馈模式(CFB)
  • 输出反馈模式(OFB)

密码分组链接模式(CBC):将整段明文切成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。

在这里插入图片描述
根据图示,在 CBC 模式下,使用 AES 加解密方式进行分组加解密时,需要用到的两个参数

  • 1、初始化向量,也就是偏移量

  • 2、加解密秘钥

PKCS5Padding到底是什么?

为什么 JAVA 里指定算法时,写的是 AES/CBC/PKCS5Padding,每个都是什么含义,又有什么作用。

  • AES,加解密算法

  • CBC,数据分组模式

  • PKCS5Padding,数据按照一定的大小进行分组,最后分剩下那一组,不够长度,就需要进行补齐, 也可以叫 补齐模式

简单的说:拿到一个原始数据以后,首先需要对数据进行分组,分组以后如果长度不满足分组条件,需要进行补齐,最后形成多个分组,在使用加解密算法,对这多个分组进行加解密。所以这个过程中,AES,CBC,PKCS5Padding 缺一不可。

在对数据进行加解密时,通常将数据按照固定的大小(block size)分成多个组,那么随之就产生了一个问题,如果分到最后一组,不够一个 block size 了,要怎么办?此时就需要进行补齐操作。

补齐规则:The value of each added byte is the number of bytes that are added, i.e. N bytes, each of value N are added.

举例:

36 位的 UUID,如果按照 block size=16 字节(即 128 比特),那么就需要补齐到 48 位,差 12 个字节。那么最后填充的 12 个字节的内容,都是字节表示的 0x0c(即 12)。

偏移量

偏移量 的添加一般是为了增加 AES 加密的复杂度,增加数据的安全性。一般在 AES_256 中会使用到 偏移量 ,而在 AES_128 加密中不会使用到。

字符集

AES 加密中,特别也要注意到字符集的问题。一般用到的字符集是 utf-8gbk

实际工作中的加密流程

在实际的工作中,客户端跟服务器交互一般都是字符串格式,所以一个比较好的加密流程是:

  • 加密流程 :明文通过 密钥 (有时也需要 偏移量 ),利用 AES 加密算法,然后通过 Base64 转码,最后生成加密后的字符串。
  • 解密流程 :加密后的字符串通过 密钥 (有时也需要 偏移量 ),利用 AES 解密算法,然后通过 Base64 转码,最后生成解密后的字符串。

AES 加密/解密 注意的问题

AES 加密/解密的时候,通常是用在服务端和客户端通讯的过程中,一端加密传输,另一端解密使用。虽然 AES 加密看似简单,但在使用过程过程中,仍然会出现在一端加密ok,但是另一端解密失败的情况。一旦出现 AES 解密失败,我们可以通过以下几个方面进行排查:

1. AES 加密/解密 使用相同的密钥
2. 若涉及到偏移量,则AES 加密/解密 使用的偏移量要一样
3. AES 加密/解密 要使用相同加密数位,如都使用`AES_256`
4. AES 加密/解密 使用相同的字符集
5. AES 加密/解密 使用相同的加密,填充模式,如都使用`AES/CBC/PKCS5Padding`模式
6. 由于不同开发语言(CJava)及不同开发环境(JavaAndroid)的影响,可能相同的加解密算法在实现上出现差异,若你们注意到这个差异,就可能导致加解密出现问题

最后,当我们需要验证自己的 AES 解密算法是否与别人的加密方法为一套的时候。可以让加密方发你一份加密后的密文和加密前的明文,然后你用密文解密,看解密结果和加密方发你的是否一致。需要注意的是,加密方给你的明文要尽量简洁,如就 中国 二字,这样既能看出加密方和解密方的字符集是否一致,而且能避免复制粘贴等环节出现空格,回车等转义字符对验证结果的干扰。

实战,AES加解密

首先定义加密、解密工具类

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;

/**
 * AES加解密工具类
 */
public class AES {

    /**
     * AES加密
     *
     * @param key
     * @param iv
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public static byte[] encryptAes(byte[] data, byte[] key, byte[] iv)
            throws GeneralSecurityException, IOException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
        return cipher.doFinal(data);
    }

    /**
     * AES解密
     *
     * @param key
     * @param iv
     * @return
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public static byte[] decryptAesToByteString(byte[] data, byte[] key, byte[] iv)
            throws GeneralSecurityException, IOException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
        return cipher.doFinal(data);
    }
}

加密和解密的代码很像,唯一的不同点是,加密 Cipher.ENCRYPT_MOD , 解密用的是 Cipher.DECRYPT_MODE

下面我们写一个测试代码:

        try {
            //加密密码
            String key = "zhaoyanjunzhaoy1";
            //偏移量
            String iv = "1234567890123456";

            String message = "今天是周二,我好开心";

            //加密
            byte[] encryResult = AES.encryptAes(message.getBytes(), key.getBytes(), iv.getBytes());

            //解密
            byte[] decryResult = AES.decryptAesToByteString(encryResult, key.getBytes(), iv.getBytes());
            System.out.println("解密数据 = " + new String(decryResult));

        } catch (IOException | GeneralSecurityException e) {
            e.printStackTrace();
        }

输出结果:

解密数据 = 今天是周二,我好开心

可以看到数据已经正常解密了。


点击全文阅读


本文链接:http://zhangshiyu.com/post/30366.html

加密  解密  算法  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1