Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

golang equivalent of PHP crypt()

Tags:

php

go

crypt

This line of code in PHP evaluates to true

echo '$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2' == crypt("enter-new-password",'$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2');

What I need is a crypt function in Golang that will also evaluate to true.

ATTEMPT 1

I tried this but it evaluated to false:

import "github.com/nyarla/go-crypt"
log.Println("$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2" == crypt.Crypt("enter-new-password","$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2"))

ATTEMPT 2

I also tried to define and use this crypt function that I found somewhere else, but it also returned false:

package main

import (
    "fmt"
    "unsafe"
)

// #cgo LDFLAGS: -lcrypt
// #define _GNU_SOURCE
// #include <crypt.h>
// #include <stdlib.h>
import "C"

// crypt wraps C library crypt_r
func crypt(key, salt string) string {
    data := C.struct_crypt_data{}
    ckey := C.CString(key)
    csalt := C.CString(salt)
    out := C.GoString(C.crypt_r(ckey, csalt, &data))
    C.free(unsafe.Pointer(ckey))
    C.free(unsafe.Pointer(csalt))
    return out
}

ATTEMPT 3

I also tried this, but it doesn't seem to have support for CRYPT_BLOWFISH, which was what was used by an older PHP5.3 and earlier:

Why does my crypt package give me invalid magic prefix error?

So my question is:

How do I get a golang crypt function to behave exactly like the PHP crypt function for the strings enter-new-password and $2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2?

like image 932
John Avatar asked Jul 01 '18 01:07

John


1 Answers

Although I haven't found an exact "Go crypt function" equivalent of PHP's crypt function, I found an alternative.

The following solved my problem

import "golang.org/x/crypto/bcrypt"
// check will be nil if the bcrypt version of "enter-new-password" is the same as the "$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2" .  Otherwise check will be an error object
check := bcrypt.CompareHashAndPassword([]byte("$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2"),[]byte("enter-new-password"))
log.Println(check)

The golang.org/x/crypto/bcrypt/bcrypt_test.go has some useful examples of how to use this module.


Apparently PHP's crypt function has many different ways of hashing a value, like sha256, sha512, blowfish etc... It seems there are many go lang modules out there, but you have to explicitly state the hash type, the cost, etc... In my question, the existence of $2a$ as a prefix to the hash value suggested the use of some blowfish type hash. Some of my earlier attempts didn't consider this. In fact, the module in attempt 3 does not have support for blowfish.

like image 99
John Avatar answered Nov 13 '22 11:11

John