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