Generating crypt() sha512 hashes in Go
Asked Answered
P

1

2

I am working on my authorization module in GoLang. Before we used PHP5 with the crypt function. The hash was generated like SHA-512:

$6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21

And stored like that in the database. But now I need make it work also in GoLang. I have searched on Google and tried different things, such as:

t512 := sha512_crypt.Crypt("rasmuslerdorf", "$6$usesomesillystringforsalt$")
fmt.Printf("hash: %v\n", t512)

But all generate different things. Who can help us further?

We want validate and create hashes like the php version.

Thanks in advance.

Proton answered 5/10, 2014 at 6:8 Comment(3)
How does the PHP version look? In the go example posted here you hash what looks like the start of the resulting string you're after. You should (probably) be hashing the salt+password, then appending the $6$rounds$salt$ afterwards. You would also need to introduce a loop to actually use the rounds number.Octave
If there is no need for compatibility with existing hashes, don't use SHA-512, use Go's bcrypt library (godoc.org/code.google.com/p/go.crypto/bcrypt). SHA-512 is a long way off being a suitable password hashing function.Endarch
At the moment we are stick to the SHA-512 hashing function. Before we had md5 but on the fly we changed it to SHA-512. Every time a user logged in, in our system, the system checked if the sha-512 hash exists. If not, verify with the md5 hash. If md5 hash is correct, encrypt with the SHA-512 hash and remove the md5 hash. In this way we can go also to a better function.Proton
A
9

The osutil library at https://github.com/kless/osutil has support for all crypt() hash types.

Your password hash can be produced with the following php code:

echo crypt('rasmuslerdorf', '$6$usesomesillystringforsalt');

This code produces the following hash:

$6$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21

This can be reproduced in Go like this:

package main                                                

import (
    "fmt"

    "github.com/kless/osutil/user/crypt/sha512_crypt"
)

func main() {
    c := sha512_crypt.New()
    hash, err := c.Generate([]byte("rasmuslerdorf"), []byte("$6$usesomesillystringforsalt"))
    if err != nil {
        panic(err)
    }

    fmt.Println(hash)
}

When run, it also produces the correct hash:

$6$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21

I hope this answers your question.

While implementing this please note that only 16 characters are used from the salt, so the same hash is returned for the salt usesomesillystri. Make sure that you choose random salts in the production code.

Althing answered 5/10, 2014 at 13:32 Comment(7)
Thank you so much! This is exactly where I am looking for. It works all fine with my currently password hashes.Proton
How about the rounds=5000?Yeah
Does anyone know why c.Generate([]byte("enter-new-password"), []byte("$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2")) gives me an invalid magic prefix error?Vertumnus
I've answered my own comment above through this question: #51120182 . The kless/osutil didn't have support for blowfish hash method, so I had to use a different module all together. blowfish is often used for PHP5.3 and below.Vertumnus
@John this link shows which hash algorithm to used base on the prefix code: security.stackexchange.com/a/92150/71546Alterant
Take into account that this library seems to changed to github.com/tredoe/osutil/user/crypt/sha512_cryptChoiseul
To add one thing i tried: if you dont want to write randomising the salt as proposed above, all you need is to pass empty string i.e. salt := "" in the following line. this util itself generates random salt/prefix ($6$) in c.Generate([]byte(plainText), []byte(salt))Pammie

© 2022 - 2024 — McMap. All rights reserved.