El mòdul anterior va acabar amb una llista de defenses que ja has vist funcionar —TLS, les URL signades de 120 segons, l'HMAC del webhook de la passarel·la, DKIM, les passkeys, la signatura RS256 del JWT, el xifratge de les còpies, la comparació en temps constant del TOTP— i amb una constatació: totes descansen sobre el mateix fonament i fins ara l'hem tractat com una caixa negra. Aquesta lliçó obre la caixa. No en sortiràs sabent xifrar: en sortiràs sabent què se li demana a la criptografia, què se li pot demanar de debò, amb quin vocabulari precís se'n parla i per què —aquesta és la idea que travessa tot el mòdul— la part difícil gairebé mai no és l'algorisme. És important perquè la majoria de les fallades criptogràfiques reals de les pimes no consisteixen a trencar AES, sinó a fer servir la primitiva equivocada per al problema equivocat, confondre codificar amb xifrar, o generar una clau amb una font d'aleatorietat que no ho era.
Contingut
- Quin problema resol exactament la criptografia
- Vocabulari precís: xifrar, codificar, calcular un hash i ofuscar no són el mateix
- Història com a palanca conceptual: Cèsar, Vigenère i Enigma
- El principi de Kerckhoffs i per què la seguretat viu a la clau
- Models d'atacant i tipus d'atac criptogràfic
- Què significa «segur» avui: bits de seguretat i mides de clau
- Aleatorietat criptogràfica: el fonament invisible
- El mapa del mòdul 3
- La criptografia que Nimbus ja fa servir sense haver-la explicat
- Quin problema resol exactament la criptografia
La criptografia és el conjunt de tècniques matemàtiques que permeten protegir informació davant d'un adversari que té accés al canal, al suport o a tots dos. Aquesta última frase és la clau i convé llegir-la a poc a poc: la criptografia no pressuposa un canal segur ni un disc fora de perill. Pressuposa el contrari. Assumeix que l'atacant veu les dades i, tot i així, aconsegueix que no li serveixin de res.
És l'aplicació directa del principi d'assumeix la bretxa de 01-03. Una nota clínica d'una clínica de fisioteràpia clienta de Nimbus viatja per wifis de cafeteries, es desa en discos d'un proveïdor cloud i es copia a buckets de respatller. En cap d'aquests tres punts no controlem el medi físic. La criptografia converteix «que ningú no toqui el medi» —impossible— en «que tocar el medi no serveixi de res» —assolible.
Quina propietat aporta cada primitiva
A 01-01 es va definir la tríada CIA i els seus complements: autenticitat, no-repudi i traçabilitat. Cadascuna d'aquestes propietats té una primitiva criptogràfica concreta que la proporciona. Aquesta taula és el mapa mental del mòdul sencer:
| Propietat que es vol | Primitiva criptogràfica | Exemple concret | S'estudia a |
|---|---|---|---|
| Confidencialitat: que ningú més no ho llegeixi | Xifratge (simètric o asimètric) | AES-GCM sobre un adjunt de Nimbus | 03-02, 03-03 |
| Integritat: detectar que ha canviat | Funció hash (davant d'un error) i MAC (davant d'un atacant) | SHA-256 d'una còpia; HMAC d'un webhook | 03-04 |
| Autenticitat: saber qui ho va produir | MAC (entre dos que comparteixen clau) o signatura digital (davant de tothom) | HMAC de la passarel·la; signatura del JWT | 03-03, 03-04 |
| No-repudi: que l'emissor no ho pugui negar | Signatura digital exclusivament | Ed25519 sobre un rebut de reserva | 03-03 |
| Frescor: que no sigui un missatge vell reenviat | Nonce, marca de temps, comptador | El nonce d'AES-GCM; la finestra de 30 s del TOTP | 03-02, 03-05 |
| Acord de clau: compartir un secret sense haver-se vist | Intercanvi de claus | ECDHE en l'encaixada de TLS | 03-03, 03-05 |
Tres lectures importants d'aquesta taula:
- Xifrar no dona integritat per si sol. És l'error conceptual més estès. Un text xifrat amb un mode antic pot ser alterat per un atacant de manera controlada sense conèixer la clau. Per això avui es fa servir xifratge autenticat, que ajunta les dues propietats en una sola operació (03-02).
- Un MAC i una signatura no són intercanviables. Tots dos donen autenticitat i integritat, però el MAC fa servir una clau compartida: si Nimbus i la passarel·la comparteixen la clau, Nimbus podria haver fabricat aquell missatge, així que no serveix com a prova davant d'un tercer. La signatura, amb clau privada, sí (03-03).
- El frescor no el dona cap de les anteriors. Un missatge xifrat, íntegre i autèntic de fa tres mesos continua sent xifrat, íntegre i autèntic avui. Reenviar-lo és un atac de repetició, i es combat amb nonces i finestres temporals, no amb més xifratge.
I què no resol la criptografia
Igual d'important que l'anterior. La criptografia no:
- Protegeix davant de qui té la clau legítimament. Si un atacant roba les credencials de l'Iván, l'API desxifra per a ell amb tota correcció. Això és un problema d'identitat (02-05) i d'autorització, no de criptografia.
- Amaga metadades. TLS amaga el contingut de la petició, no que el teu portàtil parli amb
nimbusreservas.examplea les 03:14, ni la mida aproximada de la resposta. - Dona disponibilitat. Un ransomware fa servir criptografia perfectament correcta contra tu. Xifrar no evita que esborrin.
- Substitueix el control d'accés. Hi tornarem a 03-07: xifrar una base de dades l'API de la qual exposa un IDOR no arregla l'IDOR.
- S'arregla sola. Una clau mal desada converteix AES-256 en un adorn. Aquest és l'assumpte de 03-06.
- Vocabulari precís: xifrar, codificar, calcular un hash i ofuscar no són el mateix
El mòdul sencer depèn de fer servir bé cinc paraules. Comencem per les bàsiques:
| Terme | Definició |
|---|---|
| Text en clar (plaintext) | La dada original llegible. No ha de ser text necessàriament: un PDF, una imatge o una fila de base de dades també ho són |
| Text xifrat (ciphertext) | El resultat d'aplicar el xifratge. Ha de ser indistingible de dades aleatòries |
| Algorisme (cipher) | El procediment matemàtic. Públic, estudiat, estandarditzat |
| Clau | El secret que parametritza l'algorisme. L'única cosa que l'atacant no ha de conèixer |
| Xifrar / desxifrar | Les dues operacions inverses de l'algorisme amb la clau |
| Criptoanàlisi | L'estudi de com trencar un esquema sense la clau |
I ara la distinció que més vegades es fa malament en la pràctica professional:
| Operació | És reversible? | Necessita clau? | Per a què serveix | Exemple |
|---|---|---|---|---|
| Codificar | Sí, per qualsevol | No | Representar dades en un altre alfabet per transportar-les | Base64, URL-encoding, UTF-8, hexadecimal |
| Xifrar | Sí, només amb la clau | Sí | Confidencialitat | AES-GCM, ChaCha20-Poly1305 |
| Calcular un hash | No (és unidireccional) | No (l'HMAC sí) | Integritat, empremta, emmagatzematge de contrasenyes | SHA-256, Argon2id |
| Ofuscar | Sí, amb esforç | No | Dificultar la lectura casual. No és seguretat | Minificar JavaScript, invertir una cadena |
Codificar no protegeix absolutament res. Base64 apareix constantment en tokens, en capçaleres HTTP i en configuracions, i amb una regularitat depriment algú conclou que «està encriptat». Demostrem que no:
import base64
# Una dada sensible ficticia de Nimbus
dada = "pacient=Ana Ruiz; sessio=rehabilitacio genoll; clinica=CL-014"
# CODIFICAR: converteix a un alfabet segur per a URL i capcaleres
codificat = base64.b64encode(dada.encode("utf-8")).decode("ascii")
print("Codificat:", codificat)
# DESCODIFICAR: qualsevol, sense cap secret, ho reverteix
recuperat = base64.b64decode(codificat).decode("utf-8")
print("Recuperat:", recuperat)Sortida:
Codificat: cGFjaWVudD1BbmEgUnVpejsgc2Vzc2lvPXJlaGFiaWxpdGFjaW8gZ2Vub2xsOyBjbGluaWNhPUNMLTAxNA==
Recuperat: pacient=Ana Ruiz; sessio=rehabilitacio genoll; clinica=CL-014Analitzem el codi línia a línia, perquè el detall importa:
dada.encode("utf-8")converteix el text Python en bytes. Base64 opera sobre bytes, no sobre caràcters.base64.b64encode(...)produeix la representació en l'alfabetA-Z a-z 0-9 + /, amb=de farciment al final. No hi ha intervingut cap clau. El resultat depèn únicament de l'entrada.base64.b64decode(...)reverteix l'operació. No se li passa cap secret perquè no n'existeix cap.
La conclusió operativa: si veus un valor acabat en == en un registre, un tiquet o una URL, no està protegit; està transportat. I si conté dades personals, aquell registre és una fuita (això connecta directament amb la regla de «què registrar i què no» de 02-04).
Prova de butxaca per distingir-les. Pregunta't: puc desfer això sense cap secret? Si la resposta és sí, és codificació o ofuscació, i no aporta seguretat. Si necessito un secret, és xifratge. Si no es pot desfer de cap manera, és un hash.
- Història com a palanca conceptual: Cèsar, Vigenère i Enigma
La història de la criptografia no s'estudia aquí per erudició, sinó perquè cada fracàs històric va deixar una lliçó que continua vigent paraula per paraula.
| Esquema | Època | Idea | Per què va caure | Lliçó permanent |
|---|---|---|---|---|
| Xifratge Cèsar | Roma | Desplaçar cada lletra N posicions | Només hi ha 25 claus possibles | L'espai de claus ha de ser inabastable |
| Substitució monoalfabètica | Edat Mitjana | Cada lletra es canvia per una altra de fixa | L'anàlisi de freqüències el rebenta | El text xifrat no ha de conservar estructura de l'original |
| Vigenère | S. XVI | Substitució amb clau repetida | La repetició de la clau crea patrons detectables | No reutilitzis mai material de clau (regla que reapareixerà amb els nonces) |
| Enigma | II GM | Rotors mecànics, clau diària | Errors de procediment, missatges predictibles i màquines capturades | S'ataca la implementació i el procediment, no les matemàtiques |
Trencar un Cèsar en quatre línies
Aquest exemple existeix només perquè vegis amb els teus propis ulls què significa «espai de claus petit».
Advertiment explícit. El xifratge Cèsar no té cap valor de seguretat. No el facis servir mai per protegir res, ni tan sols com a «capa addicional». Apareix aquí exclusivament com a il·lustració conceptual, igual que un dibuix d'un pany de 1900 en un manual de serralleria.
def cesar(text: str, desplacament: int) -> str:
"""Desplaca les lletres de l alfabet angles N posicions. Nomes didactic."""
sortida = []
for c in text:
if c.isalpha():
base = ord("A") if c.isupper() else ord("a")
# (ord(c) - base) dona la posicio 0..25; sumem i tornem a 0..25 amb %26
sortida.append(chr((ord(c) - base + desplacament) % 26 + base))
else:
sortida.append(c) # espais, nombres i signes passen intactes
return "".join(sortida)
interceptat = "Wudvoodw gh od uhvhuyd d ohv yxlw"
# FORCA BRUTA: recorrem TOTES les claus possibles. Son 25.
for clau in range(1, 26):
print(f"clau={clau:2d} -> {cesar(interceptat, -clau)}")Fragment de la sortida:
clau= 1 -> Vtcunncv fg nc tgugtxc c ngu xwkv
clau= 2 -> Usbtmmbu ef mb sftfswb b mft wvju
clau= 3 -> Trasllat de la reserva a les vuit
clau= 4 -> Sqzrkkzs cd kz qdrdquz z kdr uthsQuè cal entendre d'això:
- No ha calgut cap matemàtica. El bucle prova les 25 claus en microsegons i un humà identifica la correcta amb un cop d'ull.
- L'operació
% 26és el que fa que l'alfabet sigui circular: després de laztorna laa. - Desxifrar és xifrar amb el desplaçament negatiu:
cesar(text, -clau). - Un ordinador modern provaria de l'ordre de mil milions de claus per segon en un esquema tan simple. Amb 25 claus no hi ha defensa possible. Amb 2^128, com veurem a l'apartat 6, la força bruta deixa d'existir com a opció.
La lliçó permanent de Cèsar, la de Vigenère i la d'Enigma es resumeixen en tres frases que valen per al 2026: l'espai de claus ha de ser astronòmic; el material de clau no es reutilitza mai; i l'atacant ataca el més feble, que gairebé sempre és el procediment humà, no l'àlgebra.
- El principi de Kerckhoffs i per què la seguretat viu a la clau
A 01-03 vas conèixer el principi de Kerckhoffs com un dels quinze principis de disseny segur. Aquí és on cobra tot el seu sentit:
Un sistema criptogràfic ha de ser segur fins i tot si tot el que hi és relatiu, tret de la clau, és de domini públic.
Dit d'una altra manera: l'algorisme és públic; el secret és la clau, i només la clau. El contrari —confiar que ningú no conegui l'algorisme— s'anomena seguretat per obscuritat i és una de les pitjors decisions possibles en criptografia, per quatre raons concretes:
| Raó | Explicació |
|---|---|
| El secret del disseny no se sosté | Es filtra per enginyeria inversa, per un empleat que se'n va, per un repositori, per un binari descarregable |
| No es pot rotar un algorisme | Si es filtra una clau, se'n genera una altra en un segon. Si es filtra el teu algorisme propietari, cal reescriure el sistema |
| Ningú no l'ha revisat | AES fa més de dues dècades que és atacat per milers de criptògrafs. El teu algorisme l'han mirat dues persones del teu equip, amb presses |
| Impedeix la interoperabilitat i l'auditoria | Ni el client ni l'auditor no poden verificar res |
D'aquí surt la regla pedagògica central d'aquest mòdul, que llegiràs a les set lliçons:
No implementis mai criptografia a mà. Ni l'algorisme, ni el mode, ni el farciment, ni la comparació d'etiquetes. Fes servir llibreries establertes, mantingudes i auditades —en Python,
cryptography, i els mòdulshashlib,hmacisecretsde la biblioteca estàndard—. La teva feina professional no és inventar primitives: és triar la correcta, configurar-la bé i gestionar-ne les claus. Les tres coses es fan malament sovint, i les tres són suficients per arruïnar un sistema.
Això no és una recomanació d'estil. La criptografia de qualitat industrial exigeix defensar-se de canals laterals, d'errors de farciment, de multiplicacions que triguen diferent segons els bits, de generadors de nombres aleatoris defectuosos. Una implementació «que dona el resultat correcte» pot estar filtrant la clau pel temps d'execució sense que cap test ho detecti.
- Models d'atacant i tipus d'atac criptogràfic
Per dir que una cosa és segura cal dir davant de quin atacant. La criptografia formalitza això en models d'atacant, que es distingeixen pel que l'adversari pot fer:
| Model | L'atacant pot... | Exemple real al món de Nimbus |
|---|---|---|
| Només text xifrat | Veure textos xifrats | Algú captura trànsit a la wifi de convidats |
| Text en clar conegut | Veure parells (clar, xifrat) que no va triar | Sap que tota resposta comença per {"reservas":[ |
| Text en clar triat | Fer que el sistema xifri el que ell vulgui | Crea una reserva amb un text a mida i observa el xifrat resultant |
| Text xifrat triat | Fer que el sistema desxifri el que ell vulgui i observar-ne la reacció | Envia tokens manipulats i distingeix «error de format» d'«error de signatura» |
| Atacant actiu (MITM) | A més, modificar, reordenar i reenviar missatges | Un punt d'accés fals en una cafeteria, com a 02-02 |
L'estàndard modern és exigir seguretat davant del model més fort. Un algorisme actual com AES-GCM es considera segur fins i tot davant d'un atacant que tria textos en clar a voluntat; si un esquema només aguanta el model feble, es descarta.
Famílies d'atac
| Família | En què consisteix | Defensa |
|---|---|---|
| Força bruta | Provar totes les claus | Espai de claus de 128 bits o més (apartat 6) |
| Criptoanàlisi | Explotar debilitats matemàtiques de l'algorisme | Fer servir només primitives estandarditzades i vigents |
| Diccionari / taules precalculades | Provar contrasenyes freqüents o hashos ja calculats | Sal única i funcions lentes (03-04) |
| Canal lateral | Mesurar temps, consum elèctric, memòria cau o soroll per deduir la clau | Operacions en temps constant; fer servir llibreries que ja ho fan |
| Atac a la implementació | Explotar una fallada del codi, no de l'algorisme: farciment mal validat, nonce repetit, comparació amb == |
Revisió, llibreries d'alt nivell, xifratge autenticat |
| Atac a l'entorn | Robar la clau del disc, del repositori, de la memòria o de la persona | Gestió de claus (03-06) |
Aturem-nos en la de temporització perquè és contraintuïtiva. Si el teu codi compara un codi de verificació caràcter a caràcter i retorna False així que troba una diferència, triga més quan encerta més caràcters. Un atacant que mesuri milers d'intents reconstrueix el secret caràcter a caràcter, i redueix un problema impossible a un de trivial. Per això existeix hmac.compare_digest, que veuràs en detall a 03-04, i per això comparar secrets amb == està prohibit en tot aquest curs.
La idea que has de treure d'aquest apartat. Gairebé cap incident criptogràfic real no es deu al fet que algú trenqués l'àlgebra. Es deu a claus mal desades, nonces repetits, versions obsoletes de protocol, validacions desactivades i comparacions ingènues. L'atacant ataca l'implementador, no l'algorisme.
- Què significa «segur» avui: bits de seguretat i mides de clau
Un esquema té n bits de seguretat quan el millor atac conegut requereix de l'ordre de 2^n operacions. No és el mateix que la mida de la clau: RSA amb clau de 2048 bits ofereix aproximadament 112 bits de seguretat, perquè factoritzar és més fàcil que provar totes les claus.
| Bits de seguretat | Equivalències típiques | Estat el 2026 |
|---|---|---|
| 56 | DES | Trencat. Es trenca en hores amb maquinari barat |
| ~63–80 | SHA-1 (resistència a col·lisió real) | Trencat. Col·lisions demostrades públicament |
| 112 | 3DES, RSA-2048, DH-2048 | Mínim llegat. En retirada |
| 128 | AES-128, RSA-3072, ECC P-256, SHA-256 | L'estàndard actual. Adequat per a tot ús general |
| 192 | AES-192, ECC P-384 | Alta seguretat, dades de llarga vida |
| 256 | AES-256, ECC P-521, SHA-512 | Màxim pràctic. Marge a molt llarg termini |
Per què 2^128 és inabastable
Els nombres grans no signifiquen res fins que s'aterren. Suposem una màquina imaginària capaç de provar mil milions de claus per segon (10^9), i suposem que n'ajuntem mil milions, d'aquestes màquines (10^18 claus per segon, molt per damunt de tota la capacitat de còmput del planeta):
Claus possibles amb 128 bits : 2^128 ~= 3,4 x 10^38
Velocitat suposada : 10^18 claus per segon
Segons necessaris : 3,4 x 10^20
Anys necessaris : ~ 1,1 x 10^13 (onze bilions d anys)Onze bilions d'anys davant dels ~13.800 milions d'anys d'edat de l'univers. I cada bit addicional duplica aquest nombre: 256 bits no és «el doble de segur» que 128, és 2^128 vegades més.
La conclusió pràctica és alliberadora: la mida de clau no és el problema. Si fas servir AES-128 o AES-256, la força bruta contra la clau està descartada per sempre amb tecnologia clàssica. Quan llegeixis que «han trencat un xifratge», gairebé sempre significa una d'aquestes cinc coses:
- La clau es va derivar d'una contrasenya feble (03-04).
- La clau estava desada on l'atacant va arribar (03-06).
- Es va fer servir un mode o algorisme obsolet (ECB, RC4, MD5).
- Es va repetir un nonce o es va reutilitzar material de clau (03-02).
- Es va trencar la implementació: canal lateral, validació desactivada, error de farciment.
I AES-256 davant d'AES-128? Tria 256 quan la dada hagi de continuar sent confidencial durant dècades o quan una norma sectorial ho exigeixi; el cost de rendiment és petit. Per a l'ús general de Nimbus, qualsevol dels dos està fora de l'abast de qualsevol adversari.
- Aleatorietat criptogràfica: el fonament invisible
Tota la criptografia descansa a poder generar valors que l'atacant no pugui predir: claus, nonces, sals, identificadors de sessió, tokens de recuperació de contrasenya. Si aquests valors són endevinables, l'algorisme és irrellevant: l'atacant no trenca res, simplement regenera el teu secret.
Python té dos generadors i triar malament és una fallada de seguretat real:
| Mòdul | Tipus | Predictible | Ús correcte |
|---|---|---|---|
random |
PRNG estadístic (Mersenne Twister) | Sí. Amb ~624 sortides se'n reconstrueix l'estat i es prediu tota la resta | Simulacions, jocs, mostreig, tests |
secrets |
CSPRNG, alimentat pel sistema operatiu | No, per disseny | Tot el que sigui un secret |
import random
import secrets
# --- INCORRECTE: no facis servir mai random per a material de seguretat ---
token_dolent = "".join(random.choice("0123456789abcdef") for _ in range(32))
print("INCORRECTE (predictible):", token_dolent)
# --- CORRECTE ---
token_bo = secrets.token_urlsafe(32) # ~256 bits d entropia, apte per a URL
clau_bytes = secrets.token_bytes(32) # 32 bytes = clau de 256 bits
codi_sms = secrets.randbelow(1_000_000) # enter uniforme a [0, 999999]
print("CORRECTE token :", token_bo)
print("CORRECTE clau :", clau_bytes.hex())
print("CORRECTE codi :", f"{codi_sms:06d}")Sortida (diferent a cada execució, per definició):
INCORRECTE (predictible): 8f3a1c0b74e2d95a6b0f4c8137ae52d9
CORRECTE token : 9tHqR2vXbN0sLpKcYfWm3Zj7aQe1UoIdT5gRnVxB4yA
CORRECTE clau : 4c1b9f0a7d6e5382bb44c0f19a7e2d33518c6b09f2a4d7e1c3059b8a6f4e2d10
CORRECTE codi : 048217Explicació de cada línia:
random.choicefa servir el Mersenne Twister, un generador excel·lent per a estadística i catastròfic per a seguretat: és determinista i el seu estat intern es pot reconstruir observant prou sortides. Si Nimbus generés amb ell els tokens de «he oblidat la contrasenya», un atacant que demanés uns quants tokens per al seu propi compte podria predir el de la Sara.secrets.token_urlsafe(32)demana 32 bytes al generador segur del sistema operatiu i els codifica en Base64 segur per a URL. Compte: els 32 són bytes d'entropia, no caràcters de sortida.secrets.token_bytes(32)retorna bytes crus: és la manera correcta de generar una clau simètrica de 256 bits des de zero.secrets.randbelow(1_000_000)dona un enter uniforme sense el biaix que introduiria un% 1000000sobre un nombre aleatori gran. El format:06dconserva els zeros a l'esquerra:048217és un codi vàlid.
Cas històric. El 2013 es va descobrir que una fallada en el generador de nombres aleatoris de determinades aplicacions Android feia que les claus de signatura de transaccions es repetissin. Amb dues signatures que compartissin aquell valor, la clau privada quedava exposada amb àlgebra elemental. L'algorisme era correcte i estava ben implementat. L'aleatorietat no ho era, i això va bastar.
Regla operativa per a Nimbus, sense excepcions: qualsevol valor que l'atacant no hagi d'endevinar es genera amb secrets (o amb l'equivalent de la plataforma: crypto.getRandomValues al navegador, crypto/rand a Go). Mai amb random, mai amb l'hora, mai amb un comptador, mai amb un UUID versió 1.
- El mapa del mòdul 3
Abans d'entrar en els algorismes, aquest és el recorregut i quina peça aporta cada lliçó:
flowchart TB
A["03-01 FONAMENTS\nVocabulari, Kerckhoffs,\nbits de seguretat, aleatorietat"]
A --> B["03-02 SIMETRICA\nUna clau compartida.\nAES-GCM, modes, nonces.\nProblema: distribuir la clau"]
A --> C["03-04 HASH I MAC\nSHA-256, HMAC,\nArgon2id i contrasenyes"]
B --> D["03-03 ASIMETRICA\nParell de claus. RSA, ECC,\nDiffie-Hellman, signatura digital"]
C --> D
D --> E["03-05 PROTOCOLS\nTLS, SSH, VPN.\nCombinar primitives be"]
E --> F["03-06 CLAUS I PKI\nCicle de vida, certificats,\nCA. El problema dificil"]
F --> G["03-07 APLICACIONS\nXifratge en repos, camps,\ncopies, signatura d artefactes"]
La lògica de la seqüència: el simètric resol la confidencialitat però deixa oberta la distribució de la clau; l'asimètric resol la distribució però és lent, cosa que obliga a combinar-los; els hashos i els MAC aporten la integritat que el xifratge no dona; els protocols són la manera correcta d'assemblar tot això; la PKI respon a «de qui és aquesta clau pública?»; i l'última lliçó ho aplica de punta a punta al sistema de Nimbus.
- La criptografia que Nimbus ja fa servir sense haver-la explicat
Tanca la lliçó un inventari honest: en dos mòduls hem recolzat defenses sobre criptografia sense explicar-la. Aquesta taula és el deute que el mòdul 3 ve a pagar.
| Element ja vist | On va aparèixer | Quina primitiva hi ha a sota | S'explica a |
|---|---|---|---|
| HTTPS/TLS a la SPA i l'API | Tot el curs | Intercanvi ECDHE + certificat + AES-GCM | 03-02, 03-03, 03-05 |
| JWT signat amb RS256 i validat amb JWKS | 02-05 | Signatura asimètrica RSA sobre un hash | 03-03, 03-07 |
| URL signades de 120 s del bucket d'adjunts (A-05) | 01-04, 02-04 | HMAC sobre mètode, ruta i caducitat | 03-04, 03-07 |
| HMAC del webhook de la passarel·la de pagament | 02-02, 02-04 | HMAC-SHA256 amb clau compartida | 03-04 |
| TOTP de sis dígits de l'MFA | 02-05 | HMAC + comptador temporal de 30 s | 03-04, 03-05 |
| Passkeys / FIDO2 | 02-05 | Parell de claus per lloc; signatura d'un repte | 03-03 |
| Hash de contrasenyes a la taula de credencials | 02-05 | Derivació lenta amb sal (Argon2id) | 03-04 |
| DKIM al correu sortint | 02-03 | Signatura asimètrica de les capçaleres | 03-03 |
| Còpies 3-2-1-1-0 xifrades i immutables | 02-04 | Xifratge simètric + gestió de claus | 03-02, 03-07 |
| Signatura de codi (lliçó de SolarWinds) | 02-06 | Signatura asimètrica sobre l'artefacte | 03-03, 03-07 |
Secret del .env que va permetre l'escalada |
02-06 | Cap: allà precisament va fallar la gestió | 03-06 |
L'última fila és la més eloqüent. En el cas de ransomware de Nimbus no va fallar cap primitiva criptogràfica: va fallar que una clau estava desada on no havia d'estar. És la tesi que governarà 03-06 i que convé interioritzar des d'avui: la matemàtica aguanta; la gestió és el que es trenca.
Errors Comuns i Consells
Errors conceptuals
- Anomenar «encriptat» una cosa codificada en Base64. És l'error número u. Base64 i hexadecimal són transport, no protecció. Aplica la prova de butxaca de l'apartat 2.
- Creure que xifrar aporta integritat. No l'aporta tret que facis servir xifratge autenticat. Un atacant pot alterar el text xifrat de manera controlada en modes antics.
- Confondre hash amb xifratge. «Xifrem les contrasenyes» és una frase incorrecta i perillosa: si es poguessin desxifrar, l'atacant que roba la clau les tindria totes. Les contrasenyes es deriven amb una funció lenta i unidireccional (03-04).
- Pensar que un algorisme secret és més segur. Kerckhoffs diu justament el contrari i l'experiència d'un segle ho confirma.
- Obsessionar-se amb la mida de clau. Discutir AES-128 davant d'AES-256 mentre la clau viu en un fitxer
.envdel repositori és optimitzar la part que no falla. - Suposar que la criptografia substitueix el control d'accés. Són capes diferents. L'IDOR de 01-01 passava sobre una connexió TLS impecable.
Errors d'implementació
- Fer servir
randomper a material de seguretat. Tokens, sals, nonces, claus: sempresecrets. - Comparar secrets amb
==. Obre un canal lateral de temporització. Es fa servirhmac.compare_digest. - Escriure la teva pròpia primitiva «perquè és un XOR senzill». No.
- Copiar el primer fragment que apareix en un cercador. Bona part del codi criptogràfic que circula en fòrums és del 2011 i fa servir ECB, MD5 o IV fixos.
Consells pràctics
- Abans de triar algorisme, escriu en una frase quina propietat necessites: confidencialitat, integritat, autenticitat, no-repudi o frescor? La taula de l'apartat 1 et dona la primitiva gairebé sola.
- Escriu també davant de qui protegeixes. Xifrar el disc d'un servidor no defensa d'una API compromesa, i saber-ho evita comprar tranquil·litat falsa.
- Mantén una regla d'equip: el codi criptogràfic el revisen sempre dues persones, encara que el canvi sembli trivial.
- Consulta fonts vigents per a paràmetres i mides (NIST SP 800-57, les guies del CCN-CERT i ENISA, el full de ruta d'OWASP). Els valors concrets caduquen; els principis no.
Exercicis
Exercici 1 — Classificar operacions
Per a cada situació real de Nimbus, indica: (a) quina operació s'està aplicant —codificar, xifrar, calcular un hash o ofuscar—; (b) quina propietat de seguretat aporta realment; (c) si és adequada per a la finalitat declarada i, si no ho és, què s'hauria de fer.
- El token de sessió que la SPA desa conté el correu de l'usuari en Base64, «perquè no es vegi a simple vista».
- El Rubén envia a un client un fitxer ZIP protegit amb contrasenya i li envia la contrasenya pel mateix correu.
- L'Iván desa a la base de dades el resultat de
sha256(contrasenya). - L'adjunt d'una clínica es puja al bucket A-05 xifrat amb AES-GCM i la clau és en un gestor de secrets.
- La Lucía publica, al costat de la còpia de seguretat nocturna, un fitxer
.sha256amb l'empremta de l'arxiu. - El JavaScript de la SPA està minificat i amb noms de variable d'una lletra, «perquè ningú no entengui la lògica de preus».
Exercici 2 — Auditar un generador de tokens
Aquest és el codi real que Nimbus fa servir per als enllaços de recuperació de contrasenya:
import random, time, base64
def token_recuperacio(email: str) -> str:
random.seed(int(time.time())) # (1)
n = random.randint(100000, 999999) # (2)
cru = f"{email}:{n}"
return base64.b64encode(cru.encode()).decode() # (3)Es demana: (a) identifica els tres problemes marcats i explica l'atac concret que habilita cadascun; (b) estima quants intents necessitaria un atacant que coneix el correu de la Sara i el minut aproximat en què va demanar la recuperació; (c) reescriu la funció correctament, explicant cada decisió; (d) indica quines altres dues mesures, alienes a la generació del token, hauria de tenir aquest flux.
Exercici 3 — Triar la primitiva
Per a cada requisit de Nimbus, digues quina propietat es necessita, quina primitiva la proporciona i en quina lliçó del mòdul s'estudia. No cal codi.
- Que la consultora externa (A-19) no pugui llegir el contingut de les còpies que custodia.
- Que Nimbus pugui demostrar davant d'un client, mesos després, que va ser aquell client qui va cancel·lar una reserva.
- Que l'API detecti si un webhook de la passarel·la de pagament va ser fabricat per un tercer.
- Que un atacant que gravi avui el trànsit xifrat de l'app mòbil no el pugui llegir si d'aquí a dos anys roba la clau privada del servidor.
- Que un adjunt descarregat del bucket no es pugui reutilitzar demà amb la mateixa URL.
- Que, si roben el bolcat de la taula de credencials, les contrasenyes no es puguin recuperar en un termini útil.
Solucions
Exercici 1
| # | Operació | Què aporta realment | És adequada? |
|---|---|---|---|
| 1 | Codificar | Res. Qualsevol ho reverteix | No. Si el token ha d'amagar dades, xifrem; però el correcte és que el token sigui un identificador opac aleatori (secrets) sense dades personals a dins |
| 2 | Xifrar (el ZIP), però amb clau pel mateix canal | Gairebé res: qui intercepti el correu té totes dues coses | No. La clau ha de viatjar per un canal diferent (telèfon, amb verificació com a 02-03) o fer servir un enllaç amb caducitat |
| 3 | Calcular un hash, però amb funció ràpida i sense sal | Molt poc: les rainbow tables i les GPU ho rebenten | No. Argon2id amb sal única per usuari (03-04) |
| 4 | Xifrar amb AEAD | Confidencialitat i integritat de l'adjunt | Sí. És el patró correcte (03-02, 03-07) |
| 5 | Calcular un hash | Integritat davant d'errors (corrupció, transferència incompleta) | Parcialment. No protegeix d'un atacant, que recalcularia el .sha256. Per a això cal signatura o HMAC (03-04) |
| 6 | Ofuscar | Res davant d'un analista amb deu minuts | No. La lògica que ha de romandre secreta viu al servidor, no al navegador |
Exercici 2
(a) Els tres problemes:
random.seed(int(time.time()))— se sembra el generador amb l'hora en segons. L'espai de llavors d'un dia sencer són 86.400 valors. Un atacant que sàpiga el dia reprodueix tots els tokens possibles.random.randint(100000, 999999)— dues fallades: fa servirrandom(predictible) i només hi ha 900.000 valors possibles, uns 20 bits. És força bruta trivial fins i tot sense conèixer la llavor.base64.b64encode(...)— el token no està protegit: conté el correu en clar per a qualsevol i, a més, revela el format intern, cosa que facilita fabricar candidats.
(b) Estimació. Si l'atacant coneix el correu i el minut aproximat, té ~60 llavors candidates. Cada llavor determina de manera determinista la primera sortida de randint, així que produeix ~60 tokens candidats. Amb reintents automatitzats, encerta en segons. Ni tan sols cal explorar els 900.000: la sembra per temps destrueix tota l'entropia.
(c) Versió correcta:
import secrets
import hashlib
from datetime import datetime, timedelta, timezone
def crear_token_recuperacio(usuari_id: int, repo) -> str:
# 1. 32 bytes d un generador CRIPTOGRAFIC -> ~256 bits, impossible d endevinar
token = secrets.token_urlsafe(32)
# 2. A la BD NO es desa el token, sino el seu hash: si es filtra la taula,
# els enllacos pendents no son utilitzables. Aqui SHA-256 basta perque
# el token ja te entropia alta (no es una contrasenya humana).
empremta = hashlib.sha256(token.encode()).hexdigest()
# 3. Caducitat curta i un sol us
repo.desar(
usuari_id=usuari_id,
empremta=empremta,
caduca=datetime.now(timezone.utc) + timedelta(minutes=15),
usat=False,
)
# 4. El token en clar nomes s envia per correu; no es registra en logs
return tokenDecisions: entropia suficient i de font segura; el token no conté dades (és opac, no revela el correu); s'emmagatzema amb hash; caduca en 15 minuts; és d'un sol ús.
(d) Altres dues mesures: (1) resposta idèntica existeixi o no el compte —«si el correu està registrat, rebràs un enllaç»— per no permetre enumeració d'usuaris; (2) límit de taxa per correu i per IP, més registre de l'esdeveniment per a alerta (02-04). Una tercera de desitjable: invalidar totes les sessions actives en completar el canvi.
Exercici 3
| # | Propietat | Primitiva | Lliçó |
|---|---|---|---|
| 1 | Confidencialitat | Xifratge simètric autenticat (AES-GCM) amb clau que la consultora no posseeix | 03-02, 03-07 |
| 2 | No-repudi (+ autenticitat i integritat) | Signatura digital amb clau del client; un MAC no valdria | 03-03 |
| 3 | Autenticitat i integritat entre dues parts amb clau compartida | HMAC-SHA256 | 03-04 |
| 4 | Confidencialitat persistent (forward secrecy) | Intercanvi efímer ECDHE | 03-03, 03-05 |
| 5 | Frescor / caducitat | HMAC sobre la ruta més una marca de caducitat signada | 03-04, 03-07 |
| 6 | Unidireccionalitat i cost de còmput | Argon2id amb sal única per usuari | 03-04 |
Conclusió
Has obert la caixa negra. Ara tens el mapa que faltava: cada propietat de seguretat té la seva primitiva —confidencialitat al xifratge, integritat al hash i al MAC, autenticitat i no-repudi a la signatura, frescor al nonce, i l'acord de clau a l'intercanvi— i també saps el que la criptografia no fa: no protegeix de qui té la clau, no amaga metadades, no dona disponibilitat i no substitueix el control d'accés. Distingeixes amb precisió codificar, xifrar, calcular un hash i ofuscar, i tens una prova de butxaca per no tornar a confondre-les: ho puc desfer sense cap secret? Has vist en Base64 que codificar no protegeix res i en un Cèsar trencat en 25 intents què significa un espai de claus insuficient.
De la història te'n portes tres lliçons que continuen intactes: l'espai de claus ha de ser astronòmic, el material de clau no es reutilitza mai —tornarà amb els nonces a la lliçó següent— i l'atacant ataca el procediment i la implementació, no l'àlgebra. Sobre aquesta base has recuperat Kerckhoffs: l'algorisme és públic i el secret és només la clau, d'on surt la regla que governa el mòdul sencer —no implementis mai criptografia a mà—. Saps situar un adversari en el seu model, distingir un atac de força bruta d'un de canal lateral, i per què 2^128 posa la força bruta fora de l'univers, cosa que trasllada el problema real a les cinc causes de sempre: contrasenyes febles, claus mal desades, algorismes obsolets, nonces repetits i implementacions defectuoses. I has interioritzat el fonament invisible: secrets, mai random, perquè una mala font d'aleatorietat trenca qualsevol algorisme per perfecte que sigui.
Finalment has posat números al deute: onze elements de Nimbus que fa dos mòduls que funcionen gràcies a criptografia sense explicar, des de l'HMAC del webhook fins a les URL signades de 120 segons, i una fila final que resumeix la tesi del mòdul: en el ransomware de 02-06 no va fallar cap primitiva, va fallar on vivia una clau.
A Criptografia Simètrica (03-02) comencem per la primitiva més antiga i més usada: una única clau compartida que xifra i desxifra. Veuràs per què AES és l'estàndard, què és un mode d'operació i per què ECB està prohibit, quin paper hi juga el nonce i per què repetir-lo és catastròfic, i com es xifra correctament un adjunt de Nimbus amb AES-GCM lligant-lo al seu tenant_id. I acabaràs amb el problema que el simètric no pot resoldre sol —com fer arribar la clau a l'altre extrem—, que és exactament el que motiva la lliçó següent.
Curs de Fonaments de Seguretat Informàtica
Mòdul 1: Introducció a la Seguretat Informàtica
- Conceptes Bàsics de Seguretat Informàtica
- Tipus d'Amenaces i Vulnerabilitats
- Principis de la Seguretat Informàtica
- Actius, Superfície d'Atac i Actors d'Amenaça
Mòdul 2: Ciberseguretat
- Definició i Abast de la Ciberseguretat
- Tipus d'Atacs Cibernètics
- Enginyeria Social i Pesca de Credencials
- Mesures de Protecció en Ciberseguretat
- Identitat, Autenticació i Control d'Accés
- Casos d'Estudi d'Incidents de Ciberseguretat
Mòdul 3: Criptografia
- Introducció a la Criptografia
- Criptografia Simètrica
- Criptografia Asimètrica
- Funcions Hash, HMAC i Emmagatzematge de Contrasenyes
- Protocols Criptogràfics
- Gestió de Claus, Certificats i PKI
- Aplicacions de la Criptografia
Mòdul 4: Gestió de Riscos i Mesures de Protecció
- Avaluació de Riscos
- Polítiques de Seguretat
- Controls de Seguretat
- Risc de Tercers i Cadena de Subministrament
- Pla de Resposta a Incidents
- Recuperació davant Desastres i Continuïtat de Negoci
Mòdul 5: Eines i Tècniques de Seguretat
- Eines d'Anàlisi de Vulnerabilitats
- Tècniques de Monitoratge i Detecció
- Proves de Penetració
- Seguretat en Xarxes
- Seguretat en Aplicacions
- Enfortiment de Sistemes i Seguretat de l'Endpoint
- Seguretat al Núvol i en Contenidors
Mòdul 6: Bones Pràctiques i Normatives
- Bones Pràctiques en Seguretat Informàtica
- Normatives i Estàndards de Seguretat
- Protecció de Dades Personals i RGPD a la Pràctica
- Compliment i Auditoria
- Formació i Sensibilització
- Ètica, Aspectes Legals i Divulgació Responsable
