python 3 x 實現AES 加解密

2021-09-14 02:50:29 字數 3731 閱讀 3653

首先 安裝cryptography

sudo pip3 install cryptography
確認安裝的是2.1.x版本 (1.x版本的api是不一樣的).

檔案頭部的宣告為:

# coding: utf-8

import os

from cryptography.hazmat.primitives.ciphers import cipher, algorithms, modes

from cryptography.hazmat.backends import default_backend

from cryptography.hazmat.primitives import padding

import base64

# 128bits block size

aes_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 random

import unittest

import time

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的加解密速度是極快的.

python3 X棧的實現

棧 stacks 是一種只能通過訪問其一端來實現資料儲存與檢索的線性資料結構,具有後進先出 last in first out,lifo 的特徵 class stack object 棧 def init self self.list def push self,item 入棧 def pop se...

Python3 x編碼問題

1.記事本的ansi編碼為系統本地編碼,我的是gbk open 函式的encoding引數預設是本地編碼,也就是gbk,所以直接讀取ansi編碼的記事本檔案是木有問題的。怎麼檢視系統本地編碼?在cmd下輸入 chcp 從下表可以看出,936對應gbk編碼 下表列出了所有支援的 頁及其國家 地區 或者...

Python 內建函式(Python 3 x)

1 type obj 返回變數型別 2 isinstance object,class or type or tuple 測試物件是否為指定型別的例項 4 range start,end step 返回乙個 start,end 內的 range 物件,start 預設為 0,step 預設為 1 5...