dict-server/app/utils/phone_encrypt.py

55 lines
1.5 KiB
Python

import base64
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from dotenv import load_dotenv
load_dotenv()
class PhoneEncrypt:
def __init__(self, key: bytes):
self.key = key
if len(self.key) not in (16, 24, 32):
raise ValueError("AES 密钥必须是 16/24/32 字节")
@classmethod
def from_env(cls):
hex_key = os.getenv("AES_SECRET_KEY")
return cls(bytes.fromhex(hex_key))
def encrypt(self, phone: str) -> str:
"""
加密手机号 -> 返回 Base64 字符串
:return iv为解密初始数
ct为加密密文
"""
cipher = AES.new(self.key, AES.MODE_CBC) # 随机 IV
ct_bytes = cipher.encrypt(pad(phone.encode(), AES.block_size))
iv = base64.b64encode(cipher.iv).decode()
ct = base64.b64encode(ct_bytes).decode()
return f"{iv}:{ct}"
def decrypt(self, data: str) -> str:
"""解密 Base64 字符串 -> 返回手机号"""
iv_b64, ct_b64 = data.split(":")
iv = base64.b64decode(iv_b64)
ct = base64.b64decode(ct_b64)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
return pt.decode()
def main():
phone_encrypt = PhoneEncrypt()
encrypted = phone_encrypt.encrypt("13568847988")
print(encrypted)
decrypted = phone_encrypt.decrypt(encrypted)
print(decrypted)
if __name__ == '__main__':
main()