fix(settings): reconcile secret status and model drafts
This commit is contained in:
@@ -26,7 +26,7 @@ def get_or_create_secret_key() -> bytes:
|
||||
if SECRET_KEY_FILE.exists():
|
||||
encoded = SECRET_KEY_FILE.read_text(encoding="utf-8").strip()
|
||||
if encoded:
|
||||
return base64.urlsafe_b64decode(encoded.encode("ascii"))
|
||||
return read_secret_key()
|
||||
|
||||
secret_key = secrets.token_bytes(KEY_BYTES)
|
||||
encoded = base64.urlsafe_b64encode(secret_key).decode("ascii")
|
||||
@@ -34,6 +34,23 @@ def get_or_create_secret_key() -> bytes:
|
||||
return secret_key
|
||||
|
||||
|
||||
def read_secret_key() -> bytes:
|
||||
"""只读取现有主密钥,解密路径不得因缺失密钥而生成新文件。"""
|
||||
|
||||
if not SECRET_KEY_FILE.exists():
|
||||
raise ValueError("Secret key file is missing")
|
||||
|
||||
try:
|
||||
encoded = SECRET_KEY_FILE.read_text(encoding="utf-8").strip()
|
||||
secret_key = base64.urlsafe_b64decode(encoded.encode("ascii"))
|
||||
except (OSError, UnicodeError, ValueError) as exc:
|
||||
raise ValueError("Secret key file is invalid") from exc
|
||||
|
||||
if len(secret_key) != KEY_BYTES:
|
||||
raise ValueError("Secret key length is invalid")
|
||||
return secret_key
|
||||
|
||||
|
||||
def _keystream(secret_key: bytes, nonce: bytes, length: int) -> bytes:
|
||||
chunks: list[bytes] = []
|
||||
counter = 0
|
||||
@@ -57,7 +74,14 @@ def encrypt_secret(value: str) -> str:
|
||||
secret_key = get_or_create_secret_key()
|
||||
nonce = secrets.token_bytes(NONCE_BYTES)
|
||||
plaintext = value.encode("utf-8")
|
||||
ciphertext = bytes(a ^ b for a, b in zip(plaintext, _keystream(secret_key, nonce, len(plaintext)), strict=False))
|
||||
ciphertext = bytes(
|
||||
a ^ b
|
||||
for a, b in zip(
|
||||
plaintext,
|
||||
_keystream(secret_key, nonce, len(plaintext)),
|
||||
strict=False,
|
||||
)
|
||||
)
|
||||
mac = hmac.new(secret_key, b"mac:" + nonce + ciphertext, hashlib.sha256).digest()
|
||||
|
||||
encoded_nonce = base64.urlsafe_b64encode(nonce).decode("ascii")
|
||||
@@ -78,7 +102,7 @@ def decrypt_secret(value: str) -> str:
|
||||
if version != SECRET_BOX_VERSION:
|
||||
raise ValueError("Unsupported secret payload version")
|
||||
|
||||
secret_key = get_or_create_secret_key()
|
||||
secret_key = read_secret_key()
|
||||
nonce = base64.urlsafe_b64decode(encoded_nonce.encode("ascii"))
|
||||
ciphertext = base64.urlsafe_b64decode(encoded_ciphertext.encode("ascii"))
|
||||
expected_mac = base64.urlsafe_b64decode(encoded_mac.encode("ascii"))
|
||||
@@ -87,5 +111,12 @@ def decrypt_secret(value: str) -> str:
|
||||
if not hmac.compare_digest(actual_mac, expected_mac):
|
||||
raise ValueError("Secret payload integrity check failed")
|
||||
|
||||
plaintext = bytes(a ^ b for a, b in zip(ciphertext, _keystream(secret_key, nonce, len(ciphertext)), strict=False))
|
||||
plaintext = bytes(
|
||||
a ^ b
|
||||
for a, b in zip(
|
||||
ciphertext,
|
||||
_keystream(secret_key, nonce, len(ciphertext)),
|
||||
strict=False,
|
||||
)
|
||||
)
|
||||
return plaintext.decode("utf-8")
|
||||
|
||||
Reference in New Issue
Block a user