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

  1. Quin problema resol exactament la criptografia
  2. Vocabulari precís: xifrar, codificar, calcular un hash i ofuscar no són el mateix
  3. Història com a palanca conceptual: Cèsar, Vigenère i Enigma
  4. El principi de Kerckhoffs i per què la seguretat viu a la clau
  5. Models d'atacant i tipus d'atac criptogràfic
  6. Què significa «segur» avui: bits de seguretat i mides de clau
  7. Aleatorietat criptogràfica: el fonament invisible
  8. El mapa del mòdul 3
  9. La criptografia que Nimbus ja fa servir sense haver-la explicat

  1. 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.example a 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.

  1. 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 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-014

Analitzem 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'alfabet A-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.


  1. 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 uths

Què 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 la z torna la a.
  • 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.


  1. 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òduls hashlib, hmac i secrets de 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.


  1. 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.


  1. 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:

  1. La clau es va derivar d'una contrasenya feble (03-04).
  2. La clau estava desada on l'atacant va arribar (03-06).
  3. Es va fer servir un mode o algorisme obsolet (ECB, RC4, MD5).
  4. Es va repetir un nonce o es va reutilitzar material de clau (03-02).
  5. 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.


  1. 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  : 048217

Explicació de cada línia:

  • random.choice fa 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 % 1000000 sobre un nombre aleatori gran. El format :06d conserva 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.


  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.


  1. 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

  1. 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.
  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.
  3. 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).
  4. Pensar que un algorisme secret és més segur. Kerckhoffs diu justament el contrari i l'experiència d'un segle ho confirma.
  5. Obsessionar-se amb la mida de clau. Discutir AES-128 davant d'AES-256 mentre la clau viu en un fitxer .env del repositori és optimitzar la part que no falla.
  6. 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ó

  1. Fer servir random per a material de seguretat. Tokens, sals, nonces, claus: sempre secrets.
  2. Comparar secrets amb ==. Obre un canal lateral de temporització. Es fa servir hmac.compare_digest.
  3. Escriure la teva pròpia primitiva «perquè és un XOR senzill». No.
  4. 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.

  1. El token de sessió que la SPA desa conté el correu de l'usuari en Base64, «perquè no es vegi a simple vista».
  2. El Rubén envia a un client un fitxer ZIP protegit amb contrasenya i li envia la contrasenya pel mateix correu.
  3. L'Iván desa a la base de dades el resultat de sha256(contrasenya).
  4. 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.
  5. La Lucía publica, al costat de la còpia de seguretat nocturna, un fitxer .sha256 amb l'empremta de l'arxiu.
  6. 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.

  1. Que la consultora externa (A-19) no pugui llegir el contingut de les còpies que custodia.
  2. Que Nimbus pugui demostrar davant d'un client, mesos després, que va ser aquell client qui va cancel·lar una reserva.
  3. Que l'API detecti si un webhook de la passarel·la de pagament va ser fabricat per un tercer.
  4. 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.
  5. Que un adjunt descarregat del bucket no es pugui reutilitzar demà amb la mateixa URL.
  6. 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:

  1. 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.
  2. random.randint(100000, 999999) — dues fallades: fa servir random (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.
  3. 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 token

Decisions: 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

Mòdul 2: Ciberseguretat

Mòdul 3: Criptografia

Mòdul 4: Gestió de Riscos i Mesures de Protecció

Mòdul 5: Eines i Tècniques de Seguretat

Mòdul 6: Bones Pràctiques i Normatives

Mòdul 7: Projecte Final

© Copyright 2026. Tots els drets reservats