La lliçó anterior va acabar amb un problema sense sortida: l'app mòbil d'una fisioterapeuta i l'API de Nimbus necessiten una clau simètrica comuna, però l'únic canal que tenen entre elles és exactament el que volen protegir. Durant quatre mil anys aquest problema no va tenir solució; als anys setanta es va resoldre amb una idea que sona impossible el primer cop que se sent: fer servir dues claus diferents, una que es publica i una altra que no es comparteix mai. Aquesta lliçó desenvolupa aquesta idea —el parell de claus, RSA, la criptografia de corba el·líptica, l'intercanvi Diffie-Hellman i la forward secrecy, el xifratge híbrid que explica com funciona TLS de debò, i la signatura digital, l'única primitiva que dona no-repudi—. És important perquè pràcticament tot el que fa segura la web moderna, des d'HTTPS fins a les passkeys i la signatura del JWT de Nimbus, és criptografia asimètrica.

Contingut

  1. La idea del parell de claus
  2. Què es fa amb la pública i què amb la privada
  3. RSA: el problema difícil de la factorització
  4. Criptografia de corba el·líptica: la mateixa seguretat amb claus molt més curtes
  5. Intercanvi de claus Diffie-Hellman
  6. Efímer, ECDHE i confidencialitat persistent
  7. Xifratge híbrid: com es fa servir de debò
  8. Signatura digital: què garanteix i en què es diferencia d'un MAC
  9. Signar un rebut de reserva de Nimbus amb Ed25519
  10. Inspeccionar un parell RSA amb openssl
  11. La pregunta que queda oberta i l'amenaça quàntica

  1. La idea del parell de claus

En un esquema asimètric es generen dues claus matemàticament relacionades:

  • La clau pública: es pot publicar en un web, imprimir en una samarreta o enviar per correu sense xifrar. La seva difusió no compromet res.
  • La clau privada: no surt mai del sistema que la va generar. Idealment ni tan sols és exportable, com passa a les passkeys de FIDO2 de 02-05.

La relació entre totes dues és de porta trampa: és fàcil calcular la pública a partir de la privada, i computacionalment inviable fer el camí invers. Tota la criptografia asimètrica es recolza en problemes matemàtics amb aquesta asimetria —multiplicar dos primers grans és trivial, factoritzar el producte no ho és—.

flowchart TB
    G["GENERACIO\nUn sol proces produeix\nel parell complet"]
    G --> PUB["CLAU PUBLICA\nEs reparteix lliurement.\nXifrar / Verificar signatures"]
    G --> PRIV["CLAU PRIVADA\nMai no surt del sistema.\nDesxifrar / Signar"]
    PRIV -.->|"facil"| PUB
    PUB -.->|"inviable"| PRIV

Això resol la distribució de cop: per rebre missatges xifrats n'hi ha prou de publicar la clau pública. I el nombre de claus deixa de créixer quadràticament: n participants necessiten n parells, no n·(n−1)/2 claus compartides. Amb 10.000 usuaris, 10.000 parells en lloc de cinquanta milions de claus.


  1. Què es fa amb la pública i què amb la privada

Aquesta taula és la que més vegades es recorda malament, i equivocar-se aquí inverteix per complet les garanties:

Operació Es fa servir la clau... Qui ho pot fer Què s'aconsegueix
Xifrar Pública del destinatari Qualsevol Només el destinatari ho podrà llegir → confidencialitat
Desxifrar Privada del destinatari Només el destinatari
Signar Privada de l'emissor Només l'emissor Autenticitat, integritat i no-repudi
Verificar Pública de l'emissor Qualsevol

La regla mnemotècnica: la clau privada és la que "tanca" la teva identitat i "obre" els teus missatges. Signes amb allò que només tens tu; desxifres amb allò que només tens tu.

L'error habitual és invertir-ho, i les seves conseqüències són diferents en cada direcció:

  • «Xifrem amb la privada perquè només ho llegeixin els nostres». Fals i perillós: el que es xifra amb la privada ho desxifra qualsevol amb la pública, perquè la pública és pública. Això no és xifrar, és —conceptualment— signar.
  • «Signem amb la pública». Impossible: si qualsevol pot signar, la signatura no acredita res.

Una conseqüència important per al disseny de Nimbus: en un sistema amb milers de clients, xifrar amb clau pública no és el que es fa habitualment; l'habitual és acordar una clau simètrica amb criptografia asimètrica i xifrar les dades amb ella (apartat 7). El xifratge asimètric directe es reserva per a dades molt petites, com una clau.


  1. RSA: el problema difícil de la factorització

RSA (Rivest, Shamir i Adleman, 1977) va ser el primer esquema asimètric pràctic i continua sent omnipresent, especialment en certificats i signatures de tokens.

La intuïció del problema difícil. Multiplicar dos nombres primers grans és instantani:

p = 61   q = 53   ->   n = p * q = 3233     (trivial)

El camí invers —donat n, trobar p i q— és fàcil amb nombres petits i esdevé inviable quan n té 2048 o 3072 bits (més de 600 dígits decimals). La clau pública conté n; la privada depèn de conèixer p i q. La seguretat d'RSA és exactament la dificultat de factoritzar.

Mida de clau RSA Bits de seguretat aprox. Estat el 2026
1024 ~80 Prohibit. A l'abast d'adversaris amb recursos
2048 ~112 Mínim acceptable. En retirada progressiva
3072 ~128 Recomanat per a claus noves de llarga vida
4096 ~152 Alta seguretat; notablement més lent

Tres coses que cal saber d'RSA per fer-lo servir bé:

  1. És lent, sobretot l'operació amb la clau privada (signar o desxifrar). Recorda la taula de rendiment de 03-02: unes mil operacions per segon davant de gigabytes per segon d'AES.
  2. No pot xifrar dades grans. Amb RSA-2048 el límit físic és la mida del mòdul, i amb el farciment obligatori queden uns 190 bytes útils. No és una limitació pràctica que es pugui esquivar amb més claus: és estructural.
  3. El farciment importa tant com l'algorisme. L'esquema antic PKCS#1 v1.5 té atacs coneguts. Avui es fa servir OAEP per xifrar i PSS per signar. Les llibreries serioses t'obliguen a triar-lo explícitament; no copiïs mai codi que faci servir PKCS1v15 per a xifratge nou.

  1. Criptografia de corba el·líptica: la mateixa seguretat amb claus molt més curtes

La criptografia de corba el·líptica (ECC) es recolza en un problema difícil diferent: el logaritme discret sobre els punts d'una corba el·líptica. El seu gran avantatge pràctic és l'eficiència.

Bits de seguretat RSA / DH ECC Diferència de mida
80 1024 160 ~6×
112 2048 224 ~9×
128 3072 256 (P-256, Curve25519) ~12×
192 7680 384 (P-384) ~20×
256 15360 512 (P-521, Curve448) ~30×

Llegeix bé la fila destacada: una clau ECC de 256 bits ofereix la mateixa seguretat que una RSA de 3072 bits. Això significa claus i signatures molt més petites, encaixades més ràpides i menys consum, cosa que importa especialment a l'app mòbil de Nimbus i a qualsevol dispositiu amb bateria.

Corbes que veuràs a la pràctica:

Corba Ús principal Notes
P-256 (secp256r1) TLS, certificats, JWT amb ES256 Estàndard NIST, suport universal
P-384 Entorns d'alta seguretat Estàndard NIST
Curve25519 / X25519 Intercanvi de claus Disseny modern, difícil d'implementar malament
Ed25519 Signatura digital Ràpida, signatures de 64 bytes, sense paràmetres per triar
secp256k1 Cadenes de blocs No la facis servir fora d'aquest context

Ed25519 i X25519 són la parella recomanada per defecte per a codi nou. No perquè siguin «més matemàtiques», sinó perquè el seu disseny elimina la majoria de les decisions on un desenvolupador es podria equivocar: no hi ha farciment per triar, no hi ha corbes per validar a mà, i l'algorisme de signatura és determinista, cosa que evita la fallada històrica de les signatures ECDSA amb aleatorietat defectuosa (el mateix tipus de fallada que vam veure a 03-01 amb el generador d'Android).

Un advertiment de nomenclatura, perquè genera confusió constant: X25519 serveix per intercanviar claus, Ed25519 serveix per signar. Són corbes emparentades però no intercanviables, i les llibreries no et deixaran barrejar-les.


  1. Intercanvi de claus Diffie-Hellman

Aquest és el mecanisme que resol el problema amb què va tancar 03-02. Diffie-Hellman permet que dues parts que no s'han vist mai acordin un secret compartit parlant per un canal que l'atacant escolta sencer, sense que l'atacant pugui deduir el secret.

L'analogia dels colors

  1. L'Ana i l'API acorden públicament un color base, diguem-ne groc. L'atacant el veu.
  2. L'Ana tria en secret un color propi, vermell, i el barreja amb el groc: obté taronja, i l'envia. L'atacant veu el taronja.
  3. L'API tria en secret blau, el barreja amb groc i obté verd, que envia. L'atacant veu el verd.
  4. L'Ana barreja el verd rebut amb el seu vermell secret. L'API barreja el taronja rebut amb el seu blau secret. Tots dos obtenen el mateix marró.
  5. L'atacant té groc, taronja i verd, i no pot obtenir el marró, perquè separar una barreja de pintures en els seus components és molt més difícil que barrejar-les.

Aquesta dificultat de «separar la barreja» és, en la matemàtica real, el problema del logaritme discret.

sequenceDiagram
    participant A as App movil (Ana)
    participant R as Xarxa (atacant escolta)
    participant S as API de Nimbus
    A->>A: genera privada a<br/>calcula publica A
    S->>S: genera privada b<br/>calcula publica B
    A->>R: envia A (publica)
    R->>S: A
    S->>R: envia B (publica)
    R->>A: B
    A->>A: secret = combinar(B, a)
    S->>S: secret = combinar(A, b)
    Note over A,S: Tots dos tenen el MATEIX secret compartit
    Note over R: L atacant va veure A i B<br/>i no pot deduir el secret

Dues precisions fonamentals:

  • El secret compartit no es fa servir directament com a clau. Es passa per una funció de derivació (HKDF, de 03-02) per obtenir claus de xifratge amb el format i la separació de dominis correctes.
  • Diffie-Hellman tot sol no autentica. Un atacant actiu pot fer un intercanvi amb cada extrem i situar-se al mig: és el clàssic MITM de 02-02. La solució és autenticar l'intercanvi amb una signatura digital avalada per un certificat —i aquí és on el mòdul enllaça amb TLS (03-05) i amb la PKI (03-06)—.

  1. Efímer, ECDHE i confidencialitat persistent

A TLS veuràs les sigles ECDHE: Elliptic Curve Diffie-Hellman Ephemeral. La paraula clau és l'última.

  • Estàtic: les parts fan servir sempre el mateix parell de claus per a l'intercanvi.
  • Efímer: es genera un parell nou per a cada sessió i es destrueix en acabar.

D'aquí surt la propietat més valuosa de la criptografia moderna:

Confidencialitat persistent (forward secrecy, també anomenada perfect forward secrecy): comprometre la clau privada de llarga durada del servidor no permet desxifrar les sessions passades.

Val la pena aterrar-ho a Nimbus amb un escenari concret:

  1. Un atacant grava durant mesos tot el trànsit xifrat entre les apps mòbils i l'API. No pot llegir res. Ho guarda igualment.
  2. Dos anys després, aconsegueix la clau privada del servidor de Nimbus —per una intrusió, una còpia mal esborrada o una ordre judicial en una altra jurisdicció—.
Sense forward secrecy Amb forward secrecy (ECDHE)
La clau de sessió es xifrava amb la clau pública del servidor i viatjava dins de l'encaixada La clau de sessió no va viatjar mai: es va acordar amb un parell efímer que es va destruir en penjar
Amb la clau privada, l'atacant desxifra tot el que ha gravat, retroactivament Amb la clau privada, l'atacant no pot desxifrar res del que ha gravat
Un sol compromís arruïna anys de trànsit Un compromís permet suplantar el servidor d'aquí endavant, però no llegir el passat

Aquesta és la raó per la qual TLS 1.3 va eliminar de l'estàndard tots els modes sense forward secrecy i per la qual l'intercanvi de clau RSA està prohibit en configuracions modernes (03-05). I és també la resposta directa a l'escenari de «collir ara, desxifrar després» de l'apartat 11.


  1. Xifratge híbrid: com es fa servir de debò

Ja tenim les dues peces i les seves limitacions creuades:

  • L'asimètric resol la distribució però és lent i no pot amb dades grans.
  • El simètric és rapidíssim però no pot distribuir la seva pròpia clau.

La solució és combinar-los, i s'anomena xifratge híbrid. És el patró que hi ha darrere de TLS, de PGP, del xifratge de sobre del núvol i de gairebé tota la resta:

flowchart TB
    A["1. Es genera una CLAU SIMETRICA\naleatoria, unica per a aquest missatge\no aquesta sessio (clau de sessio)"]
    A --> B["2. Les DADES es xifren amb aquesta clau\nfent servir AES-GCM: rapid,\nsense limit de mida"]
    A --> C["3. La CLAU SIMETRICA es protegeix\namb criptografia asimetrica:\nECDHE (acord) o RSA-OAEP (xifratge)"]
    B --> D["4. S envia o s emmagatzema:\nclau protegida + dades xifrades"]
    C --> D
    D --> E["5. El destinatari recupera la clau\nsimetrica amb la seva privada i\ndesxifra les dades"]

Per què això és el correcte i no un pedaç:

  • Es xifren 190 bytes amb l'asimètric en lloc de 3 MB. El cost de la part lenta és constant i menyspreable.
  • La mida del missatge deixa de tenir límit.
  • Si es fa servir ECDHE al pas 3 en lloc de xifrar la clau, s'obté a més forward secrecy.

Aquest mateix patró, aplicat a l'emmagatzematge en lloc de a la comunicació, s'anomena xifratge de sobre (envelope encryption): una clau de dades xifra l'objecte i una clau mestra del KMS xifra la clau de dades. És com xifra Nimbus els adjunts del bucket A-05, i es desenvolupa a 03-06 i 03-07.


  1. Signatura digital: què garanteix i en què es diferencia d'un MAC

Signar no és xifrar. Una signatura digital no amaga res: el missatge viatja llegible i la signatura s'hi adjunta. El que aporta és prova d'origen.

El flux real —i és important, perquè explica per què signar un fitxer de 4 GB és ràpid—:

flowchart LR
    M["MISSATGE\nqualsevol mida"] --> H["HASH\nSHA-256 -> 32 bytes"]
    H --> F["OPERACIO AMB LA\nCLAU PRIVADA\nsobre aquests 32 bytes"]
    F --> S["SIGNATURA\n64 bytes (Ed25519)"]
    M --> V["VERIFICAR:\nrefer el hash i comprovar\namb la clau PUBLICA"]
    S --> V

No es signa el missatge: es signa el seu hash. Per això el cost de signar no depèn de la mida del fitxer, i per això una funció hash trencada (MD5, SHA-1) trenca també la signatura: si l'atacant troba dos documents amb el mateix hash, una signatura vàlida per a un ho és per a l'altre. Els hashos s'estudien a 03-04.

Signatura davant de MAC

MAC (HMAC) Signatura digital
Tipus de clau Compartida entre les dues parts Parell: la privada signa, la pública verifica
Integritat?
Autenticitat? Sí, davant de l'altre posseïdor de la clau Sí, davant de tothom
No-repudi? No
Cost Molt baix (és un hash) Alt (operació asimètrica)
Qui pot verificar? Només qui té la clau Qualsevol amb la pública
Cas a Nimbus Webhook de la passarel·la de pagament Signatura del JWT, DKIM, signatura d'artefactes

La diferència decisiva és el no-repudi. Si Nimbus i la passarel·la comparteixen una clau HMAC, un webhook amb MAC vàlid demostra que el va generar algun dels dos, i com que Nimbus també té la clau, no serveix com a prova davant d'un tercer: Nimbus podria haver-lo fabricat. Amb una signatura, en canvi, només la clau privada de la passarel·la pot produir-la, i Nimbus no la té; per això la signatura sí que és prova.

La regla pràctica: fes servir MAC quan les dues parts es coneixen, comparteixen un secret i només necessiten detectar manipulació; fes servir signatura quan el verificador pot ser qualsevol o quan necessites prova oposable.


  1. Signar un rebut de reserva de Nimbus amb Ed25519

Nimbus vol emetre rebuts de reserva verificables: la clínica ha de poder comprovar, mesos després, que aquell rebut el va emetre Nimbus i no ha estat alterat.

from cryptography.hazmat.primitives.asymmetric.ed25519 import (
    Ed25519PrivateKey, Ed25519PublicKey,
)
from cryptography.hazmat.primitives import serialization
from cryptography.exceptions import InvalidSignature
import json

# ---------------------------------------------------------------
# 1. GENERACIO DEL PARELL. Es fa UNA VEGADA. La privada va al gestor
#    de secrets o al KMS (03-06); la publica es publica.
# ---------------------------------------------------------------
privada = Ed25519PrivateKey.generate()
publica = privada.public_key()

pub_pem = publica.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
print(pub_pem.decode())

# ---------------------------------------------------------------
# 2. EL MISSATGE. Serialitzacio CANONICA: mateix objecte -> mateixos bytes.
#    sort_keys i separators eviten que un espai invalidi la signatura.
# ---------------------------------------------------------------
rebut = {
    "tenant": "CL-014",
    "reserva_id": 88421,
    "pacient_ref": "PX-7731",           # referencia, no el nom
    "data": "2026-08-14T10:30:00+02:00",
    "import_cent": 4500,
    "emes_per": "nimbus-reservas",
    "emes_el": "2026-08-02T09:12:44+02:00",
}
missatge = json.dumps(rebut, sort_keys=True, separators=(",", ":")).encode("utf-8")

# ---------------------------------------------------------------
# 3. SIGNAR amb la clau privada -> 64 bytes
# ---------------------------------------------------------------
signatura = privada.sign(missatge)
print("Longitud de la signatura:", len(signatura), "bytes")

# ---------------------------------------------------------------
# 4. VERIFICAR amb la clau publica
# ---------------------------------------------------------------
def verificar(pem_publica: bytes, missatge: bytes, signatura: bytes) -> bool:
    clau: Ed25519PublicKey = serialization.load_pem_public_key(pem_publica)
    try:
        clau.verify(signatura, missatge)  # no retorna res si es valida
        return True
    except InvalidSignature:
        return False

print("Rebut intacte:", verificar(pub_pem, missatge, signatura))

# ---------------------------------------------------------------
# 5. ALTERAR EL MISSATGE: es canvia l import de 45,00 a 5,00 euros
# ---------------------------------------------------------------
rebut_alterat = dict(rebut, import_cent=500)
missatge_alterat = json.dumps(
    rebut_alterat, sort_keys=True, separators=(",", ":")
).encode("utf-8")

print("Rebut alterat:", verificar(pub_pem, missatge_alterat, signatura))

Sortida:

-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAJ1n2rQ0kXsF8mB4vC7pLd9TgYhWq3ZeR6aKcNfUx0sM=
-----END PUBLIC KEY-----

Longitud de la signatura: 64 bytes
Rebut intacte: True
Rebut alterat: False

El que cal comprendre d'aquest codi:

  • La clau pública en PEM ocupa tres línies. Compara-la amb una clau pública RSA-3072, que n'ocupa unes quinze. Aquest és l'avantatge de mida d'ECC de l'apartat 4.
  • La serialització canònica és imprescindible. sort_keys=True fixa l'ordre de les claus i separators=(",", ":") elimina els espais. Sense això, dues serialitzacions del mateix objecte produirien bytes diferents i la signatura fallaria per un motiu que no és un atac. És la fallada d'integració número u amb signatures sobre JSON.
  • privada.sign(missatge) fa internament el hash. Ed25519 fa servir SHA-512 per dins; tu no toques aquesta part, i aquest és justament l'objectiu.
  • verify no retorna True/False: llança InvalidSignature. És un disseny deliberat, perquè sigui impossible ignorar el resultat per descuit amb un if mal escrit. No capturis mai aquesta excepció sense actuar.
  • Canviar l'import invalida la signatura. Un sol camp modificat i la verificació falla: això és integritat i autenticitat juntes.
  • El rebut porta pacient_ref, no el nom. Un document signat és difícil de retirar del món i sol acabar arxivat durant anys. Minimitza les dades personals que conté (02-04; el marc legal, a 06-03).

Nota de validació professional. Si un rebut signat s'ha de fer servir com a prova amb efectes legals o fiscals a Espanya, la signatura criptogràfica és condició necessària però no suficient: la normativa de signatura electrònica i factura electrònica imposa requisits addicionals sobre el certificat, el prestador i la conservació. Valida el disseny amb assessoria jurídica abans de donar-li valor probatori; els aspectes normatius es tracten al mòdul 6.


  1. Inspeccionar un parell RSA amb openssl

Encara que per a codi nou la recomanació sigui ECC, RSA continua sent a la majoria de certificats i a molts emissors de JWT, així que cal saber manejar-lo.

# 1. Generar una clau privada RSA de 3072 bits (~128 bits de seguretat)
openssl genpkey -algorithm RSA \
  -pkeyopt rsa_keygen_bits:3072 \
  -out nimbus_privada.pem
chmod 600 nimbus_privada.pem          # NOMES el propietari la pot llegir

# 2. Extreure la clau publica del parell
openssl pkey -in nimbus_privada.pem -pubout -out nimbus_publica.pem

# 3. Inspeccionar la clau publica
openssl pkey -pubin -in nimbus_publica.pem -text -noout

# 4. Comparar: generar tambe un parell Ed25519 i mirar-ne la mida
openssl genpkey -algorithm ed25519 -out nimbus_ed25519.pem
ls -l nimbus_privada.pem nimbus_ed25519.pem

Sortida del pas 3 (retallada):

Public-Key: (3072 bit)
Modulus:
    00:c4:1f:9a:e7:2b:8d:05:6f:31:a0:4c:d8:77:e2:
    b9:15:3c:80:6a:f4:29:1d:cb:07:5e:a3:44:90:11:
    ...  (384 bytes en total)
Exponent: 65537 (0x10001)

Sortida del pas 4:

-rw------- 1 lucia lucia 2484 ago  2 09:41 nimbus_privada.pem
-rw-r--r-- 1 lucia lucia  119 ago  2 09:41 nimbus_ed25519.pem

Lectura d'aquests resultats:

  • El mòdul és l'n = p·q de l'apartat 3, aquí de 3072 bits (384 bytes). És públic. Els factors p i q són només a la clau privada.
  • L'exponent públic 65537 és el valor estàndard: primer, petit i amb pocs bits a u, cosa que fa ràpida l'operació pública. Veure'l diferent és un senyal d'alarma.
  • 2484 bytes davant de 119. La mateixa taula de l'apartat 4, feta visible al sistema de fitxers.
  • chmod 600 no és decoratiu. Una clau privada llegible per tots els usuaris del sistema és una troballa d'auditoria habitual, i tornarà a aparèixer a 03-06 i a 05-06.
  • No facis servir mai -des3 ni contrasenyes febles per protegir la clau privada. Si necessita xifratge en repòs, fes servir xifratge modern; i si és una clau de servei, el correcte és que visqui en un gestor de secrets o en un HSM, no en un fitxer (03-06).

  1. La pregunta que queda oberta i l'amenaça quàntica

De qui és realment aquesta clau pública?

Tota la lliçó s'ha recolzat en un supòsit que encara no hem justificat. Repassa l'intercanvi de l'apartat 5: l'app mòbil rep una clau pública per la xarxa i la fa servir per acordar el secret. Com sap que aquella clau és de Nimbus i no d'un atacant situat al mig?

Si no hi ha manera de comprovar-ho, el MITM funciona perfectament: l'atacant fa un intercanvi amb l'app fent-se passar per Nimbus i un altre amb Nimbus fent-se passar per l'app, i desxifra i torna a xifrar tot el que hi passa. Tots dos extrems tindrien xifratge impecable amb la persona equivocada.

La criptografia asimètrica trasllada el problema, no l'elimina. Ja no cal distribuir secrets, però cal autenticar claus públiques. Aquest és el problema que resolen els certificats digitals i la infraestructura de clau pública, i és l'assumpte de 03-06. La manera concreta com TLS ho aplica a cada connexió es veu a 03-05.

Criptografia postquàntica i el «collir ara, desxifrar després»

Un ordinador quàntic prou gran podria executar l'algorisme de Shor, que trenca alhora RSA, Diffie-Hellman i la criptografia de corba el·líptica. No els debilita: els resol. Avui no existeix una màquina així, i les estimacions públiques parlen d'anys o dècades, però això no fa que l'assumpte sigui irrellevant avui:

Primitiva Impacte quàntic Resposta
RSA, DH, ECC Trencats per l'algorisme de Shor Migrar a algorismes postquàntics (ML-KEM, ML-DSA, estandarditzats pel NIST el 2024)
AES-256 Debilitat a ~128 bits efectius per Grover Suficient. N'hi ha prou de fer servir 256 bits
SHA-256/512 Debilitats, no trencats Suficient

Per què importa ja: «collir ara, desxifrar després». Un adversari amb recursos pot gravar avui trànsit xifrat que no pot llegir, guardar-lo, i desxifrar-lo quan disposi de la màquina. Si la dada continua sent sensible d'aquí a quinze anys, el problema és d'avui.

Per a Nimbus, a la pràctica: les dades de cites perden valor amb relativa rapidesa, així que no és una prioritat d'aquest any. El que sí que és assenyat és (1) fer servir forward secrecy sempre, que ja limita el dany d'escenaris d'aquest tipus; (2) mantenir el programari de TLS actualitzat, perquè els navegadors i les llibreries estan activant modes híbrids postquàntics (X25519 combinat amb ML-KEM) de manera transparent; i (3) portar un inventari d'on es fa servir cada algorisme, que és el que farà barata la migració quan toqui. Aquesta agilitat criptogràfica —poder canviar d'algorisme sense reescriure el sistema— és la conclusió pràctica de l'apartat, i connecta amb el byte de versió que vam introduir al format de xifratge de 03-02.


Errors Comuns i Consells

Errors conceptuals

  1. Invertir l'ús de les claus. Es xifra amb la pública del destinatari i es signa amb la pròpia privada. «Xifrar amb la privada» no protegeix res.
  2. Creure que la signatura xifra. Una signatura no amaga el contingut; l'acredita. Si a més cal confidencialitat, s'ha de xifrar a part.
  3. Confondre MAC amb signatura. Només la signatura dona no-repudi. Si el verificador pot ser qualsevol, necessites signatura.
  4. Pensar que ECC és «menys segura» per tenir claus més curtes. P-256 equival a RSA-3072. La longitud no és comparable entre famílies.
  5. Suposar que una clau pública rebuda per la xarxa és de qui diu ser. No ho és fins que alguna cosa ho certifica (03-06).

Errors d'implementació

  1. Xifrar dades grans amb RSA. No hi caben, i és lentíssim. Fes servir xifratge híbrid.
  2. Fer servir PKCS#1 v1.5 en codi nou. OAEP per xifrar, PSS per signar; o directament Ed25519, que no et deixa triar malament.
  3. Signar JSON sense serialització canònica. Un espai o una reordenació de camps trenca la verificació i produeix incidències que semblen atacs.
  4. Generar claus amb random o en dispositius sense bona entropia. És la lliçó de 03-01, i en signatures ECDSA és letal.
  5. Deixar la clau privada en un fitxer llegible, al repositori o a la imatge del contenidor. El problema de 03-06.
  6. Ignorar el resultat de verify. Si no llança excepció és vàlida; si la llança, el missatge es descarta i es registra l'esdeveniment. Mai «es continua per si de cas».

Consells

  • Per a codi nou: Ed25519 per signar, X25519 per intercanviar. Si una interoperabilitat t'obliga a RSA, fes servir 3072 bits amb OAEP/PSS.
  • Desa sempre un identificador de clau (kid) al costat de la signatura. Sense ell, rotar la clau obliga a aturar el servei; amb ell, la rotació és transparent. És exactament el que feia el JWKS de 02-05 i es desenvolupa a 03-06.
  • Publica les teves claus públiques per un canal que el client pugui verificar, i tingues pensat des del principi com les rotaràs.
  • Anota a l'inventari tècnic quin algorisme fa servir cada component. El dia de la migració postquàntica, aquell document serà la diferència entre un projecte i una crisi.

Exercicis

Exercici 1 — Triar la primitiva correcta

Per a cada requisit de Nimbus indica: quina primitiva faries servir (xifratge simètric, xifratge asimètric, intercanvi de claus, signatura o MAC), amb quin algorisme concret, quina clau fa servir cada part i per què descartes les alternatives.

  1. L'app mòbil i l'API han d'acordar una clau de sessió sense haver-se vist mai.
  2. Nimbus ha de demostrar davant d'un jutjat, dos anys després, que un rebut el va emetre el seu sistema.
  3. L'API ha de comprovar que un webhook ve de la passarel·la de pagament, amb la qual comparteix un secret configurat.
  4. Nimbus vol enviar la clau de desxifratge d'una còpia a la consultora (A-19) per a una restauració puntual.
  5. Les actualitzacions de l'agent que Nimbus instal·la als servidors d'alguns clients han de ser verificables pel client.
  6. Un adjunt de 18 MB s'ha de desar xifrat al bucket A-05.

Exercici 2 — Explicar la forward secrecy

La Marta ha llegit en una auditoria que «el servidor no ofereix forward secrecy» i pregunta si això significa que el trànsit va sense xifrar.

Es demana: (a) respon a la Marta en dos paràgrafs sense fórmules; (b) descriu l'escenari concret de dany a Nimbus si la clau privada del servidor es filtrés d'aquí a tres anys, amb i sense forward secrecy; (c) explica quina configuració concreta ho garanteix i per què TLS 1.3 ho resol per disseny; (d) relaciona això amb el risc de «collir ara, desxifrar després».

Exercici 3 — Diagnosticar un disseny de signatura

Un desenvolupador proposa aquest disseny per als rebuts:

import hashlib

CLAU_SECRETA = "nimbus-2026"

def signar_rebut(rebut: dict) -> str:
    text = str(rebut)                                          # (1)
    return hashlib.sha256((CLAU_SECRETA + text).encode()).hexdigest()   # (2)

def verificar(rebut: dict, signatura: str) -> bool:
    return signar_rebut(rebut) == signatura                    # (3)

Es demana: (a) identifica els problemes de les tres línies marcades; (b) indica quina propietat de seguretat creu l'autor que està aconseguint i quina aconsegueix realment; (c) explica per què aquest disseny no serveix per al requisit que la clínica verifiqui el rebut pel seu compte; (d) proposa el disseny correcte i justifica la primitiva triada.


Solucions

Exercici 1

# Primitiva Algorisme Claus Per què no les alternatives
1 Intercanvi de claus X25519 (ECDHE) dins de TLS 1.3 Parell efímer per sessió a cada extrem El xifratge asimètric directe perdria forward secrecy; el simètric no es pot distribuir
2 Signatura digital Ed25519 (o RSA-PSS si ho exigeix la interoperabilitat) La privada de Nimbus signa; la pública verifica Un MAC no dona no-repudi: Nimbus té la clau i podria haver-lo fabricat
3 MAC HMAC-SHA256 Secret compartit amb la passarel·la Una signatura seria innecessàriament cara i no aporta res aquí: les dues parts es coneixen
4 Xifratge híbrid Clau de la còpia xifrada amb RSA-OAEP o sobre X25519, cap a la clau pública de la consultora La pública de la consultora xifra; la seva privada desxifra Enviar la clau en clar per correu és l'error de 03-01 ex. 1.2. I l'accés ha de ser temporal: rotar després (03-06)
5 Signatura digital Ed25519 sobre l'artefacte La privada de Nimbus al CI/CD; la pública distribuïda amb l'agent Un MAC obligaria a compartir el secret amb cada client: qualsevol podria signar. És la lliçó de SolarWinds (02-06, 03-07)
6 Xifratge simètric AES-256-GCM amb AAD del tenant_id Clau de dades protegida per la clau mestra del KMS (sobre) RSA no pot xifrar 18 MB. La part asimètrica només protegeix la clau

Exercici 2

(a) Resposta a la Marta. No: el trànsit va xifrat igualment i avui ningú no el pot llegir. «Forward secrecy» es refereix a una altra cosa —a què passaria en el futur si algú aconseguís la clau privada del servidor—. Sense forward secrecy, aquella clau permetria desxifrar retroactivament totes les converses antigues que algú hagués gravat; amb ella, cada sessió fa servir un secret efímer que es destrueix en acabar, així que el passat queda protegit per sempre.

Dit d'una altra manera: sense forward secrecy, la clau del servidor és una clau mestra que obre també l'arxiu històric; amb forward secrecy, obre només les portes d'avui endavant. Per això l'auditoria ho assenyala encara que ara mateix no hi hagi cap problema visible.

(b) Escenari. Un atacant grava el trànsit de les apps mòbils durant divuit mesos. Sense forward secrecy, en obtenir la clau privada d'aquí a tres anys desxifra els divuit mesos complets: agendes de clíniques, correus, telèfons i informació que revela indirectament dades de salut. Amb forward secrecy, no desxifra ni una sessió; només podria suplantar el servidor a partir d'aquell moment, cosa que es talla revocant el certificat i rotant la clau (03-06).

(c) Configuració. Permetre únicament suites amb ECDHE i deshabilitar l'intercanvi de clau RSA estàtic; a la pràctica, exigir TLS 1.3 —que va eliminar de l'estàndard tots els modes sense forward secrecy— i mantenir TLS 1.2 només amb suites ECDHE mentre hi hagi clients antics. El detall de configuració és a 03-05.

(d) Relació amb «collir ara, desxifrar després». És el mateix patró —gravar avui, desxifrar demà— amb un habilitador diferent: allà la clau robada, aquí un futur ordinador quàntic. La forward secrecy no protegeix davant de l'amenaça quàntica per si sola (el mateix intercanvi efímer és vulnerable a Shor), però elimina l'escenari més probable i barat, i encaixa amb la mateixa resposta: claus efímeres, algorismes actualitzables i inventari d'on es fa servir cadascun.

Exercici 3

(a) Problemes:

  1. str(rebut) — serialització no canònica: depèn de l'ordre d'inserció del diccionari i del repr de Python. El mateix rebut pot produir cadenes diferents i verificacions fallides sense cap atac. A més no és interoperable amb cap altre llenguatge.
  2. sha256(CLAU + text) — és la construcció prefix-MAC, vulnerable a l'atac d'extensió de longitud en funcions tipus SHA-2: un atacant pot afegir dades al missatge i calcular una signatura vàlida sense conèixer la clau. Per a això existeix l'HMAC, que s'estudia a 03-04. I la clau, a més, és al codi i és una cadena endevinable.
  3. == — comparació de secrets no constant en el temps: obre un canal lateral de temporització (03-01). Cal fer servir hmac.compare_digest.

(b) L'autor creu que està aconseguint una signatura amb no-repudi. Aconsegueix, en el millor dels casos, un MAC mal construït: integritat i autenticitat fràgils entre parts que comparteixen el secret, sense no-repudi, i amb la clau a l'abast de qualsevol amb accés al repositori.

(c) Per què no serveix. Perquè la clínica verifiqui pel seu compte, necessitaria CLAU_SECRETA. I així que la té, pot fabricar rebuts indistingibles dels de Nimbus. Un esquema de clau compartida no pot donar verificació pública: és la diferència estructural entre MAC i signatura.

(d) Disseny correcte. Signatura Ed25519 amb la clau privada de Nimbus custodiada al gestor de secrets o KMS, sobre una serialització canònica (json.dumps(..., sort_keys=True, separators=(",", ":"))), incloent-hi al mateix rebut un identificador de clau (kid) i la data d'emissió, i publicant la clau pública en un extrem verificable. Així qualsevol clínica verifica sense poder falsificar, la rotació de clau és possible gràcies al kid, i el rebut té valor probatori tècnic —amb la validació legal assenyalada a l'apartat 9—.


Conclusió

Has vist la idea que va resoldre el problema amb què va tancar la lliçó anterior. Un parell de claus relacionades per una funció de porta trampa —fàcil en un sentit, inviable en l'altre— permet publicar-ne una meitat sense perdre res, i amb això desapareix la necessitat de distribuir secrets previs. Tens fixada la taula que més es confon: es xifra amb la pública i es desxifra amb la privada; es signa amb la privada i es verifica amb la pública. Coneixes RSA i el seu problema difícil, les seves mides vigents —2048 com a mínim, 3072 com a recomanació— i els seus dos límits estructurals, la lentitud i la impossibilitat de xifrar dades grans; i coneixes la criptografia de corba el·líptica, on 256 bits equivalen a 3072 d'RSA, amb Ed25519 per signar i X25519 per intercanviar com a recomanació per defecte per a codi nou.

Has entès Diffie-Hellman amb l'analogia dels colors i la seva versió efímera, ECDHE, de la qual surt la propietat més valuosa del conjunt: la confidencialitat persistent (forward secrecy), que fa que robar la clau privada del servidor d'aquí a tres anys no permeti llegir res del que s'ha gravat fins avui. Has vist el xifratge híbrid —clau simètrica per a les dades, criptografia asimètrica només per protegir aquella clau— que és el patró real de TLS i del xifratge de sobre dels adjunts de Nimbus. I has separat amb precisió signatura i MAC: tots dos donen integritat i autenticitat, però només la signatura dona no-repudi, perquè el verificador no la pot fabricar. Ho has practicat signant un rebut de reserva amb Ed25519 en 64 bytes, comprovant que alterar l'import invalida la signatura, i aprenent el detall que trenca la majoria de les integracions reals: la serialització canònica.

Però la lliçó acaba amb la mateixa honestedat amb què va acabar l'anterior. La criptografia asimètrica no elimina el problema de confiança: el trasllada. Ja no cal distribuir secrets, però encara s'ha de respondre una pregunta sense la qual tot l'anterior s'esfondra davant d'un atacant al mig: aquesta clau pública que acabo de rebre, és realment de Nimbus?

A Funcions Hash, HMAC i Emmagatzematge de Contrasenyes (03-04) fem un pas enrere cap a la primitiva que ja ha aparegut dues vegades sense explicació —el hash que se signa en lloc del missatge— i l'estudiem a fons: quines propietats té, per què MD5 i SHA-1 estan trencats, com es construeix correctament un HMAC per validar el webhook de la passarel·la de pagament, i, per fi, com ha de desar Nimbus les contrasenyes dels seus usuaris amb Argon2id, sal i paràmetres calibrats. La resposta a la pregunta de la clau pública haurà d'esperar a 03-06.

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