da5eb4c18c
Strategy nodes gain fleet token APIs; control/ app for local ops; manage.sh offers strategy vs control one-click deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
"""简易密封:无需 cryptography 依赖。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
import hashlib
|
|
import hmac
|
|
import os
|
|
|
|
|
|
def _keystream(key: bytes, n: int) -> bytes:
|
|
out = bytearray()
|
|
counter = 0
|
|
while len(out) < n:
|
|
block = hashlib.sha256(key + counter.to_bytes(8, "big")).digest()
|
|
out.extend(block)
|
|
counter += 1
|
|
return bytes(out[:n])
|
|
|
|
|
|
def seal(plaintext: str, secret: str) -> str:
|
|
raw = plaintext.encode("utf-8")
|
|
key = hashlib.sha256(secret.encode("utf-8")).digest()
|
|
iv = os.urandom(16)
|
|
stream = _keystream(key + iv, len(raw))
|
|
cipher = bytes(a ^ b for a, b in zip(raw, stream))
|
|
mac = hmac.new(key, iv + cipher, hashlib.sha256).digest()
|
|
return base64.urlsafe_b64encode(iv + mac + cipher).decode("ascii")
|
|
|
|
|
|
def unseal(blob: str, secret: str) -> str:
|
|
data = base64.urlsafe_b64decode(blob.encode("ascii"))
|
|
if len(data) < 16 + 32:
|
|
raise ValueError("invalid sealed blob")
|
|
iv, mac, cipher = data[:16], data[16:48], data[48:]
|
|
key = hashlib.sha256(secret.encode("utf-8")).digest()
|
|
expect = hmac.new(key, iv + cipher, hashlib.sha256).digest()
|
|
if not hmac.compare_digest(expect, mac):
|
|
raise ValueError("sealed blob mac mismatch")
|
|
stream = _keystream(key + iv, len(cipher))
|
|
raw = bytes(a ^ b for a, b in zip(cipher, stream))
|
|
return raw.decode("utf-8")
|