加入了 GVSDSDK 模块,进行了 QModel 兼容层的尝试,生产环境可用

This commit is contained in:
2026-06-16 00:13:10 +08:00
parent 9d9cfa53a4
commit 63e0f4edfc
68 changed files with 10256 additions and 1143 deletions

93
gvsdsdk/auth/crypto.py Normal file
View File

@@ -0,0 +1,93 @@
import os
import bcrypt
import base64
import hashlib
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes as _crypto_hashes
def HashPassword(password, rounds=12):
if isinstance(password, str):
password = password.encode('utf-8')
return bcrypt.hashpw(password, bcrypt.gensalt(rounds=rounds))
def VerifyPassword(password, hashed):
if isinstance(password, str):
password = password.encode('utf-8')
if isinstance(hashed, str):
hashed = hashed.encode('utf-8')
return bcrypt.checkpw(password, hashed)
def _derive_key(master_secret):
"""使用 HKDF-SHA256 从任意长度的主密钥派生 256-bit AES 密钥"""
if isinstance(master_secret, str):
master_secret = master_secret.encode('utf-8')
hkdf = HKDF(
algorithm=_crypto_hashes.SHA256(),
length=32,
salt=b'gvsds-crypto-salt',
info=b'aes-gcm-256',
)
return hkdf.derive(master_secret)
def SymmetricEncrypt(plaintext, master_secret):
"""使用 AES-256-GCM 加密
输出格式: base64(nonce_12 + ciphertext + tag_16)
"""
if isinstance(plaintext, str):
plaintext = plaintext.encode('utf-8')
key = _derive_key(master_secret)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
ciphertext_with_tag = aesgcm.encrypt(nonce, plaintext, None)
return base64.b64encode(nonce + ciphertext_with_tag).decode('ascii')
def SymmetricDecrypt(ciphertext_b64, master_secret):
"""使用 AES-256-GCM 解密
输入格式: base64(nonce_12 + ciphertext + tag_16)
"""
raw = base64.b64decode(ciphertext_b64)
nonce = raw[:12]
ciphertext_with_tag = raw[12:]
key = _derive_key(master_secret)
aesgcm = AESGCM(key)
plaintext = aesgcm.decrypt(nonce, ciphertext_with_tag, None)
return plaintext.decode('utf-8')
def FileSHA1(filepath):
sha1 = hashlib.sha1()
with open(filepath, 'rb') as f:
while True:
chunk = f.read(8192)
if not chunk:
break
sha1.update(chunk)
return sha1.hexdigest()
def FileSHA256(filepath):
sha256 = hashlib.sha256()
with open(filepath, 'rb') as f:
while True:
chunk = f.read(8192)
if not chunk:
break
sha256.update(chunk)
return sha256.hexdigest()
def BytesSHA1(data):
return hashlib.sha1(data).hexdigest()
def BytesSHA256(data):
return hashlib.sha256(data).hexdigest()