working on auth.
mailer, basic setup with html template and a dev treansport
This commit is contained in:
75
util/crypto/hash.go
Normal file
75
util/crypto/hash.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"log/slog"
|
||||
"math/big"
|
||||
|
||||
"gitserver.in/patialtech/rano/util/logger"
|
||||
"golang.org/x/crypto/argon2"
|
||||
)
|
||||
|
||||
func MD5(b []byte) string {
|
||||
hash := md5.Sum(b)
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
func MD5Int(b []byte) uint64 {
|
||||
n := new(big.Int)
|
||||
n.SetString(MD5(b), 16)
|
||||
return n.Uint64()
|
||||
}
|
||||
|
||||
// Password using Argon2id
|
||||
//
|
||||
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id
|
||||
func PasswordHash(pwd string) (hash, salt string, err error) {
|
||||
var sl []byte
|
||||
sl, err = randomSecret(32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Generate hash
|
||||
h := argon2.IDKey([]byte(pwd), sl, 3, 12288, 1, 32)
|
||||
|
||||
hash = base64.StdEncoding.EncodeToString(h)
|
||||
salt = base64.StdEncoding.EncodeToString(sl)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ComparePassword
|
||||
func ComparePasswordHash(pwd, hash, salt string) bool {
|
||||
var h, s []byte
|
||||
var err error
|
||||
|
||||
if h, err = base64.StdEncoding.DecodeString(hash); err != nil {
|
||||
logger.Error(err, slog.String("ref", "util/crypto.ComparePasswordHash decode hash"))
|
||||
}
|
||||
|
||||
if s, err = base64.StdEncoding.DecodeString(salt); err != nil {
|
||||
logger.Error(err, slog.String("ref", "util/crypto.ComparePasswordHash decode salt"))
|
||||
}
|
||||
|
||||
// Generate hash for comparison.
|
||||
ph := argon2.IDKey([]byte(pwd), s, 3, 12288, 1, 32)
|
||||
|
||||
// Compare the generated hash with the stored hash.
|
||||
// If they don't match return error.
|
||||
return bytes.Equal(h, ph)
|
||||
}
|
||||
|
||||
func randomSecret(length uint32) ([]byte, error) {
|
||||
secret := make([]byte, length)
|
||||
_, err := rand.Read(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return secret, nil
|
||||
}
|
22
util/crypto/hash_test.go
Normal file
22
util/crypto/hash_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package crypto
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestPasswordHash(t *testing.T) {
|
||||
pwd := "MY Bingo pwd"
|
||||
hash, salt, err := PasswordHash(pwd)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if hash == "" || salt == "" {
|
||||
t.Error("either hash or password is empty")
|
||||
return
|
||||
}
|
||||
|
||||
if !ComparePasswordHash(pwd, string(hash), string(salt)) {
|
||||
t.Error("supposed to match")
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user