zoukankan      html  css  js  c++  java
  • AES简介以及配合Base64实现加密解密

    一、对称加密

    1、什么是对称加密

    对称加密就是指加密和解密使用同一个密钥的加密方式。

    2、对称加密的工作过程

    发送方使用密钥将明文数据进行加密成密文,发送给接收方,接收方收到密文后,使用同一个密钥将密文解密成明文。

    3、对称加密的优点

    加密计算量小,速度快,适合对大量数据进行加密的场景。

    4、对称加密的两大不足

    • 密钥传输问题:由于对称加密的加密和解密用的是同一个密钥,所以对称加密的安全性就不仅仅取决于加密算法本身的强度,更取决于密钥是否被安全保管,因此加密者如何将密钥安全传递到解密者手里,就成了对称加密面临的关键问题。
    • 密钥管理问题:随着密钥数量增多,密钥管理问题会逐渐显现出来。

    二、AES加密算法

    AES加密算法是众多对成绩密算法中的一种,它的英文全称是Advanced Encryption Standard,翻译过来就是高级加密标准。

    AES加密算法采用分组密码体制,每个分组数据的长度为128位16个字节,密钥长度可以是128位16个字节,192位或256位,一共有五种加密模式,我们通常采用需要初始向量IV的CBC模式,初始向量也是128位16个字节。

    1、AES的加密流程

    (1)五个关键词
    • 分组密码体制:将明文切成一段一段的来进行加密,然后把一段一段的密文拼接起来形成最终密文的加密方式。AES采用分组密码体制,即AES加密会首先把明文切成一段一段的,而且每段数据的长度要求必须是128位16个字节,如果最后一段不够16个字节,就需要用Padding来把这段数据填充满16个字节,然后分别对每段数据进行加密,最后再把每段加密数据拼接起来形成最终密文、

    • Padding:Padding就是用来把不满16个字节的分组数据填充为16个字节用的,它有三种模式:PKCS5PKCS7NOPADDINGPKCS5是指分组数据缺少几个字节,就在数据的末尾填充几个字节的几。比如缺少5个字节,就在末尾填充5个字节的5。PKCS7是指分组数据缺少几个字节,就在数据的末尾填充几个字节的0,比如缺少7个字节,就在末尾填充7个字节的0。No Padding是指不需要填充,也就是说数据的发送方肯定会保证最后一段数据也正好是16个字节。那如果在PKCS5模式下,最后一段数据的内容刚好就是16个16怎么办?那解密端就不知道这一段数据到底是有效数据还是填充数据,PKCS5模式会自动帮我们在最后一段数据后再添加16个字节的数据,而且填充的数据也是16个16,这样解密端就能知道谁是有效数据谁是填充数据了。PKCS7最后一段数据的内容的内容是16个0,也是同样的道理。解密端需要使用和加密端同样的Padding模式,才能准确的十倍有效数据和填充数据。我们开发通常采用PKCS7模式。

    • 初始向量IV:初始向量IV的作用是使加密更加安全可靠,我们使用AES加密时需要主动提供初始向量,而且只需要提供一个初始向量就够了,后面每段数据的加密向量都是前面一段的密文。初始向量IV的长度规定为128位16个字节,初始向量的来源为随机生成。

    • 密钥:AES要求密钥的长度可以是128位16个字节,192位或256位,位数越高,加密强度自然越大,但是加密的效率自然会低一些,因此要做好衡量,我们开发通常采用128位16个字节的密钥,我们使用AES加密时需要主动提供密钥,而且只需要提供一个密钥就够了,每段数据加密使用的都是这一个密钥,密钥来源为随机生成。

    • 五种加密模式:AES一共有五种加密模式,分别是ECB(电码本模式),CBC(密码分组链接模式),CTR(计算器模式),CFB(密码反馈模式),OFB(输出反馈模式)

      • ECB

        最基本的加密模式,即仅仅使用明文和密钥来加密数据,相同的明文块会被加密成相同的密文块,这样明文和密文的结构将是完全一样的,就会更容易被破解,相对来说不是那么安全,因此很少使用。

      • CBC

        CBC模式比EBC模式对了一个初始向量IV,加密的时候,第一个明文块首先会和IV做异或操作,然后在经过密钥加密,然后第一个密文块又会被作为第二个明文块的加密向量来异或,依次类推下去,相同的明文块经过加密后得到的密文块是不同的,明文接口和密文结构也不同,因此更加安全。

      • CTR

        计算器模式不常见,在CTR模式中, 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次。

      • CFBOFB

    (2)AES加密流程(主要针对CBC模式)
    > 1、首先`AES`加密会把明文按128位16个字节进行切分,如果数据的最后一段不够16个字节,会用Padding来填充。
    >
    > 2、把明文块0与初始向量IV做异或操作,再用密钥加密,得到密文块0,同时也会将密文块0用作明文块1的加密向量。
    >
    > 3、明文块1与密文块0进行异或操作,再用密钥加密,得到密文块1,以此类推。
    >
    > 4、最后把密文块拼接起来得到最终的密文。
    
    (3)、AES的加密原理

    我们探讨AES的加密原理,起始就是探讨加密器里做了什么,加密器里做了四个重要的操作,分别是:密钥扩展,初始轮,重复轮,最终轮。

    • 密钥扩展:根据初始密钥生成后面10轮密钥的操作。

      AES内部一共会执行11轮加密,AES会通过一个简单快速的混合操作,根据初始密钥依次生成后面10轮的密钥,每一轮的密钥都是通过上一轮生成的,所以每一轮的密钥都是不同的。

    • 初始轮:初始轮就是将128位的明文数据与128位的初始密钥进行异或操作

    • 重复轮:所谓重复轮,就是指把字节混淆,行移位,列混乱,加轮密钥这四个操作重复好几轮。

      重复轮重复的论述取决于密钥的长度,128位16位字节的密钥重复轮推荐重复执行9次,192位密钥重复轮推荐重复执行11次,256位密钥重复轮推荐执行13次。

    • 最终轮:最终轮其实和重复轮的操作差不多,知识在最终轮我们丢弃了列混乱这个操作。

    三、Python代码实现(配合Base64)

    import base64
    import json
    
    from Crypto.Cipher import AES
    
    
    class Aes_cbc(object):
        def __init__(self, key):
            self.key = key.encode("utf-8")     # 密钥
            self.vi = "0102030405060708".encode("utf-8")   # 偏移量
            self.mode = AES.MODE_CBC  # 加密模式
    
        def encryption(self, data):   # 加密
            pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16)  # 对字符串进行补位
            data = pad(json.dumps(data)).encode("utf-8")
            cipher = AES.new(self.key, self.mode, self.vi)
            encryptedbytes = cipher.encrypt(data)
            # 使用Base64进行编码,返回byte字符串
            encodestrs = base64.b64encode(encryptedbytes)
            # 对byte字符串按照utf-8进行解码,并返回
            return encodestrs.decode("utf-8")
    
        def decrypt(self, data):   # 解密
            encodebytes = base64.decodebytes(data.encode("utf-8"))   # 将加密的数据转换为bytes数据类型
            cipher = AES.new(self.key, self.mode, self.vi)
            text_decrypted = cipher.decrypt(encodebytes)
            unpad = lambda s: s[0:-s[-1]]
            return unpad(text_decrypted).decode("utf-8")
    
    
    
    if __name__ == '__main__':
        a = Aes_cbc("0CoJUm6Qyw8W8jud")
        r_code ={
            "code": {
                "code": "0000",
                "msgId": "Success",
                "msg": "成功",
            },
            "bo": {
                "applyId": "REQX10000001423",
                "openStatus": "1"
            },
            "other": {
                "syncType": "2"
            }
        }
        print(a.encryption(r_code))
        print(json.loads(a.decrypt(a.encryption(r_code))))
    
  • 相关阅读:
    CentOS 6.5下快速搭建ftp服务器
    Ubuntu增加swap交换空间的步骤
    mysql官方下载安装教程(centos)
    阿里云上遇到: virtual memory exhausted: Cannot allocate memory
    解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误
    centos安装nodejs和配置npm
    JavaScript(二)-精简
    JavaScript(一)
    ease,seae-in,ease-in-out,ease-out区别
    安装 sass 文档
  • 原文地址:https://www.cnblogs.com/huiyichanmian/p/12539984.html
Copyright © 2011-2022 走看看