AES加密解密

BG35

Posted by Blue Geek on October 21, 2019

AES加密解密

By 青衣极客 Blue Geek In 2019-10-21

在互联网世界中,海量的数据跑来跑去,这其中包括了带有敏感信息的隐私数据。虽然某厂大佬说中国人不在乎隐私,但是人终究还是会有些秘密的,而中国人是人这一点毋庸置疑。在使用企业或者其他组织提供的工具时,我们没有办法掌控网络环境,而且各种窃听和泄漏使得我们没有办法相信私人的敏感信息能够保密。这时,加密和解密的算法就可以帮助我们。虽然加解密的算法设计常常是复杂而难以理解的,只是在普通使用过程中,我们并不需要关心这些,我们需要关心的事情是:1. 加密之后是否难以破解;2.怎样加密解密。

AES加密已经在很多场合得到应用,如果密钥掌握在自己的手中,那么一般情况下是很难破解的,对于个人的信息加密而言基本够用。本文就讨论一下使用python模块实现AES加密和解密,让大家有能力对私人的敏感信息进行保密。

1. 模块安装

python中比较常用的AES加解密模块是Crypto。如果你直接导入这个模块可能或报错说找不到模块,即使你认为已经安装了类似名称的模块。遇到这种情况,网上很多教程提供的解决方案是修改python目录下的模块文件夹名。这种解决方案实在是不太可取,一种更好的解决方案是安装pycryptodome模块。使用如下指令:pip3 install pycryptodome。安装完成后就可以导入相关的模块和小工具了。

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

2. 加密

加密过程是指将一个字符串转换为意义未知的另一个字符串的操作过程。各种加密算法在加密时都有一些设置要求。这里演示的AES加密需要设置一个长度为16的bytes类型的字符串作为key。在python3中,我们通过单引号或者双引号创建的字符串为str类型,需要调用encode函数将其转换为bytes类型。同样需要进行这样转换的是被加密字符串。除此之外,对被加密字符串的长度要求是16的整数倍。对于这一点,可以通过在字符串右侧补0来实现。

def encode(text, key='1234567890123456'.encode('utf-8'), mode=AES.MODE_CBC):
    """
    功能: 加密字符串
    注意:key是长度为16的bytes类型字符串
    """
    # 将str类型转换为bytes类型
    if isinstance(text, str):
        text = text.encode('utf-8')
    # 创建加密对象
    cpt = AES.new(key, mode, key)
    # 补充0元素的个数
    add_len = 16 - (len(text) % 16)
    # 补充0元素,是的被加密字符串的长度为16的整数倍
    text = text + ('\0'*add_len).encode('utf-8')
    # 加密
    cpt_text = cpt.encrypt(text)
    # 返回一个加密后的bytes字符串
    return b2a_hex(cpt_text)
test_text = '123'
aes_str = encode(test_text)
print('aes_str={}, type(aes_str)={}'.format(aes_str, type(aes_str)))
aes_str=b'd79b53fb2d1bfa526ad8720a523b2fbe', type(aes_str)=<class 'bytes'>

加密得到的字符串是一个bytes类型的16进制串。如果需要将这个加密的字符串通过网络或者其它方式传递出去,需要使用decode函数将其转换为str类型。以免自动转换成str类型时带有“b”这样多余的字符。

3. 解密

解密操作相对于加密而言就简单很多,只是需要保证key和mode与加密时的设置一致。由于解密得到的字符串是bytes类型,需要使用bytes.decode函数将其转换为str类型。此外,在加密之前对字符串右侧进行了补0操作,这里也需要将这些补上的元素移除。

def decode(text, key='1234567890123456'.encode('utf-8'), mode=AES.MODE_CBC):
    """
    功能:解密字符串
    注意:解密使用的key和mode必须和加密时使用的一致
    """
    # 创建加密对象
    cpt = AES.new(key, mode, key)
    # 解密
    ori_text = cpt.decrypt(a2b_hex(text))
    # 返回str类型的字符串
    return bytes.decode(ori_text).rstrip('\0')
ori_text = decode(aes_str)
print('ori_text={}, type(ori_text)={}'.format(ori_text, type(ori_text)))
# 测试解密之后的字符串与原始测试字符串是否一致
if test_text == ori_text:
    print('解密成功')
else:
    print('解密失败')
ori_text=123, type(ori_text)=<class 'str'>
解密成功

最终解密得到的字符串为str类型,与原始的测试字符串进行对比发现完全一致,解密成功。

单独使用这种加密的地方大概是比较少,比如保存账户和密码,更多的需要是在互联网中传输数据。可以将加密后的字符串作为http链接的参数进行传递,或者将AES加密的字符串再使用base64加密一次,然后使用http链接传递。这种方式在构建小型系统时比较实用,也能较高程度保证数据的安全性。

【青衣极客】公众号



COMMENT

博客评论区功能由Github Issue提供,提交Issue时请以本文标题为话题

"BG35-AES加密解密"