[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,21 +2,205 @@
|
||||
id: wiki-2026-0508-practical-cryptography
|
||||
title: Practical Cryptography
|
||||
category: 10_Wiki/Topics
|
||||
status: merged
|
||||
redirect_to: 보안_및_시스템_신뢰성_표준
|
||||
canonical_id: wiki-2026-0507-039
|
||||
aliases: []
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [Applied Cryptography, Crypto Engineering]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [cryptography, security, encryption]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: Python/Go
|
||||
framework: libsodium/cryptography
|
||||
---
|
||||
|
||||
# Redirect
|
||||
# Practical Cryptography
|
||||
|
||||
이 문서는 Canonical 문서인 [[보안_및_시스템_신뢰성_표준]]으로 통합되었습니다.
|
||||
모든 최신 지식과 세부 내용은 위 링크를 참조하십시오.
|
||||
## 매 한 줄
|
||||
> **"매 don't roll your own crypto"**. 매 application engineer 의 task 는 매 well-vetted primitives (AES-GCM, ChaCha20-Poly1305, Ed25519, X25519) 의 correct composition — 매 algorithm 의 invention 아님. 2026 의 modern stack 은 libsodium, AWS KMS, age, Noise Protocol Framework 위 의 build.
|
||||
|
||||
## 매 핵심
|
||||
|
||||
### 매 Primitives (2026 baseline)
|
||||
- **Symmetric AEAD**: ChaCha20-Poly1305 (mobile/no-AES-NI), AES-256-GCM (server with AES-NI), AES-256-GCM-SIV (nonce-misuse resistant).
|
||||
- **Asymmetric**: X25519 (ECDH key agreement), Ed25519 (signing), Kyber-1024 (post-quantum KEM, NIST FIPS 203).
|
||||
- **Hashing**: BLAKE3 (fast), SHA-256 (interop), Argon2id (password hashing, 2026 default).
|
||||
- **Key derivation**: HKDF-SHA256 (key expansion), Argon2id (password → key).
|
||||
|
||||
### 매 Threat models
|
||||
- **Confidentiality**: encrypt-then-MAC, AEAD prevents IND-CCA2 attacks.
|
||||
- **Integrity**: HMAC, Poly1305, signatures.
|
||||
- **Authenticity**: signatures (Ed25519), authenticated key exchange (Noise).
|
||||
- **Forward secrecy**: ephemeral keys (X25519 per session).
|
||||
- **Post-quantum**: hybrid Kyber + X25519 (2026 TLS 1.3 default).
|
||||
|
||||
### 매 응용
|
||||
1. TLS 1.3 (transport security).
|
||||
2. Signal Protocol (E2EE messaging — Double Ratchet).
|
||||
3. age/rage (file encryption — replaces GPG).
|
||||
4. JWT/PASETO (stateless tokens — PASETO preferred).
|
||||
5. Password storage (Argon2id with per-user salt).
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### AEAD encryption (ChaCha20-Poly1305 with libsodium)
|
||||
```python
|
||||
from nacl.secret import SecretBox
|
||||
from nacl.utils import random
|
||||
|
||||
key = random(SecretBox.KEY_SIZE) # 32 bytes
|
||||
box = SecretBox(key)
|
||||
|
||||
# Encrypt — nonce auto-generated, prepended to ciphertext
|
||||
ciphertext = box.encrypt(b"sensitive data")
|
||||
|
||||
# Decrypt — fails with CryptoError on tampering
|
||||
plaintext = box.decrypt(ciphertext)
|
||||
```
|
||||
|
||||
### Authenticated key exchange (X25519 + HKDF)
|
||||
```python
|
||||
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
|
||||
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
|
||||
# Each party generates ephemeral keypair
|
||||
alice_priv = X25519PrivateKey.generate()
|
||||
bob_priv = X25519PrivateKey.generate()
|
||||
|
||||
# Compute shared secret
|
||||
shared = alice_priv.exchange(bob_priv.public_key())
|
||||
|
||||
# Derive symmetric key — never use raw DH output as key
|
||||
session_key = HKDF(
|
||||
algorithm=hashes.SHA256(),
|
||||
length=32,
|
||||
salt=None,
|
||||
info=b"session-v1",
|
||||
).derive(shared)
|
||||
```
|
||||
|
||||
### Password hashing (Argon2id)
|
||||
```python
|
||||
from argon2 import PasswordHasher
|
||||
|
||||
ph = PasswordHasher(
|
||||
time_cost=3, # iterations
|
||||
memory_cost=65536, # 64 MiB
|
||||
parallelism=4,
|
||||
)
|
||||
|
||||
hash = ph.hash("user-password") # store this
|
||||
|
||||
# Verify (constant-time)
|
||||
try:
|
||||
ph.verify(hash, "user-password")
|
||||
if ph.check_needs_rehash(hash):
|
||||
new_hash = ph.hash("user-password") # parameter upgrade
|
||||
except VerifyMismatchError:
|
||||
raise AuthError()
|
||||
```
|
||||
|
||||
### Digital signature (Ed25519)
|
||||
```python
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
||||
|
||||
priv = Ed25519PrivateKey.generate()
|
||||
pub = priv.public_key()
|
||||
|
||||
signature = priv.sign(b"message")
|
||||
pub.verify(signature, b"message") # raises InvalidSignature on failure
|
||||
```
|
||||
|
||||
### Envelope encryption (KMS pattern)
|
||||
```python
|
||||
import boto3
|
||||
from cryptography.fernet import Fernet
|
||||
|
||||
kms = boto3.client("kms")
|
||||
|
||||
def encrypt_blob(plaintext: bytes, kms_key_id: str) -> dict:
|
||||
# Generate per-message data key
|
||||
resp = kms.generate_data_key(KeyId=kms_key_id, KeySpec="AES_256")
|
||||
data_key = resp["Plaintext"]
|
||||
encrypted_dk = resp["CiphertextBlob"]
|
||||
|
||||
# Encrypt data with data key, discard plaintext data key
|
||||
f = Fernet(base64.urlsafe_b64encode(data_key))
|
||||
ct = f.encrypt(plaintext)
|
||||
|
||||
return {"ciphertext": ct, "encrypted_key": encrypted_dk}
|
||||
```
|
||||
|
||||
### Constant-time comparison
|
||||
```python
|
||||
import hmac
|
||||
|
||||
# WRONG — leaks length info via timing
|
||||
if user_token == stored_token:
|
||||
pass
|
||||
|
||||
# RIGHT — constant time
|
||||
if hmac.compare_digest(user_token, stored_token):
|
||||
pass
|
||||
```
|
||||
|
||||
### Post-quantum hybrid KEM (2026)
|
||||
```python
|
||||
# liboqs-python — hybrid X25519 + Kyber768
|
||||
from oqs import KeyEncapsulation
|
||||
import nacl.public
|
||||
|
||||
# Classical X25519
|
||||
x_priv = nacl.public.PrivateKey.generate()
|
||||
|
||||
# Post-quantum Kyber
|
||||
with KeyEncapsulation("Kyber768") as kem:
|
||||
pq_pub = kem.generate_keypair()
|
||||
|
||||
# Combine both shared secrets via HKDF for hybrid security
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| File encryption | age (modern), libsodium SecretBox |
|
||||
| Password hash | Argon2id (never bcrypt for new systems) |
|
||||
| Token format | PASETO v4 (Ed25519) over JWT |
|
||||
| Mobile/IoT AEAD | ChaCha20-Poly1305 |
|
||||
| TLS 1.3 backend | rustls or BoringSSL, hybrid PQ enabled |
|
||||
| Signing | Ed25519 (never RSA for new systems) |
|
||||
|
||||
**기본값**: libsodium + Argon2id + Ed25519 + ChaCha20-Poly1305.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Cryptography]] · [[Security]]
|
||||
- 변형: [[Symmetric-Encryption]] · [[Post-Quantum-Cryptography]]
|
||||
- 응용: [[Secret_Management]] · [[Zero-Trust Architecture]]
|
||||
- Adjacent: [[OWASP Top 10]] · [[Practical-Cryptography]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: explain primitive choice, audit crypto code for misuse, suggest migration paths.
|
||||
**언제 X**: never ask LLM to design new protocol — always defer to peer-reviewed designs (Noise, Signal).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Roll-your-own**: custom XOR-based "encryption" — 매 broken in seconds.
|
||||
- **ECB mode**: leaks pattern (penguin image meme). Always GCM/CTR/CBC-with-MAC.
|
||||
- **Static IV/nonce**: catastrophic for GCM (key recovery). Always random or counter.
|
||||
- **MD5/SHA-1**: collision-broken. Never for security purposes.
|
||||
- **bcrypt for new systems**: Argon2id 2026 default.
|
||||
- **String comparison for tokens**: use `hmac.compare_digest`.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (NIST FIPS 203/204/205, RFC 9180 HPKE, libsodium docs).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — full primitives + 2026 PQ baseline |
|
||||
|
||||
Reference in New Issue
Block a user