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