Как безопасно сохранить закрытый ключ PyNaCl (libsodium) на диске в Python (избегайте простых файлов)? [закрыто]Python

Программы на Python
Ответить
Anonymous
 Как безопасно сохранить закрытый ключ PyNaCl (libsodium) на диске в Python (избегайте простых файлов)? [закрыто]

Сообщение Anonymous »

Я создаю небольшой клиент Python для службы FastAPI, которая отправляет одноразовые зашифрованные сообщения. Ключи должны оставаться на клиенте (никогда не отправляться на сервер и не храниться им).
Env/Libraries
  • Python 3.11
  • [PyNaCl] для X25519/box (nacl.public)
  • Необязательно криптография для KDF + AEAD
    Цель
Сохранять долгоживущую пару ключей PyNaCl между запусками. Я хочу, чтобы закрытый ключ хранился на диске и расшифровывался только после того, как пользователь введет парольную фразу (или, альтернативно, используйте связку ключей ОС, если это считается лучшей практикой).
Что я пробовал
  • Запись необработанного 32-байтового закрытого ключа в файл → легко, но явно небезопасно в состоянии покоя.
  • Использование криптографии для получения ключа из файла парольную фразу (Scrypt) и зашифруйте закрытый ключ с помощью AES-GCM перед записью на диск. Это работает, но я не уверен насчет рекомендуемых параметров/шаблонов.
  • Использование пакета ключей для хранения закрытого ключа в хранилище учетных данных ОС (Windows DPAPI / macOS Keychain / Secret Service). Это позволяет избежать использования парольных фраз, но я не уверен в переносимости и резервном копировании/восстановлении.
    Минимальное воспроизведение (эскиз)
    Python 3.11
    pip install pynacl шифрование

    Код: Выделить всё

    from nacl.public import PrivateKey
    from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.backends import default_backend
    import os, json, base64
    
    # 1) Generate
    sk = PrivateKey.generate()
    pk = sk.public_key
    sk_bytes = bytes(sk)               # 32 bytes
    pk_bytes = bytes(pk)               # 32 bytes (saved in clear is fine)
    
    # 2) Derive wrap key from passphrase
    def derive_key(passphrase: str, salt: bytes) -> bytes:
    kdf = Scrypt(salt=salt, length=32, n=2**15, r=8, p=1,
    backend=default_backend())
    return kdf.derive(passphrase.encode("utf-8"))
    
    3) Зашифруйте секретный ключ с помощью AES-GCM и сохраните (salt, nonce, ct)
    def store_key(sk_bytes: bytes, passphrase: str, path="keystore.json"):
    salt = os.urandom(16)
    nonce = os.urandom(12)
    aad_key = Decode_key(passphrase, salt)
    ct = AESGCM(aeaad_key).encrypt(nonce, sk_bytes, Associated_data=None)
    data = {
    "salt": base64.b64encode(salt).decode(),
    "nonce": base64.b64encode(nonce).decode(),
    "ct": base64.b64encode(ct).decode(),
    "pub": base64.b64encode(pk_bytes).decode(),
    }
    с open(path, "w") как f:
    json.dump(data, f)
    4) Загрузить + расшифровать
    def load_key(passphrase: str, path="keystore.json") -> байты:
    data = json.load(open(path))
    salt = base64.b64decode(data["salt"])
    nonce = base64.b64decode(data["nonce"])
    ct = base64.b64decode(data["ct"])
    aad_key = Decrypt(nonce, ct, Associated_data=None)
    return sk_bytes
    Использование:
    store_key(sk_bytes, "my passphrase")
    recovered = load_key("my passphrase")
    assert восстановлен == sk_bytes
Вопросы
  • Является ли «ключ, полученный из Scrypt + упаковка AES-GCM, а затем сохранение JSON в файле» разумным шаблоном для сохранения ключа на стороне клиента с помощью PyNaCl? Какие-либо рекомендуемые параметры Scrypt для настольных компьютеров в 2025 году?
  • Рекомендуете ли вы вместо этого использовать связку ключей ОС через связку ключей (и если да, то как безопасно и портативно хранить 32 необработанных байта)?
  • Есть ли подводные камни с ключами X25519 в PyNaCl при такой сериализации/десериализации?
    Ограничения
    Я не могу хранить секреты на сервер. Можно запросить у пользователя парольную фразу при запуске; никаких инфраструктур пользовательского интерфейса не требуется.
    Ожидается:
    руководство или пример кода, демонстрирующий рекомендуемый подход (файл с парольной фразой или связка ключей ОС) и выбор параметров (стоимость шифрования, обработка nonce AES-GCM и т. д.).


Подробнее здесь: https://stackoverflow.com/questions/798 ... ython-avoi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»