Our app uses the library, SecureHash object, in order to create one-way password: https://github.com/nremond/pbkdf2-scala/blob/master/src/main/scala/io/github/nremond/SecureHash.scala
Now my problem is that my code in Go returns -1
for password check.
package main
import (
"bytes"
"crypto/rand"
"crypto/sha512"
"fmt"
"golang.org/x/crypto/pbkdf2"
"math/big"
"strings"
)
func main() {
iteration := 25000
// Hash User input
password := []byte("123")
salt := "yCyQMMMBt1TuPa1F9FeKfT0yrNIF8tLB"
key := pbkdf2.Key(password, []byte(salt), iteration, sha512.Size, sha512.New)
// COMPARE PASSWORD fetched from DB
// 123 hash in scala
tokenS := strings.Split("$pbkdf2-sha512$25000$yCyQMMMBt1TuPa1F9FeKfT0yrNIF8tLB$TtQt5BZLs4qlA0YAkcGukZwu7pkxOLcxwuoQB3qNtxM", "$")
passwordHashInDatabase := tokenS[4]
out := bytes.Compare(key, []byte(passwordHashInDatabase))
fmt.Println("out: ", out)
}
You have a couple problems:
You're not base64 decoding the salt before passing it to pbkdf2.Key()
and you're not base64 decoding the key fetched from the database before comparing it to the result from pbkdf2.Key()
. Also note that the Scala implementation does some character replacement before/after base64 decoding/encoding. This too needs to be replicated in the Go implementation.
The createHash()
method in the Scala implementation has a dkLength
parameter which defaults to 32
. In the Go implementation, you're instead providing the result of sha512.Size
, which is 64
and does not match. I know that the default value was used because the value from the database is 32 bytes long.
Here's a hastily fixed implemnentation:
package main
import (
"bytes"
"crypto/sha512"
"encoding/base64"
"fmt"
"log"
"strings"
"golang.org/x/crypto/pbkdf2"
)
func b64Decode(s string) ([]byte, error) {
s = strings.ReplaceAll(s, ".", "+")
return base64.RawStdEncoding.DecodeString(s)
}
func main() {
iteration := 25000
// Hash User input
password := []byte("123")
salt, err := b64Decode("yCyQMMMBt1TuPa1F9FeKfT0yrNIF8tLB")
if err != nil {
log.Fatal("Failed to base64 decode the salt: %s", err)
}
key := pbkdf2.Key(password, salt, iteration, 32, sha512.New)
// COMPARE PASSWORD fetched from DB
// 123 hash in scala
tokens := strings.Split("$pbkdf2-sha512$25000$yCyQMMMBt1TuPa1F9FeKfT0yrNIF8tLB$TtQt5BZLs4qlA0YAkcGukZwu7pkxOLcxwuoQB3qNtxM", "$")
passwordHashInDatabase, err := b64Decode(tokens[4])
if err != nil {
log.Fatal("Failed to base64 decode password hash from the database: %s", err)
}
fmt.Printf("%x\n%x\n", key, passwordHashInDatabase)
fmt.Printf("%d\n%d\n", len(key), len(passwordHashInDatabase))
out := bytes.Compare(key, passwordHashInDatabase)
fmt.Println("out: ", out)
}
Output:
4ed42de4164bb38aa503460091c1ae919c2eee993138b731c2ea10077a8db713
4ed42de4164bb38aa503460091c1ae919c2eee993138b731c2ea10077a8db713
32
32
out: 0