goshort/internal/util/passwords/util.go
2023-08-26 11:47:46 -03:00

68 lines
1.4 KiB
Go

package passwords
import (
"crypto/subtle"
"fmt"
"strings"
randomutil "git.maronato.dev/maronato/goshort/internal/util/random"
)
func GenerateSalt(n int) []byte {
salt, err := randomutil.GenerateRandomBytes(n)
if err != nil {
panic(err)
}
return salt
}
func AreEqual(key1, key2 []byte) bool {
return subtle.ConstantTimeCompare(key1, key2) == 1
}
func EncodePasswordHash(algorithm, salt, hash string, params map[string]string) string {
// Create the param string
paramStrings := make([]string, len(params))
idx := 0
for key, value := range params {
paramStrings[idx] = key + "=" + value
idx++
}
paramString := strings.Join(paramStrings, ",")
// Return the encoded hash
return fmt.Sprintf("%s$%s$%s$%s", algorithm, paramString, salt, hash)
}
const (
hashlen = 4
kvpartlen = 2
)
func DecodePasswordHash(encodedHash string) (algorithm, salt, hash string, params map[string]string, err error) {
// Split the encoded hash into its parts
parts := strings.Split(encodedHash, "$")
if len(parts) != hashlen {
return "", "", "", nil, ErrInvalidHash
}
params = make(map[string]string)
paramsKV := strings.Split(parts[1], ",")
for _, kv := range paramsKV {
kvParts := strings.Split(kv, "=")
if len(kvParts) != kvpartlen {
return "", "", "", nil, ErrInvalidHash
}
params[kvParts[0]] = kvParts[1]
}
// Return the parts
return parts[0], parts[2], parts[3], params, nil
}