feat(crypto): add master key loader and Fernet encrypt/decrypt helpers
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
36
scripts/service/crypto.py
Normal file
36
scripts/service/crypto.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Fernet 加密 / 解密的薄封装。
|
||||
|
||||
不暴露 Fernet 对象;调用方只看 encrypt/decrypt 字符串。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
|
||||
from service.master_key import load_master_key
|
||||
from service.secret_store import mask_secret
|
||||
|
||||
|
||||
class CredentialDecryptError(Exception):
|
||||
"""Decryption failed (bad key or corrupted ciphertext)."""
|
||||
|
||||
code = "ERR_CREDENTIAL_DECRYPT_FAILED"
|
||||
|
||||
|
||||
def encrypt_secret(plaintext: str) -> str:
|
||||
"""Encrypt using current master key; returns url-safe token string."""
|
||||
key = load_master_key()
|
||||
f = Fernet(key)
|
||||
tok = f.encrypt(plaintext.encode("utf-8"))
|
||||
return tok.decode("ascii")
|
||||
|
||||
|
||||
def decrypt_secret(ciphertext: str) -> str:
|
||||
"""Decrypt Fernet token string to plaintext."""
|
||||
key = load_master_key()
|
||||
f = Fernet(key)
|
||||
try:
|
||||
raw = f.decrypt(ciphertext.encode("ascii"))
|
||||
return raw.decode("utf-8")
|
||||
except InvalidToken as e:
|
||||
raise CredentialDecryptError("Fernet decrypt failed") from e
|
||||
Reference in New Issue
Block a user