mirror of
https://github.com/fastapi-practices/fastapi_best_architecture.git
synced 2025-08-26 04:33:09 +08:00
Add department-related interfaces and others (#101)
* Add tool to build tree structure data * Update to keyword parameter style * Add department-related interfaces * Update departmental section interface permissions * Add TODO and minor fixes * Fix department relationships * Fix user foreign key relationship deletion setting * Add path parameters to the operation log * Complete todo items * Update department deletion logic * Update operation log entry records * Add AES encryption algorithm * Add operation log request entry to the secret * Fix naming prefixes * Add easy encryption tools * FIX CASBIN_EXCLUDE typing * Update user password reset interface * Add confirm_password to the operation log encryption
This commit is contained in:
66
backend/app/utils/encrypt.py
Normal file
66
backend/app/utils/encrypt.py
Normal file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
from cryptography.hazmat.backends.openssl import backend
|
||||
from cryptography.hazmat.primitives import padding
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
|
||||
|
||||
class AESCipher:
|
||||
def __init__(self, key: bytes | str):
|
||||
"""
|
||||
:param key: 密钥,16/24/32 bytes 或 16 进制字符串
|
||||
"""
|
||||
self.key = key if isinstance(key, bytes) else bytes.fromhex(key)
|
||||
|
||||
def encrypt(self, plaintext: bytes) -> bytes:
|
||||
"""
|
||||
AES 加密
|
||||
|
||||
:param plaintext: 加密前的明文
|
||||
:return:
|
||||
"""
|
||||
iv = os.urandom(16)
|
||||
cipher = Cipher(algorithms.AES(self.key), modes.CBC(iv), backend=backend)
|
||||
encryptor = cipher.encryptor()
|
||||
padder = padding.PKCS7(cipher.algorithm.block_size).padder() # type: ignore
|
||||
padded_plaintext = padder.update(plaintext) + padder.finalize()
|
||||
ciphertext = encryptor.update(padded_plaintext) + encryptor.finalize()
|
||||
return iv + ciphertext
|
||||
|
||||
def decrypt(self, ciphertext: bytes | str) -> bytes:
|
||||
"""
|
||||
AES 解密
|
||||
|
||||
:param ciphertext: 解密前的密文, bytes 或 16 进制字符串
|
||||
:return:
|
||||
"""
|
||||
ciphertext = ciphertext if isinstance(ciphertext, bytes) else bytes.fromhex(ciphertext)
|
||||
iv = ciphertext[:16]
|
||||
ciphertext = ciphertext[16:]
|
||||
cipher = Cipher(algorithms.AES(self.key), modes.CBC(iv), backend=backend)
|
||||
decryptor = cipher.decryptor()
|
||||
unpadder = padding.PKCS7(cipher.algorithm.block_size).unpadder() # type: ignore
|
||||
padded_plaintext = decryptor.update(ciphertext) + decryptor.finalize()
|
||||
plaintext = unpadder.update(padded_plaintext) + unpadder.finalize()
|
||||
return plaintext
|
||||
|
||||
|
||||
class Md5Cipher:
|
||||
@staticmethod
|
||||
def encrypt(plaintext: bytes | str) -> str:
|
||||
"""
|
||||
MD5 加密
|
||||
|
||||
:param plaintext: 加密前的明文
|
||||
:return:
|
||||
"""
|
||||
import hashlib
|
||||
|
||||
md5 = hashlib.md5()
|
||||
if isinstance(plaintext, str):
|
||||
md5.update(plaintext.encode('utf-8'))
|
||||
else:
|
||||
md5.update(plaintext)
|
||||
return md5.hexdigest()
|
Reference in New Issue
Block a user