Treinta minutos en clase; los minutos de cada ejercicio son un ritmo sugerido y el docente gestiona el tiempo, así que lo que no se cierre en el aula continúa como trabajo independiente. Los tres ejercicios corren en su navegador, sin conexión: reparto de secreto de Shamir, rotación de llave maestra sin recifrar, y tokenización. El ejercicio en Python, con pycryptodome, está al final.
La llave de los cajeros la tiene hoy una sola persona, de hecho, sin custodios. Con un umbral de tres, repártanla entre cinco custodios: harán falta tres para reconstruirla, y con dos no se obtiene nada. Ese último punto es el que hay que ver con los ojos.
Cada byte de la llave es el término independiente de un polinomio secreto de grado dos —una parábola en aritmética de campo finito—. Cada custodio recibe un punto de esa parábola. Con tres puntos hay una sola parábola que pasa por ellos, así que el término independiente queda determinado: se recupera la llave. Con dos puntos pasan infinitas parábolas, una por cada valor posible del secreto, y todas son igual de probables. Por eso dos custodios no obtienen una versión aproximada: obtienen un valor que no tiene ninguna relación con la llave real. Compruébenlo marcando solo dos partes.
«Rotar llaves es inviable, habría que recifrarlo todo.» Este ejercicio demuestra que no. Se cifran los datos con una llave de datos (DEK), y la DEK se guarda envuelta bajo una llave maestra (KEK). Rotar la maestra vuelve a envolver la DEK: cambian 40 bytes, y ni un solo registro se recifra.
Imaginen mil cajas cerradas con la misma llave pequeña, la DEK. Esa llave pequeña se guarda dentro de una caja fuerte, la KEK. Rotar la llave maestra es cambiar la caja fuerte y mover la llave pequeña de la vieja a la nueva: las mil cajas siguen cerradas con la misma llave pequeña, intactas. Recifrar todo sería abrir las mil cajas y volver a cerrarlas con otra llave —lo que nadie quiere hacer, y por eso no se rota nunca en Coopaburrá—. Con este diseño, rotar cuesta 40 bytes.
El área de analítica necesita cruzar datos por persona, pero no necesita las cédulas. Reemplacen cada cédula por un token aleatorio, guarden la correspondencia aparte, y expliquen qué puede hacer un tercero con el archivo tokenizado y qué no.
Conserva la posibilidad de cruzar: la misma cédula produce siempre el mismo token, así que analítica puede contar cuántas operaciones hizo cada persona sin saber quién es. Destruye la posibilidad de identificar: el token es aleatorio y no tiene ninguna relación matemática con la cédula, así que del token no se vuelve a la cédula sin la tabla de correspondencia. Un tercero que reciba el archivo tokenizado puede hacer estadística, pero no puede señalar a nadie.
Es distinto de cifrar: un dato cifrado se puede descifrar con la llave, y dos datos iguales cifrados con modos que preservan patrones pueden delatarse. El token no se «descifra»: se busca en una tabla que vive en otro lugar, bajo otro control. Por eso es la respuesta correcta para un archivo que sale del área que lo custodia.
Seis situaciones de gestión de llaves y datos. Elijan la técnica adecuada.
Una página por equipo con los tres resultados y, sobre todo, la respuesta del ejercicio 3, que va directo a la recomendación de la entrega final.
# pip install cryptography pycryptodome import os, secrets from Crypto.Protocol.SecretSharing import Shamir from cryptography.hazmat.primitives.keywrap import aes_key_wrap, aes_key_unwrap # 1 · repartir la llave de los cajeros: cinco custodios, umbral de tres llave_cajeros = os.urandom(16) partes = Shamir.split(3, 5, llave_cajeros) assert Shamir.combine(partes[:3]) == llave_cajeros # tres partes bastan # 2 · rotar la llave maestra sin recifrar los datos kek_vieja, kek_nueva = os.urandom(32), os.urandom(32) dek_envuelta = aes_key_wrap(kek_vieja, os.urandom(32)) dek_rotada = aes_key_wrap(kek_nueva, aes_key_unwrap(kek_vieja, dek_envuelta)) # cambiaron 40 bytes; ni un registro se recifro # 3 · tokenizar una cedula sin relacion con el valor original token = secrets.token_hex(8) # sustituto aleatorio correspondencia = {token: "1015442387"} # se guarda aparte, con acceso restringido