# -*- coding=utf-8-*-
# 需要先安装pip3 install pycryptodome
import base64
from decimal import Decimal
import datetime
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def force_str(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Similar to smart_str(), except that lazy instances are resolved to
strings, rather than kept as lazy objects.
If strings_only is True, don't convert (some) non-string-like objects.
"""
# Handle the common case first for performance reasons.
if issubclass(type(s), str):
return s
if strings_only and is_protected_type(s):
return s
try:
if isinstance(s, bytes):
s = str(s, encoding, errors)
else:
s = str(s)
except UnicodeDecodeError as e:
print("error: ",e)
return s
def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
return force_str(s, encoding, strings_only, errors)
_PROTECTED_TYPES = (
type(None), int, float, Decimal, datetime.datetime, datetime.date, datetime.time,
)
def is_protected_type(obj):
"""Determine if the object instance is of a protected type.
Objects of protected types are preserved as-is when passed to
force_str(strings_only=True).
"""
return isinstance(obj, _PROTECTED_TYPES)
def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Similar to smart_bytes, except that lazy instances are resolved to
strings, rather than kept as lazy objects.
If strings_only is True, don't convert (some) non-string-like objects.
"""
# Handle the common case first for performance reasons.
if isinstance(s, bytes):
if encoding == 'utf-8':
return s
else:
return s.decode('utf-8', errors).encode(encoding, errors)
if strings_only and is_protected_type(s):
return s
if isinstance(s, memoryview):
return bytes(s)
return str(s).encode(encoding, errors)
class Crypto:
def __init__(self, key=None):
assert len(key) >= 32, "mirage key length must more than 32!"
self.key = base64.urlsafe_b64encode(force_bytes(key))[:32]
def encrypt(self, text):
if text is None:
return None
try:
self.try_decrypt(text)
return text
except Exception:
return self.try_encrypt(text)
def try_encrypt(self, text):
encryptor = Cipher(algorithms.AES(self.key), modes.ECB(), default_backend()).encryptor()
padder = padding.PKCS7(algorithms.AES(self.key).block_size).padder()
padded_data = padder.update(force_bytes(text)) + padder.finalize()
encrypted_text = encryptor.update(padded_data) + encryptor.finalize()
return force_text(base64.urlsafe_b64encode(encrypted_text))
def try_decrypt(self, encrypted_text):
decryptor = Cipher(algorithms.AES(self.key), modes.ECB(), default_backend()).decryptor()
padder = padding.PKCS7(algorithms.AES(self.key).block_size).unpadder()
decrypted_text = decryptor.update(base64.urlsafe_b64decode(encrypted_text))
unpadded_text = padder.update(decrypted_text) + padder.finalize()
return force_text(unpadded_text)
def decrypt(self, encrypted_text):
if encrypted_text is None:
return None
try:
return self.try_decrypt(encrypted_text)
except Exception:
return encrypted_text
# 加解密
if __name__ == '__main__':
value='5s29Lry60loQ5vEHe8Xw'
crypto = Crypto(f'hfusaf2m4ot#7)fkw#di2bu6(cv0@opwmafx8n#6=3d%x^hpl9') # 初始化密钥
if value is not None:
encrypted_text = crypto.encrypt(value)
print("加密后的字符串:",encrypted_text)
decrypted_text = crypto.decrypt(encrypted_text)
print("解密密后的字符串:",decrypted_text)
采用的是:AES/CBC/pkcs7padding 的方案