Python - AES SHA1PRNG 加密解密总结
Max.Bai
2020-11
上篇文章是当时研究AES加密的时候的记录,来龙去脉可以取看这篇 python3 - AES 加密实现java中SHA1PRNG 算法
好多人回复并提问,我发现还有必要写这篇做一个总结,并写成了一个开箱即用类,添加了ECB,CBC的加解密,当然也包含SHA1PRNG,如果其他类型可以参照里面代码添加其他加密模式。
加解密的流程总结:
0. 确认加密模式、ECB、CBC等
1. key,看是否需要sha1prng, 看是否需要做padding,cbc的需要16的倍数,所有需要padding为16的倍数,或者你自己的padding方法。
2. 加密内容确认填充模式,被加密内容当为CBC的时候必须16倍数,当然就涉及到了填充模式pkcs5/7, zero deng
3. iv 只有CBC的时候需要, iv必须16倍数,要么填充,要么iv设置成16倍数
4. 确认加密输出格式 base64、hexstr
加密流程:
key --> sha1prng encode | padding | customencode
content --> padding --> transfer to bytes --> encrypt(ECB/CBC/...) --> transfer to format(base64/hexstr)
解密流程:
key --> sha1prng encode|padding|customencode
encrypted(base64/hexstr) --> transfer to bytes --> decrypt(ECB/CBC/...) --> unpadding --> transfer to str
codding by max.bai 2020-11
开箱即用的完整的代码:
包含了ECB、CBC的样例。
# -*- coding: utf-8 -*-
"""
AES crypt
requirment mode:
pycryptodome
For Java SHA1PRNG KEY
Max.Bai
2020-11
"""
import base64
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.py3compat import bchr, bord
import Crypto.Cipher.AES as AES
import hashlib
BS = AES.block_size
class AES_Crypt:
PADDING_PKCS5 = "PKCS5"
PADDING_PKCS7 = "PKCS7"
PADDING_ZERO = "ZEROPKCS"
NO_PADDING = "NOPKCS"
def __init__(self, key: bytes, mode: str = AES.MODE_ECB, padding: str = "NOPKCS") -> None:
"""AES crypt
Encrypt fllow:
key --> sha1prng encode|padding|customencode
content --> padding --> transfer to bytes --> encrypt(ECB/CBC/...) --> transfer to format(base64/hexstr)
Decrypt fllow:
key --> sha1prng encode|padding|customencode
encrypted(base64/hexstr) --> transfer to bytes --> decrypt(ECB/CBC/...) --> unpadding --> transfer to str
codding by max.bai 2020-11
Args:
key (bytes): encrypt key, if mode is CBC, the key must be 16X len.
mode (str, optional): AES mode. Defaults to AES.MODE_ECB.
padding (str, optional): AES padding mode. Defaults to "NOPKCS".
"""
self.key = key
self.pkcs = padding
@staticmethod
def get_sha1prng_key(key: str, byte_len:int=128) -> bytes:
"""
encrypt key with SHA1PRNG
same as java AES crypto key generator SHA1PRNG
key: encode/decode key
byte_len: length of key gen, same as java code kgen.init(128, secureRandom);
default is 128
"""
signature = hashlib.sha1(key.encode()).digest()
signature = hashlib.sha1(signature).digest()
len = int(byte_len/8)
return signature[:len]
@staticmethod
def padding_pkcs5(value: str) -> bytes:
"""padding pkcs5 mode
Args:
value (str): need padding data
Returns:
bytes: after padding data with bytes type
"""
padding_len = BS - len(value.encode()) % BS
return value.encode() + bchr(padding_len) * padding_len
@staticmethod
def padding_zero(value: str) -> bytes:
"""padding with zero
Args:
value (str): need padding data
Returns:
bytes: after