加入了 GVSDSDK 模块,进行了 QModel 兼容层的尝试,生产环境可用
This commit is contained in:
93
gvsdsdk/auth/crypto.py
Normal file
93
gvsdsdk/auth/crypto.py
Normal 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()
|
||||
Reference in New Issue
Block a user