Guardar contraseñas como hash

Convierte un PIN en un número con una función hash y compara el resultado en lugar de guardar el PIN escrito.

Qué vas a construir

El control de acceso de las clases anteriores, pero sin el PIN escrito en el código. El programa guarda solo un hash del PIN y compara el hash de lo que escribes.

Lo que aprendes

  • Qué es una función hash: convierte un texto en un número fijo.
  • Por qué guardar hashes protege la confidencialidad.
  • Cómo calcular un hash sencillo con unsigned long.

Idea clave

Una función hash es de un solo sentido: es fácil calcular el resultado a partir del texto, pero no es práctico recuperar el texto a partir del resultado. El sistema guarda el hash del PIN. Cuando escribes un PIN, el sistema calcula su hash y lo compara. Si los hashes coinciden, el PIN es correcto.

Importante: la función de este ejemplo (djb2) es didáctica. Los sistemas reales usan funciones diseñadas para contraseñas, como bcrypt, scrypt o Argon2, con una sal aleatoria. No uses djb2 para proteger datos reales.

Materiales en Tinkercad

  • Arduino Uno R3
  • Monitor serie

Paso 1: Función hash

unsigned long hashDe(String texto) {
  unsigned long h = 5381;
  for (unsigned int i = 0; i < texto.length(); i++) {
    h = h * 33 + texto.charAt(i);
  }
  return h;
}

Paso 2: Código

El hash del PIN 4821 ya está calculado: 2088405012. El PIN original no aparece en el programa.

const unsigned long HASH_PIN = 2088405012UL;

unsigned long hashDe(String texto) {
  unsigned long h = 5381;
  for (unsigned int i = 0; i < texto.length(); i++) {
    h = h * 33 + texto.charAt(i);
  }
  return h;
}

void setup() {
  Serial.begin(9600);
  Serial.println("Escribe el PIN y pulsa Enter:");
}

void loop() {
  if (Serial.available()) {
    String intento = Serial.readStringUntil('\n');
    intento.trim();

    if (hashDe(intento) == HASH_PIN) {
      Serial.println("Acceso concedido");
    } else {
      Serial.println("Acceso denegado");
    }
  }
}

Paso 3: Prueba y verificación

  1. Escribe 4821. Debe conceder el acceso.
  2. Escribe 1234. Debe negar el acceso.
  3. Abre el código y busca el PIN 4821. ¿Aparece en alguna línea? ¿Por qué no?
  4. Cambia el PIN: calcula el hash de tu nuevo PIN con hashDe() (puedes imprimirlo con Serial.println(hashDe("tu_pin")); en un programa aparte) y reemplaza HASH_PIN.

Cómo sabes que lo lograste

  • El acceso correcto funciona con 4821.
  • El PIN no aparece en el código.
  • Sabes cambiar el PIN calculando un nuevo hash.
  • Puedes explicar por qué djb2 no sirve para datos reales.

Qué salió mal

Siempre niega el acceso. Compara el hash con el valor exacto. Un espacio extra cambia el hash, así que revisa trim().

El número del hash no coincide. Verifica que la función hashDe() sea idéntica en el programa que calculó el hash y en este.

Siguiente clase

En la siguiente clase vas a ocultar un mensaje con una operación XOR, y a ver por qué una clave corta no alcanza.