首先 安裝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...