博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python(3.x) 实现AES 加解密
阅读量:5962 次
发布时间:2019-06-19

本文共 3323 字,大约阅读时间需要 11 分钟。

首先 安装cryptography

sudo pip3 install cryptography

确认安装的是2.1.x版本 (1.x版本的api是不一样的).

文件头部的声明为:

# coding: utf-8import osfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modesfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import paddingimport base64# 128bits block sizeaes_block_size = 16

我们可以生成一个随机的密钥:

def get_random_key_readable(key_size=256):    '''    get random key for symmetric encryption    with key_size bits    :param key_size: bit length of the key    :return: bytes key    '''    # length for urandom    ulen = int(key_size/8/4*3)    key = base64.b64encode(os.urandom(ulen))    return key

注意要使用密码学安全的随机方法os.urandom.

这里生成的是str而不是bytes, 为了可读性.

采用AES CBC 加密:

def aes_cbc_encrypt(message, key):    '''    use AES CBC to encrypt message, using key and init vector    :param message: the message to encrypt    :param key: the secret    :return: bytes init_vector + encrypted_content    '''    iv_len = 16    assert type(message) in (str,bytes)    assert type(key) in (str,bytes)    if type(message) == str:        message = bytes(message, 'utf-8')    if type(key) == str:        key = bytes(key, 'utf-8')    backend = default_backend()    iv = os.urandom(iv_len)    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)    encryptor = cipher.encryptor()    padder = padding.PKCS7(128).padder()    padded_data = padder.update(message) + padder.finalize()    enc_content = encryptor.update(padded_data) + encryptor.finalize()    return iv + enc_content

内容加密前需要padding到128bit(16bytes)的整数倍长度才可. cryptography有对应padding方法.

初始向量为16bit长度. 返回初始向量+加密数据.

解密方法为:

def aes_cbc_decrypt(content, key):    '''    use AES CBC to decrypt message, using key    :param content: the encrypted content using the above protocol    :param key: the secret    :return: decrypted bytes    '''    assert type(content) == bytes    assert type(key) in (bytes, str)    if type(key) == str:        key = bytes(key, 'utf-8')    iv_len = 16    assert len(content) >= (iv_len + 16)    iv = content[:iv_len]    enc_content = content[iv_len:]    backend = default_backend()    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)    unpadder = padding.PKCS7(128).unpadder()    decryptor = cipher.decryptor()    dec_content = decryptor.update(enc_content) + decryptor.finalize()    real_content = unpadder.update(dec_content) + unpadder.finalize()    return real_content

我们可以随机生成一些message测试下加解密:

import randomimport unittestimport timefrom app.libs.crypto_enc import *from app.libs.crypto_sign import *class TestAESEnc(unittest.TestCase):    def test_aes_enc_dec(self):        key = get_random_key_readable()        print('start test_aes_enc_dec')        total_len = 0        s = time.time()        for i in range(100):            mlen = random.randint(1, 1024*1024)            total_len += mlen            message = os.urandom(mlen)            enc = aes_cbc_encrypt(message, key)            dec = aes_cbc_decrypt(enc, key)            self.assertEqual(message, dec, 'aes message len {} is not equal'.format(mlen))        e = time.time()        print('total_len', total_len)        print('total_time', e - s)        print('speed', total_len / (e - s))if __name__ == '__main__':    unittest.main()

注意这里的速度测试是不准的, 因为包含了urandom的时间, 而这个方法比较耗时.

但是仍然可以看到, AES的加解密速度是极快的.

转载地址:http://oejax.baihongyu.com/

你可能感兴趣的文章
Linux报“Unknown HZ value! (288) Assume 100”错误
查看>>
mysql多实例实例化数据库
查看>>
我的友情链接
查看>>
golang xml和json的解析与生成
查看>>
javascript 操作DOM元素样式
查看>>
Android 内存管理 &Memory Leak & OOM 分析
查看>>
【查找算法】基于存储的查找算法(哈希查找)
查看>>
JavaWeb网上图书商城完整项目--day02-10.提交注册表单功能之页面实现
查看>>
做程序开发的你如果经常用Redis,这些问题肯定会遇到
查看>>
006android初级篇之jni数据类型映射
查看>>
org.openqa.selenium.StaleElementReferenceException
查看>>
HBase 笔记3
查看>>
Linux嵌入式GDB调试环境搭建
查看>>
java分析jvm常用指令
查看>>
【Linux】Linux 在线安装yum
查看>>
Atom 编辑器系列视频课程
查看>>
[原][osgearth]osgearthviewer读取earth文件,代码解析(earth文件读取的一帧)
查看>>
阿里百川码力APP监控 来了!
查看>>
使用dotenv管理环境变量
查看>>
温故js系列(11)-BOM
查看>>