mirror of
https://github.com/thomiceli/opengist.git
synced 2024-12-22 20:42:40 +00:00
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/subtle"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"golang.org/x/crypto/argon2"
|
|
"strings"
|
|
)
|
|
|
|
type Argon2ID struct {
|
|
format string
|
|
version int
|
|
time uint32
|
|
memory uint32
|
|
keyLen uint32
|
|
saltLen uint32
|
|
threads uint8
|
|
}
|
|
|
|
var Argon2id = Argon2ID{
|
|
format: "$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
|
|
version: argon2.Version,
|
|
time: 1,
|
|
memory: 64 * 1024,
|
|
keyLen: 32,
|
|
saltLen: 16,
|
|
threads: 4,
|
|
}
|
|
|
|
func (a Argon2ID) Hash(plain string) (string, error) {
|
|
salt := make([]byte, a.saltLen)
|
|
if _, err := rand.Read(salt); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
hash := argon2.IDKey([]byte(plain), salt, a.time, a.memory, a.threads, a.keyLen)
|
|
|
|
return fmt.Sprintf(a.format, a.version, a.memory, a.time, a.threads,
|
|
base64.RawStdEncoding.EncodeToString(salt),
|
|
base64.RawStdEncoding.EncodeToString(hash),
|
|
), nil
|
|
}
|
|
|
|
func (a Argon2ID) Verify(plain, hash string) (bool, error) {
|
|
if hash == "" {
|
|
return false, nil
|
|
}
|
|
|
|
hashParts := strings.Split(hash, "$")
|
|
|
|
if len(hashParts) != 6 {
|
|
return false, errors.New("invalid hash")
|
|
}
|
|
|
|
_, err := fmt.Sscanf(hashParts[3], "m=%d,t=%d,p=%d", &a.memory, &a.time, &a.threads)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
salt, err := base64.RawStdEncoding.DecodeString(hashParts[4])
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
decodedHash, err := base64.RawStdEncoding.DecodeString(hashParts[5])
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
hashToCompare := argon2.IDKey([]byte(plain), salt, a.time, a.memory, a.threads, uint32(len(decodedHash)))
|
|
|
|
return subtle.ConstantTimeCompare(decodedHash, hashToCompare) == 1, nil
|
|
}
|