Saltar al contenido

Explicar BCrypt como si tuviera 5

Solución:

Hashing versus cifrado

La mayor diferencia entre bcrypt y blowfish es que blowfish es un algoritmo de cifrado simétrico y bcrypt es un algoritmo hash. (Es un tipo especial de algoritmo hash, pero llegaremos a eso más adelante).

Cifrado (lo que hace Blowfish)

Un algoritmo de cifrado simétrico toma una clave secreta y algo de texto sin formato (el término “mensaje” se usa regularmente y la variable metro se utiliza normalmente para referirse a él) y genera texto cifrado, C. La idea es que el texto cifrado solo se puede volver a transformar en el mensaje original con el mismo[^same] clave secreta que se utilizó al cifrar.

[^same]: Estoy dando respuestas aproximadamente verdaderas aquí para centrarme en las ideas y conceptos centrales. Espero que aquellos que reconocen que mis respuestas no son exactamente verdaderas me den un poco de holgura con fines expositivos.

Así que Alice podría cifrar el mensaje “Ataque al amanecer” con la clave 13 (esto es no blowfish, pero es un cifrado simétrico) y producir el texto cifrado “Nggnpx ng qnja”. Ella puede enviar ese texto cifrado a Bob, y si Bob sabe que la clave es 13, puede transformar el texto cifrado en los mensajes originales. A veces, Alice no quiere enviar un mensaje a otra persona, pero quiere guardarlo para que pueda leerlo más tarde. Podemos pensar en esos casos como si Alice enviara un mensaje a la futura Alice.

Con Blowfish (en lugar del cifrado que utilicé en mi ejemplo), es efectivamente imposible que cualquiera que no tenga la clave aprenda algo sobre el mensaje original (aparte de su longitud y existencia) a partir del texto cifrado. Solo un aparte, AES es un algoritmo de cifrado simétrico preferible sobre Blowfish, pero continuaré usando Blowfish en mis descripciones ya que eso es sobre lo que se preguntó.

Hashing

Un algoritmo hash criptográfico (bcrypt es un tipo especial, con algunos extras, pero comenzaré con un caso más simple) no toma una clave y no es prácticamente reversible. Entonces, un algoritmo hash criptográfico como SHA256 tomaría un mensaje (digamos una contraseña) como “¡JaguarsRule!” y transformarlo en hash.

$ echo -n 'JaguarsRule!' | shasum -a256
13f26e5a60e402d895c5ce1d9492d080563c5079a8b5f52a25953fd24a2cb1da  

Una de las varias propiedades de un hash criptográfico es que no se puede calcular de manera factible “JaguarsRule!” de 13f26e5a60e402d895c5ce1d9492d080563c5079a8b5f52a25953fd24a2cb1da. En este caso no hay clave.

Por lo tanto, un mecanismo de hash sencillo como este podría parecer una buena manera de verificar las contraseñas en un servidor. Suponga que está ejecutando algún servicio web en el que las personas inician sesión. Tienes un usuario, digamos con nombre de usuario jason quien configura su cuenta con la contraseña JaguarsRule!. Como no quiere que nadie que pueda leer lo que está en su servidor aprenda la contraseña de Jason, no almacena la contraseña en sí. En su lugar, almacena su hash.

Cuando jason (o alguien que pretende ser jason) inicia sesión en su servidor, toma la contraseña que se ingresó y realiza la operación de hash y compara ese hash que está almacenado. Si los hash coinciden, el sistema sabe que se ingresó la contraseña correcta.

Sales y cocción lenta

El esquema descrito anteriormente, que utiliza un hash criptográfico general como SHA256, funcionaría muy bien excepto por una cosa: la gente elige contraseñas que se pueden adivinar. Si las personas fueran tan propensas a utilizar contraseñas como wZFoO_SKrgEw como son para JaguarsRule! entonces no necesitaríamos funciones de hash especializadas como bcrypt. Pero la gente, siendo humana, no va a elegir contraseñas al azar y uniformemente sobre un espacio suficientemente grande. En cambio, es mucho más probable que elijan algunas contraseñas posibles sobre otras.

Sal

Piense en otro usuario de su sistema, pillboy. Pill Boy también es fanático de los Jacksonville Jaguars y resulta que también eligió JaguarsRule! como su contraseña. Usando hash (sin sal), el hash de la contraseña de Pill Boy será el mismo que el hash de la contraseña de Jason. Un atacante solo necesita comparar hashes para ver que esos dos usuarios tienen la misma contraseña.

Además, si un atacante descubre de una forma u otra que la contraseña de Jason es JaguarsRule! ‘, Inmediatamente conoce la contraseña de Pill Boy. Además, podría crear una gran lista de hashes para las contraseñas más comunes.

La solución a esto es agregar algo único a la contraseña antes de aplicar el hash. Entonces, cuando creas por primera vez el hash de la contraseña de Jason (cuando Jason se registra por primera vez y crea la contraseña), le agregas algunas cosas al azar. Suponga que en este momento su sistema crea la sal 9cb3779f69e271c1. A continuación, lo coloca delante de la contraseña antes de aplicar el hash, por lo que en realidad es un hash de algo como 9cb3779f69e271c1JaguarsRule! (No es así como se agrega realmente la sal, pero es lo suficientemente cerca como para explicar para qué sirve la sal). El hash de 9cb3779f69e271c1JaguarsRule! será completamente diferente al hash de JaguarsRule!.

El sistema necesitará saber cuál era la sal cuando llegue el momento de verificar una contraseña. Por lo que almacenará la sal y el hachís junto con el nombre de usuario de Jason. Cuando Pill Boy crea su cuenta, se configurará con una sal diferente generada aleatoriamente, por lo que su combinación de sal y contraseña producirá un hash diferente.

Entonces, lo que almacena en su servidor podría verse así

[
    {
        "algorithm": "sha256",
        "username": "jason",
        "salt": "9cb3779f69e271c1",
        "hash": "37a932267ed055facf03cc5d09ca90f927a1eed47a8cd4856e57cd67434426be"
    },
    {
        "algorithm": "sha256",
        "username": "pillboy",
        "salt": "0a19471dab710025",
        "hash": "4be637a8c85455dce0cdc1c7670f062764100276b6ed64141c06fbef4578f185"
    },

]

Al tener diferentes sales para estos usuarios, no podemos ver que tienen la misma contraseña, y el atacante no podrá comparar los hash con una lista que ella calculó previamente de hash de contraseñas comunes.

Así que bcrypt, debido a que está diseñado para el hash de contraseñas, toma un poco de sal.

Tomándolo con calma

La salazón es absolutamente esencial, pero aún así no impide que un atacante que se apodera de lo que está almacenado en el servidor adivine automáticamente. Puede tomar la sal y combinar eso con contraseñas comunes y calcular hashes hasta que encuentre una coincidencia. Podría realizar decenas o cientos de millones de adivinaciones de contraseñas por segundo.

Una de las razones por las que puede calcular muchas suposiciones con tanta rapidez es que los algoritmos hash criptográficos como sha256 están diseñados para ser rápidos y eficientes y, al mismo tiempo, cumplir con sus propiedades de seguridad. Así que cosas como bcrypt son “hash lento”. La idea es que pasar de un mensaje (sal y contraseña) a un hash requiera tanto cálculo que una computadora típica tardará un cuarto de segundo en realizar el hash.

El usuario no notará una demora de un cuarto de segundo, pero si el atacante está usando el mismo tipo de computadora, se verá reducido a hacer cuatro conjeturas por segundo en lugar de 10 millones. (En la práctica, tendrá un equipo informático especialmente configurado, pero reducir su velocidad de millones de suposiciones por segundo a decenas de miles de suposiciones por segundo es algo bueno).

bcrypt es uno de varios “hashes lentos”. Otros son PBBKDF2, scrypt y Argon2. Los dos últimos no solo requieren mucho cálculo para crear el hash, sino que también requieren mucha memoria.

Bcrypt es genial, pero …

La sal y el hash lento es algo que todo sistema de hash de contraseñas debería hacer. Pero también produce rendimientos decrecientes. Hay muchas cosas que el hash lento puede hacer por el defensor, por lo que aún necesitamos (siempre que existan contraseñas) hacer que las personas usen más para adivinar las. He escrito más sobre eso en Bcrypt, es genial, pero …

NB: Gracias https://security.stackexchange.com/users/6253/schroeder por eliminar correctamente mi respuesta anterior en la que tomé “como si tuviera 5” literalmente. Y mis disculpas al cartel original por haber sido sarcástico en lugar de útil.

Bcrypt utiliza el cifrado de bloques de clave simétrica Blowfish y acepta 3 parámetros; costo, sal y contraseña.

  • El costo lo determina el nivel del sistema para que el administrador pueda decidir el momento del ataque de búsqueda de contraseña, consulte hashcat. Determina el número de iteraciones como iter= 2^cost donde el costo está entre 2 y 31.

  • La sal es aleatoria de 16 bytes. Se puede generar cualquier buena fuente aleatoria como devurandom

  • La contraseña es la contraseña del usuario que se procesará. El tamaño de las contraseñas es de 1 a 72 bytes.

  • La salida de Bcrypt es de 24 bytes.

El Bcrypt cifra el texto OrpheanBeholderScryDoubt en un modo ECB encadenado.

 state = EksBlowfishSetup(cost, salt, password) //Special key scheduling 
 ctext = "OrpheanBeholderScryDoubt"
 repeat (64)
      ctext = EncryptECB(state, ctext)
 return Concatenate(cost, salt, ctext)

actualización sobre el costo

EksBlowfishSetup (Extensive Key Setup) brevemente de la siguiente manera;

state = InitialState()
state = ExpandKey(state, salt, password)
repeat (2^cost)
    state = ExpandKey(state, 0, password)
    state = ExpandKey(state, 0, salt)

El costo juega un papel en la función anterior de BCrypt. Con el costo aumentado, el ciclo de repetición se ejecutará exponencialmente. Esto aumentará el tiempo de ataque, como puede ver en la tabla de esta respuesta. Si desea compararlo con hashcat, vea un punto de referencia para Tesla K80

Nota: que Bcrypt es antiguo (1999), debería utilizar Argon2i como el ganador del concurso de hash de contraseñas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *