Added the ARGON2 algorithm.
parent
66556d188f
commit
e7886a26fb
@ -0,0 +1,22 @@
|
|||||||
|
package argon2
|
||||||
|
|
||||||
|
// Algorithm
|
||||||
|
type Algorithm struct {
|
||||||
|
keyLen uint32
|
||||||
|
memory uint32
|
||||||
|
saltLen uint32
|
||||||
|
threads uint8
|
||||||
|
time uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// New
|
||||||
|
func New(keyLen uint32, memory uint32, saltLen uint32, threads uint8, time uint32) Algorithm {
|
||||||
|
// Return Algorithm
|
||||||
|
return Algorithm{
|
||||||
|
keyLen: keyLen,
|
||||||
|
memory: memory,
|
||||||
|
saltLen: saltLen,
|
||||||
|
threads: threads,
|
||||||
|
time: time,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package argon2
|
||||||
|
|
||||||
|
import (
|
||||||
|
// Standard
|
||||||
|
"crypto/subtle"
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
// Standard Extended
|
||||||
|
"golang.org/x/crypto/argon2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check Hash
|
||||||
|
func (algorithm Algorithm) CheckHash(data []byte, hashToCheck string) (bool, error) {
|
||||||
|
// Hash Information
|
||||||
|
var version int
|
||||||
|
var memory uint32
|
||||||
|
var threads uint8
|
||||||
|
var time uint32
|
||||||
|
// Hash Parts
|
||||||
|
hashParts := strings.Split(hashToCheck, "$")
|
||||||
|
// Validate Hash Parts
|
||||||
|
if len(hashParts) != 6 {
|
||||||
|
return false, errors.New("the hash is invalid")
|
||||||
|
}
|
||||||
|
// Get Version
|
||||||
|
_, err := fmt.Sscanf(hashParts[2], "v=%d", &version)
|
||||||
|
// Handle Error
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// Validate Version
|
||||||
|
if version != argon2.Version {
|
||||||
|
return false, errors.New("incompatible version")
|
||||||
|
}
|
||||||
|
// Get Other Hash Information
|
||||||
|
_, err = fmt.Sscanf(hashParts[3], "m=%d,t=%d,p=%d", &memory, &time, &threads)
|
||||||
|
// Handle Error
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// Salt
|
||||||
|
salt, err := base64.RawStdEncoding.Strict().DecodeString(hashParts[4])
|
||||||
|
// Handle Error
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// Hash
|
||||||
|
hash, err := base64.RawStdEncoding.Strict().DecodeString(hashParts[5])
|
||||||
|
// Handle Error
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// Return Match
|
||||||
|
return subtle.ConstantTimeCompare(argon2.IDKey(data, salt, time, memory, threads, uint32(len(hash))), hash) == 1, err
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package argon2
|
||||||
|
|
||||||
|
import (
|
||||||
|
// Standard
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
// Standard Extended
|
||||||
|
"golang.org/x/crypto/argon2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hash
|
||||||
|
func (algorithm Algorithm) Hash(data []byte) (string, error) {
|
||||||
|
// Generate Salt
|
||||||
|
salt := make([]byte, algorithm.saltLen)
|
||||||
|
_, err := rand.Read(salt)
|
||||||
|
// Handle Error
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Hash
|
||||||
|
return fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", argon2.Version, algorithm.memory, algorithm.time, algorithm.threads, base64.RawStdEncoding.EncodeToString(salt), base64.RawStdEncoding.EncodeToString(argon2.IDKey(data, salt, algorithm.time, algorithm.memory, algorithm.threads, algorithm.keyLen))), err
|
||||||
|
}
|
Loading…
Reference in New Issue