Kryptografi — hash, signaturer, nycklar
Kunna förklara hashfunktioner, signaturer och varför API-nycklar aldrig ska ligga i kod.
Förkunskaper
- BBinära tal och bitarkrävs
Intuition
Tre byggstenar som räcker för det mesta:
Hash (SHA-256): en envägsfunktion från godtycklig data till 256 bitar. Samma indata ger alltid samma hash; minsta ändring ger en helt annan. Går inte att vända. Används för fingeravtryck (har filen ändrats?) och för lösenord — då med en långsam hash (bcrypt, argon2) plus salt, aldrig SHA-256 rakt av.
Signatur (HMAC eller asymmetrisk): bevisar att data kommer från någon med nyckeln och inte har ändrats. AI-grafens kompetensbevis signeras med HMAC — därför kan de verifieras utan att kunna förfalskas.
Kryptering: symmetrisk (samma nyckel, snabb, AES) eller asymmetrisk (publik/privat nyckel, långsam, används för att utbyta symmetriska nycklar — det TLS gör).
Formellt
Varför API-nycklar aldrig ska ligga i kod:
- Git glömmer inte. En nyckel som committats finns kvar i historiken även efter att den tagits bort ur filen. Enda åtgärden är att återkalla nyckeln.
- Repot sprids — forkar, backuper, CI-loggar, en laptop som försvinner.
- Automatiska skannare hittar nycklar i publika repon inom minuter. Det finns dokumenterade fall där en läckt molnnyckel gav tiotusentals kronor i kostnader på en natt.
Var de ska ligga i stället, i stigande ordning:
| Plats | Lämpligt för |
|---|---|
| Miljövariabel | lokal utveckling |
.env utanför git (i .gitignore) | lokal utveckling |
| Hemlighetshanterare (Vault, molnets KMS) | produktion |
| Kortlivade tokens med automatisk rotation | bäst — läckan har en utgångstid |
AI-grafen hämtar LLM-nyckeln ur Vault vid bootstrap och skriver den till en miljöfil som aldrig ligger i repot; bara de tolv första tecknen loggas någonsin.
Om en nyckel läckt: återkalla först, utred sedan. Ordningen är inte förhandlingsbar.
Kod
import hashlib, hmac, os, secrets
# Fingeravtryck — samma indata, samma hash
print(hashlib.sha256(b"hej").hexdigest()[:16]) # 4c3a...
# Lösenord: ALDRIG rå SHA-256. Långsam hash + salt.
salt = secrets.token_bytes(16)
hashad = hashlib.scrypt(b"lösenord", salt=salt, n=2**14, r=8, p=1)
# Signatur (samma princip som plattformens kompetensbevis)
NYCKEL = os.environ["SIGNING_KEY"].encode() # ur miljön, inte ur koden
def signera(data: bytes) -> str:
return hmac.new(NYCKEL, data, hashlib.sha256).hexdigest()
def verifiera(data: bytes, sig: str) -> bool:
return hmac.compare_digest(signera(data), sig) # konstanttidsjämförelse
# Nyckel ur miljön, med tydligt fel om den saknas
API_NYCKEL = os.environ.get("LLM_API_KEY")
if not API_NYCKEL:
raise RuntimeError("LLM_API_KEY saknas — sätt den i miljön, inte i koden")
print("nyckel:", API_NYCKEL[:12] + "…") # logga aldrig hela
hmac.compare_digest i stället för == är inte pedanteri: en vanlig jämförelse avbryter vid första felaktiga tecknet, vilket läcker information om signaturen via svarstiden.
Behärskning innebär
- Förklarar hashfunktioner, signaturer och nycklar
- Vet varför API-nycklar aldrig ska ligga i kod
- Hanterar hemligheter rätt
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- OWASP — Secrets Management Cheat Sheet — CC BY-SA 4.0
- Python-dokumentationen (PSF-licens) — PSF