Files
account-manager/crypto.go
2026-04-02 01:55:44 -04:00

72 lines
1.3 KiB
Go

package main
import (
"crypto/rand"
"crypto/subtle"
"encoding/base64"
"fmt"
"strings"
"golang.org/x/crypto/argon2"
)
const (
memory = 64 * 1024 // 64 MB
iterations = 3
parallelism = 2
saltLength = 16
keyLength = 32
)
func generateSalt() ([]byte, error) {
salt := make([]byte, saltLength)
_, err := rand.Read(salt)
return salt, err
}
func verifyPassword(password, encodedHash string) bool {
parts := strings.Split(encodedHash, "$")
params := parts[3]
salt := parts[4]
hash := parts[5]
var memory uint32
var iterations uint32
var parallelism uint8
fmt.Sscanf(params, "m=%d,t=%d,p=%d", &memory, &iterations, &parallelism)
saltBytes, _ := base64.RawStdEncoding.DecodeString(salt)
hashBytes, _ := base64.RawStdEncoding.DecodeString(hash)
comparisonHash := argon2.IDKey(
[]byte(password),
saltBytes,
iterations,
memory,
parallelism,
uint32(len(hashBytes)),
)
return subtle.ConstantTimeCompare(hashBytes, comparisonHash) == 1
}
func hashPassword(password string, salt []byte) string {
hash := argon2.IDKey(
[]byte(password),
salt,
iterations,
memory,
parallelism,
keyLength,
)
b64Salt := base64.RawStdEncoding.EncodeToString(salt)
b64Hash := base64.RawStdEncoding.EncodeToString(hash)
return fmt.Sprintf("$argon2id$v=19$m=%d,t=%d,p=%d$%s$%s",
memory, iterations, parallelism, b64Salt, b64Hash)
}