miércoles, 4 de febrero de 2026

Cómo hashear contraseñas de forma segura en Google Apps Script

Usando Google Apps Script, guardar los passwords de manera segura es posible siguiendo paso a paso este manual.

Cuando construyes un sistema de login, el error más común —y más peligroso— es guardar el password tal como el usuario lo escribe.

Si alguien accede a tu base de datos:

  • ve todas las contraseñas
  • compromete a todos tus usuarios
  • y probablemente reutilizan esas claves en otros servicios

La solución correcta no es “encriptar” el password, sino hashearlo.


❌ El error clásico

// MAL — extremadamente inseguro sheet.getRange(row, 3).setValue(password);

Esto guarda el password real.
Si alguien ve la hoja → todo está perdido.


✅ La solución correcta: HASH

Un hash es una función matemática que:

  • transforma un texto en una huella irreversible
  • siempre produce el mismo resultado para el mismo input
  • no puede convertirse de vuelta al texto original

Ejemplo:

clave123  →  a3dcb4d229de6fde0db5686dee47145d
clave124  →  9f86d081884c7d659a2feaa0c55ad015

Un solo carácter cambia todo el resultado.


🔧 Mi función hashPassword en Apps Script

function hashPassword(password) {
  return Utilities.computeDigest(
    Utilities.DigestAlgorithm.SHA_256,
    password,
    Utilities.Charset.UTF_8
  )
  .map(b => ('0' + (b & 0xFF).toString(16)).slice(-2))
  .join('');
}

Veamos qué hace realmente.


🧠 Paso 1: SHA-256

Utilities.DigestAlgorithm.SHA_256
  • Algoritmo estándar
  • usado en sistemas reales
  • produce un hash de 256 bits
  • rápido y confiable

En Google Apps Script es la mejor opción nativa.


🧠 Paso 2: UTF-8

Utilities.Charset.UTF_8

Esto garantiza que:

  • letras con acentos
  • símbolos
  • emojis

siempre generen el mismo hash, sin importar el sistema. Sin esto, el mismo password podría producir hashes distintos.


🧠 Paso 3: bytes → hexadecimal

El resultado de computeDigest no es texto, es un array de bytes:

[34, -120, 91, 77, ...]

Por eso convertimos cada byte a hexadecimal:

.map(b => ('0' + (b & 0xFF).toString(16)).slice(-2))

Esto:

  • normaliza los valores
  • asegura siempre 2 caracteres por byte
  • produce un string limpio y comparable

Finalmente:

.join('');

Obtenemos algo así:

ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f

🔄 Cómo funciona el login realmente

🟢 Registro

password → hashPassword → guardar hash

Nunca se guarda el password real.


🟢 Login

password ingresado → hashPassword
hash generado === hash guardado → acceso OK

Nunca necesitas saber la contraseña original.


✅ Comparación correcta

if (hashPassword(inputPassword) === storedHash)

🔐 ¿Es SHA-256 suficiente?

Opinión honesta:

  • Para un MVP
  • sin backend propio
  • usando Google Apps Script
  • sin librerías externas

👉 sí, es una mejora enorme y correcta

En sistemas grandes se usa:

  • bcrypt
  • scrypt
  • argon2
    (con salt y cost)

Pero Apps Script tiene límites, y esto ya te pone muy por encima del promedio.


🧠 Regla de oro

Un sistema seguro nunca guarda contraseñas.
Guarda pruebas matemáticas de que el usuario las conoce.


🚀 Conclusión

Con una sola función:

  • evitas fugas masivas
  • mejoras la seguridad real
  • no rompes tu frontend
  • no necesitas servidor

Si estás construyendo productos sin backend tradicional, esto no es opcional, es obligatorio.

No hay comentarios:

Publicar un comentario