Git 3.0 cambiará todo a SHA-256 y el autor de Git dice que será un desastre

Código en una pantalla oscura con colores de sintaxis
El hash es la identidad de cada objeto en Git. Cambiarlo no es un detalle menor.

El tipo que escribío Git dice que Git lo está rompiendo. No es un developers arrogant en un hilo de Reddit: es Scott Chacon, cofundador de GitHub y autor de Pro Git, uno de los libros que te hicieron entender cómo funciona esta herramienta. Su veredicto sobre el próximo Git 3.0 es brutal: un desastre global, carísimo y completamente evitable. Y lo agrega: casi nadie sabe lo que viene.

El plan de Git 3.0 es simple en apariencia y brutal en consecuencias: SHA-256 deja de ser la alternativa experimental y se convierte en el algoritmo de hash por defecto para todo repositorio nuevo. Hasta ahora Git usa SHA-1 desde 2005, cuando Linus Torvalds lo eligió, y funcionó bien durante dos décadas.

¿Por qué SHA-1 debería estar "roto"?

Empecemos por el contexto, porque aquí está el error de lectura más común. Git es una base de datos direccionable por contenido: calcula un hash del contenido y lo usa como clave. Los commits codifican el hash del commit anterior, así que la integridad se propaga hacia atrás. Hashear el último commit es, técnicamente, hashear millones de archivos que lo preceden.

En 2005 eso era incuestionable. Hoy, SHA-1 está semirroto: existen ataques publicados que generan colisiones a propósito (SHAttered en 2017, SHA-1 is a Shambles en 2020). Con suficientes GPUs puedes fabricar dos archivos distintos que producen exactamente el mismo hash.

Hasta ahí todo suena a catástrofe. No lo es, y aquí está el giro que casi nadie entiende.

Colisiones != segundo pre-imagen (la distinción que salva todo)

Ahí está el corazón técnico del asunto, y distingue a quien entendió de algo de quien repitió un titular.

Un ataque de colisión exige que el atacante sea el mismo que introduce el archivo benigno: genera el par, te lo da, espera que gane tu confianza y luego lo cambia por la versión maliciosa. Sí, suena grave, pero el atacante tiene que ser el autor del archivo original.

Un ataque de segundo pre-imagen es mucho peor: ves un archivo que quieres reemplazar y fabricas otro malicioso que colisiona con su hash, sin que el autor original tenga participación alguna. Y aquí viene la sorpresa: casi ninguna función de hash usada jamsánd ha sido vulnerable a esto.

Chacon calcula el peor caso para MD5, que es infinitamente más débil que SHA-1. Si los unos 3 mil millones de GPUs del planeta fueran RTX 5090, todos dedicados el 100% del tiempo a esto y nada más, el tiempo esperado para encontrar un pre-imagen sería de unos 16 mil millones de años. La edad del universo, pero al cuadrado.

El problema real nunca fue el hash

Entonces, si SHA-1 resiste bien, ¿por qué gastar el ecosistema entero? Chacon echa la culpa al marco equivocado. En el mundo del control de versiones el hash nunca fue el mecanismo de confianza.

Realmente creo que la gente no debería considerar que SHA-1 es la "seguridad". La verdadera seguridad está en la distribución. — Linus Torvalds, 2005

La confianza siempre estuvo en dónde haces pull. Si tu fuente está comprometida, da igual si el hash es SHA-1, SHA-256 o la suma de todos los números primos. Linus lo dijo al nacer Git y Chacon lo repite 21 años después. El ataque de colisión tampoco te regala nada práctico: todavía tienes que lograr que alguien haga pull de tu archivo y lo ejecute de una forma teñguida — y eso son dos problemas distintos, no uno.

La factura real

Aquí se pone serio el artículo. Esto no es una entrada de blog sin sustancia; es contabilidad.

1. Repositorios atrapados en dos universos. Todo proyecto nuevo será SHA-256 y todo proyecto viejo sigue en SHA-1, y los formatos no se pueden mezclar. Creas el repo en local, lo subes, y:

fatal: the receiving end does not support this repository's hash algorithm

Necesitas saber qué versión de Git usaste en el git init y elegir el formato correcto al crear el repo en el servidor. Persona normal que entiende eso.

2. Las firmas se rompen. Si un proyecto migra, hay que convertir cada objeto, y eso invalida todas las firmas existentes. Además, cualquiera que trabaje en ese repo debe cambiar al mismo tiempo o te cae el split head.

3. Las URLs mueren. Cada URL, cada enlace de Slack o email que jamás llevaba un hash SHA-1 deja de existir. Y no puedes redirigirlo si te cambiaste de host.

4. El ecosistema de librerías se rompe. Git se desarrolló con una librería GPL no reentrante y no enlazable, así que casi todo el ecosistema usa reimplementaciones desde cero. Esas librerías tienen soporte cero o parcial. Todo script que no haga fork-exec del binario de Git va a romperse en algún momento.

5. Google podría boicotearlo internamente. Emily Shaffer, del equipo de infraestructura de Google, dió que la empresa ya está preparando respuestas y que el panorama no es bonito. Chacon cuenta que Google considera forzar overrides de sistema para que todos sus proyectos internos sigan en SHA-1 el mayor tiempo posible.

Y lo más incisivo: si el mayor usuario de Git del mundo quiere bloquear la característica, la característica está mal.

La alternativa que sí resuelve

Chacon no se queda en la queja. Propone algo sencillo: no usar el hash para confiar en el contenido. Agregar una firma independiente sobre un checksum del árbol, separada del SHA-1, como encabezado opcional y retrocompatible.

Y hay un dato que destruye el argumento del gasto: implementó una prueba de concepto y la midió contra Chromium con todos sus submódulos, el peor caso imaginable: 35 GB de working tree y 2.1 millones de archivos. 5 segundos en un M5 con multithreading. El kernel de Linux: 257 ms. El propio proyecto Git: 17 ms.

Además resuelve el tema de cumplimiento del NIST sin tocar nada: si cada firma cubre un hash SHA-256 del contenido, SHA-1 deja de estar aplicando protección criptográfica. Solo queda como clave direccionable.

Y si SHA-256 algún vez se rompe, agregas otro algoritmo. Migrar un solo proyecto, no todos los que existen.

Mi lectura (y el ángulo LATAM)

Chacon reconoce que el debido proceso ya ocurrió en la lista de correo de Git por años, con gente mucho más brillante que él. Su artículo no innova: tira de la palanca del gatillo antes de que se dispare. Ese es el valor real, y es enorme.

Para los que trabajamos en LATAM el impacto será concreto en una cosa: forks y herramientas de larga cola. Si el ecosistema se parte en dos formatos, los proyectos pequeños con menos recursos son los primeros en sufrir, porque nadie va a mantener un espejo en SHA-256 de un repositorio de 400 estrellas. Laminoría de Innovación paga el costo de una decisión tomada por defecto, no por necesidad.

Y ojo con el marco: esto no es "los desarrolladores se niegan a actualizar". Es un cambio de algoritmo por defecto en la herramienta más extendida del mundo, hecho por las mismas personas que escribieron el código, que dicen que el costo es enorme y el beneficio práctico casi nulo. Cuando los Responsible del core del open source dicen "esto sale caro", conviene escuchar.

El punto que queda

Hay una ironía enorme en todo esto. Git 3.0 todavía no sale, y una de las razones principales que retrasan el lanzamiento es precisamente que GitHub aún no puede aceptar repositorios SHA-256 correctamente. O sea: el cambio que nadie quiere ya está costándole tiempo al ecosistema.

Mi postura es simple: el hashing más fuerte es buena higiene, pero migrar por defecto a todo el planeta no es higiene, es un naufragio. Es un coste que paga todo el mundo por un riesgo teórico que casi nadie tiene. Chacon tiene razón en algo que se dice poco: la seguridad nunca estuvo en el hash, estaba en quién te sirve el código.

¿Cuándo teóricamente vas a migrar — o vas a esperar a que un mantenedor con más recursos que tú lo haga por ti? Cuéntame en los comentarios.

Comparte esto con el compañero que dice que "Git 3.0 no te va a afectar". Le afecta más de lo que cree.