"매 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.
Signal Protocol (E2EE messaging — Double Ratchet).
age/rage (file encryption — replaces GPG).
JWT/PASETO (stateless tokens — PASETO preferred).
Password storage (Argon2id with per-user salt).
💻 패턴
AEAD encryption (ChaCha20-Poly1305 with libsodium)
fromnacl.secretimportSecretBoxfromnacl.utilsimportrandomkey=random(SecretBox.KEY_SIZE)# 32 bytesbox=SecretBox(key)# Encrypt — nonce auto-generated, prepended to ciphertextciphertext=box.encrypt(b"sensitive data")# Decrypt — fails with CryptoError on tamperingplaintext=box.decrypt(ciphertext)
Authenticated key exchange (X25519 + HKDF)
fromcryptography.hazmat.primitives.asymmetric.x25519importX25519PrivateKeyfromcryptography.hazmat.primitives.kdf.hkdfimportHKDFfromcryptography.hazmat.primitivesimporthashes# Each party generates ephemeral keypairalice_priv=X25519PrivateKey.generate()bob_priv=X25519PrivateKey.generate()# Compute shared secretshared=alice_priv.exchange(bob_priv.public_key())# Derive symmetric key — never use raw DH output as keysession_key=HKDF(algorithm=hashes.SHA256(),length=32,salt=None,info=b"session-v1",).derive(shared)
Password hashing (Argon2id)
fromargon2importPasswordHasherph=PasswordHasher(time_cost=3,# iterationsmemory_cost=65536,# 64 MiBparallelism=4,)hash=ph.hash("user-password")# store this# Verify (constant-time)try:ph.verify(hash,"user-password")ifph.check_needs_rehash(hash):new_hash=ph.hash("user-password")# parameter upgradeexceptVerifyMismatchError:raiseAuthError()
Digital signature (Ed25519)
fromcryptography.hazmat.primitives.asymmetric.ed25519importEd25519PrivateKeypriv=Ed25519PrivateKey.generate()pub=priv.public_key()signature=priv.sign(b"message")pub.verify(signature,b"message")# raises InvalidSignature on failure
Envelope encryption (KMS pattern)
importboto3fromcryptography.fernetimportFernetkms=boto3.client("kms")defencrypt_blob(plaintext:bytes,kms_key_id:str)->dict:# Generate per-message data keyresp=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 keyf=Fernet(base64.urlsafe_b64encode(data_key))ct=f.encrypt(plaintext)return{"ciphertext":ct,"encrypted_key":encrypted_dk}
Constant-time comparison
importhmac# WRONG — leaks length info via timingifuser_token==stored_token:pass# RIGHT — constant timeifhmac.compare_digest(user_token,stored_token):pass
Post-quantum hybrid KEM (2026)
# liboqs-python — hybrid X25519 + Kyber768fromoqsimportKeyEncapsulationimportnacl.public# Classical X25519x_priv=nacl.public.PrivateKey.generate()# Post-quantum KyberwithKeyEncapsulation("Kyber768")askem:pq_pub=kem.generate_keypair()# Combine both shared secrets via HKDF for hybrid security
언제: 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.