148 lines
4.1 KiB
Python
148 lines
4.1 KiB
Python
|
|
import hashlib
|
|||
|
|
import base64
|
|||
|
|
import secrets
|
|||
|
|
from cryptography.fernet import Fernet
|
|||
|
|
from cryptography.hazmat.primitives import hashes
|
|||
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|||
|
|
from flask import current_app
|
|||
|
|
import os
|
|||
|
|
|
|||
|
|
class SimpleCrypto:
|
|||
|
|
"""简化的加密工具类,使用 cryptography 包"""
|
|||
|
|
|
|||
|
|
def __init__(self, key=None):
|
|||
|
|
"""
|
|||
|
|
初始化加密器
|
|||
|
|
:param key: 加密密钥,默认使用应用配置中的密钥
|
|||
|
|
"""
|
|||
|
|
if key:
|
|||
|
|
self.key = key.encode() if isinstance(key, str) else key
|
|||
|
|
else:
|
|||
|
|
# 从应用配置获取密钥,或使用默认密钥
|
|||
|
|
key_str = current_app.config.get('AUTH_SECRET_KEY', 'default-key-32-chars-long')
|
|||
|
|
self.key = key_str.encode('utf-8')
|
|||
|
|
|
|||
|
|
# 使用 PBKDF2 生成固定长度的密钥
|
|||
|
|
kdf = PBKDF2HMAC(
|
|||
|
|
algorithm=hashes.SHA256(),
|
|||
|
|
length=32,
|
|||
|
|
salt=b'static_salt_for_consistency', # 固定盐值以确保一致性
|
|||
|
|
iterations=100000,
|
|||
|
|
)
|
|||
|
|
self.fernet_key = base64.urlsafe_b64encode(kdf.derive(self.key))
|
|||
|
|
self.cipher = Fernet(self.fernet_key)
|
|||
|
|
|
|||
|
|
def encrypt(self, data):
|
|||
|
|
"""
|
|||
|
|
加密数据
|
|||
|
|
:param data: 要加密的数据(字符串)
|
|||
|
|
:return: base64编码的加密结果
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
if isinstance(data, str):
|
|||
|
|
data = data.encode('utf-8')
|
|||
|
|
|
|||
|
|
encrypted_data = self.cipher.encrypt(data)
|
|||
|
|
result = base64.b64encode(encrypted_data)
|
|||
|
|
return result.decode('utf-8')
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
raise ValueError(f"加密失败: {str(e)}")
|
|||
|
|
|
|||
|
|
def decrypt(self, encrypted_data):
|
|||
|
|
"""
|
|||
|
|
解密数据
|
|||
|
|
:param encrypted_data: base64编码的加密数据
|
|||
|
|
:return: 解密后的原始数据
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
if isinstance(encrypted_data, str):
|
|||
|
|
encrypted_data = encrypted_data.encode('utf-8')
|
|||
|
|
|
|||
|
|
data = base64.b64decode(encrypted_data)
|
|||
|
|
decrypted_data = self.cipher.decrypt(data)
|
|||
|
|
return decrypted_data.decode('utf-8')
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
raise ValueError(f"解密失败: {str(e)}")
|
|||
|
|
|
|||
|
|
def generate_hash(data, salt=None):
|
|||
|
|
"""
|
|||
|
|
生成哈希值
|
|||
|
|
:param data: 要哈希的数据
|
|||
|
|
:param salt: 盐值,如果不提供则随机生成
|
|||
|
|
:return: (哈希值, 盐值) 元组
|
|||
|
|
"""
|
|||
|
|
if salt is None:
|
|||
|
|
salt = secrets.token_hex(16)
|
|||
|
|
|
|||
|
|
# 组合数据和盐值
|
|||
|
|
combined = f"{data}{salt}".encode('utf-8')
|
|||
|
|
|
|||
|
|
# 生成SHA256哈希
|
|||
|
|
hash_obj = hashlib.sha256(combined)
|
|||
|
|
hash_value = hash_obj.hexdigest()
|
|||
|
|
|
|||
|
|
return hash_value, salt
|
|||
|
|
|
|||
|
|
def generate_signature(data, secret_key):
|
|||
|
|
"""
|
|||
|
|
生成签名
|
|||
|
|
:param data: 要签名的数据
|
|||
|
|
:param secret_key: 密钥
|
|||
|
|
:return: 签名
|
|||
|
|
"""
|
|||
|
|
combined = f"{data}{secret_key}".encode('utf-8')
|
|||
|
|
hash_obj = hashlib.sha256(combined)
|
|||
|
|
return hash_obj.hexdigest()
|
|||
|
|
|
|||
|
|
def verify_hash(data, hash_value, salt):
|
|||
|
|
"""
|
|||
|
|
验证哈希值
|
|||
|
|
:param data: 原始数据
|
|||
|
|
:param hash_value: 要验证的哈希值
|
|||
|
|
:param salt: 盐值
|
|||
|
|
:return: 验证结果
|
|||
|
|
"""
|
|||
|
|
computed_hash, _ = generate_hash(data, salt)
|
|||
|
|
return computed_hash == hash_value
|
|||
|
|
|
|||
|
|
def generate_token(length=32):
|
|||
|
|
"""
|
|||
|
|
生成随机令牌
|
|||
|
|
:param length: 令牌长度
|
|||
|
|
:return: 随机令牌字符串
|
|||
|
|
"""
|
|||
|
|
return secrets.token_urlsafe(length)
|
|||
|
|
|
|||
|
|
def generate_uuid():
|
|||
|
|
"""
|
|||
|
|
生成UUID
|
|||
|
|
:return: UUID字符串
|
|||
|
|
"""
|
|||
|
|
import uuid
|
|||
|
|
return str(uuid.uuid4())
|
|||
|
|
|
|||
|
|
def encrypt_password(password, salt=None):
|
|||
|
|
"""
|
|||
|
|
加密密码
|
|||
|
|
:param password: 原始密码
|
|||
|
|
:param salt: 盐值
|
|||
|
|
:return: (加密后的密码, 盐值)
|
|||
|
|
"""
|
|||
|
|
return generate_hash(password, salt)
|
|||
|
|
|
|||
|
|
def verify_password(password, hashed_password, salt):
|
|||
|
|
"""
|
|||
|
|
验证密码
|
|||
|
|
:param password: 原始密码
|
|||
|
|
:param hashed_password: 加密后的密码
|
|||
|
|
:param salt: 盐值
|
|||
|
|
:return: 验证结果
|
|||
|
|
"""
|
|||
|
|
return verify_hash(password, hashed_password, salt)
|
|||
|
|
|
|||
|
|
# 为了兼容性,保留原来的函数名
|
|||
|
|
def AESCipher(key=None):
|
|||
|
|
"""兼容性包装器"""
|
|||
|
|
return SimpleCrypto(key)
|