Практикум — шаг 2: криптография
Блокчейн фиксирует что произошло; криптография доказывает кто это инициировал. Добавляем подписи переводов и шифрование секрета в покое.
Библиотека: cryptography (обёртка над OpenSSL).
Пара ключей Ed25519
Для учебного проекта выбран Ed25519 (короткие ключи, быстрые подписи). В Bitcoin — ECDSA/secp256k1; идея та же: приватный ключ подписывает, публичный проверяет.
Код ITЗагрузка примера кода…
Адрес кошелька в практикуме — hex публичного ключа (в mainnet адреса строятся иначе, через хеши и префиксы сети).
Подпись перевода
Транзакция — структура с полями sender, recipient, asset, amount, nonce. Подписываем канонический JSON без поля signature:
Код ITЗагрузка примера кода…
Зачем nonce: защита от повторного воспроизведения (replay). Каждый успешный перевод увеличивает счётчик отправителя — как sequence в Ethereum.
Проверка на узле:
def verify_signature(self) -> bool:
public_key = public_key_from_hex(self.sender)
message = canonical_json(self.payload_dict()).encode("utf-8")
signature = base64.b64decode(self.signature_b64.encode("ascii"))
return verify_ed25519(public_key, message, signature)
Глубже про PKI, TLS и хранение секретов — информационная безопасность.
Симметричное шифрование ключа (vault)
Приватный ключ нельзя хранить в открытом виде на диске. Учебный vault:
- PBKDF2-HMAC-SHA256 (200 000 итераций) из пароля пользователя.
- AES-GCM для шифрования PEM приватного ключа.
- В blob сохраняются
salt,nonce,ciphertext.
def encrypt_private_key_pem(private_key: Ed25519PrivateKey, password: str) -> str:
salt = os.urandom(16)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=200_000)
key = kdf.derive(password.encode("utf-8"))
aesgcm = AESGCM(key)
nonce = os.urandom(12)
pem = private_key.private_bytes(...)
ciphertext = aesgcm.encrypt(nonce, pem, None)
return base64.urlsafe_b64encode(salt + nonce + ciphertext).decode("ascii")
| Практика | В продакшене |
|---|---|
| Пароль в CLI | HSM, KMS (AWS CloudHSM, Vault) |
| Файл blob на диске | Аппаратный токен, MPC-кошельки |
| Один алгоритм | Ротация ключей, политики доступа |
Практическое задание
- Сгенерируйте
KeyPair, подпишите строкуb"test", измените один байт сообщения — убедитесь, чтоverifyвозвращаетFalse. - Зашифруйте PEM с паролем
demo, расшифруйте, сравните публичные ключи. - Добавьте в
tests/test_ledger.pyтест на подпись и расшифровку vault (пример — в шаге 4).
Что дальше
Шаг 3 — ledger, балансы и mempool: как подписанные переводы попадают в блок.