Generando password seguros Bcrypt/Blowfish en GO



Los históricamente conocidos algoritmos de hash MD5, SHA1 dejan de ser una alternativa segura a la hora de almacenar y proteger contraseñas, debido a que sus algoritmos matemáticos convierten una cantidad de datos a un valor string de longitud fija, dejando la posibilidad de originarse una colisión ó 2 hash iguales para distintos datos.

Por qué usar Bcrypt?

Es un hash pensado para ser utilizado para guardar contraseñas. Utiliza el algoritmo Blowfish de una sola via.

Razones el por que usar Bcrypt:

1. Es lento,  y lento es bueno porque  fustra los ataques de fuerza bruta. (pueden leer de aquí.)

2. La salida de bcrypt es un alfabeto base-64.

En esta entrada,  les comparto como generar un hash Bcrypt/Blowfish con el lenguaje de programación de Google, el ya conocido Go (Golang).

Para ello, primero necesitamos instalar Golang:

$ sudo yum install golang

Seteamos la variable de entorno:

$ mkdir $HOME/go
$ export GOPATH=$HOME/go
$ export PATH=$PATH:$GOPATH/bin

Instalamos mercurial, para poder descargar el package bcrypt del repositorio de Google.

$ sudo yum install mercurial

Si se presenta un problema para instalar Mercurial, puedes hacer lo siguiente:

$ sudo yum install python-setuptools python-devel gcc -y
$ sudo easy_install Mercurial

Luego descargamos el package del repositorio de Google para generar bcrypt.

$ go get code.google.com/p/go.crypto/bcrypt

Luego creamos nuestro script en go (bcrypt_generate.go)

package main
import (
	"flag"
	"fmt"
	"os"
	"code.google.com/p/go.crypto/bcrypt"
)
 
func main() {
	password := flag.String("password", "", "the password to hash or validate")
	hash := flag.String("hash", "", "the hash to validate the password against")
	cost := flag.Int("cost", 13, "the cost of the bcrypt function to execute")
 
	flag.Parse()
 
	if *hash != "" {
		// do validation
		err := bcrypt.CompareHashAndPassword([]byte(*hash), []byte(*password))
		if err != nil {
			fmt.Print("Error: Password and hash do not match.")
			os.Exit(1)
		}
		fmt.Print("OK")
		os.Exit(0)
	} else {
		// do encryption
		generated_hash, err := bcrypt.GenerateFromPassword([]byte(*password), *cost)
		if err != nil {
			fmt.Print("Error: Couldn't generate hash.")
			os.Exit(1)
		}
 
		fmt.Printf("%s\n", generated_hash)
		os.Exit(0)
	}
}

Compilamos nuestro script.

$ go build clicrypt.go

Probamos nuestro script, intentando hashear un valor, atraves del parametro password.

$ ./bcrypt_generate -password="@gchacaltanab"

Me retorna el siguiente hash:

$ $2a$13$oWvgAl9CYjiQE8rjzX6h4.Lf/NS2pIAb9KnfG2s9vszFy6dXmP6Ry

Y finalmente para comparar hash, se utiliza de la siguiente forma.

$./bcrypt_generate -password="@gchacaltanab" -hash='$2a$13$oWvgAl9CYjiQE8rjzX6h4.Lf/NS2pIAb9KnfG2s9vszFy6dXmP6Ry'

Fuente imagen: eduonix.com

Publicado por

24 x 7 Internet User, Engineer, Web & Backend Developer, IT Project Manager, University professor, Freelancer, Programming Fanatic and Kanban lover.

  • Javier Millan Macias

    my buen tutorial, me ha venido muy bien! clarito como debe ser!

    http://www.compumarketing.es

  • gchacaltana

    Que bueno! 🙂

  • Hola!

    Muchas gracias por la informacion, habra que probarlo y veremos que tal.

    Saludos!