117 lines
2.6 KiB
Go
117 lines
2.6 KiB
Go
package passwd
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"crypto/sha512"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"math/rand"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var rnd *rand.Rand
|
|
|
|
const (
|
|
sha256Prefix = "sha256pwd"
|
|
sha512Prefix = "sha512pwd"
|
|
saltSize = 12
|
|
)
|
|
|
|
func init() {
|
|
src := rand.NewSource(time.Now().UnixNano())
|
|
rnd = rand.New(src)
|
|
}
|
|
|
|
func MakeSHA256Hash(passwd []byte) string {
|
|
var res string
|
|
salt := hex.EncodeToString(randomBytes(saltSize))
|
|
passwdString := hex.EncodeToString(passwd)
|
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
|
|
|
hasher := sha256.New()
|
|
hasher.Write([]byte(passwdString))
|
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
|
|
|
res = fmt.Sprintf("%s:%s:%s", sha256Prefix, salt, checksum)
|
|
return res
|
|
}
|
|
|
|
func MakeSHA512Hash(passwd []byte) string {
|
|
var res string
|
|
salt := hex.EncodeToString(randomBytes(saltSize))
|
|
passwdString := hex.EncodeToString(passwd)
|
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
|
|
|
hasher := sha512.New()
|
|
hasher.Write([]byte(passwdString))
|
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
|
|
|
res = fmt.Sprintf("%s:%s:%s", sha512Prefix, salt, checksum)
|
|
return res
|
|
}
|
|
|
|
func PasswordMatchCompat(passwd []byte, hash string) bool {
|
|
if strings.HasPrefix(hash, sha256Prefix) || strings.HasPrefix(hash, sha512Prefix) {
|
|
return PasswordMatch(passwd, hash)
|
|
}
|
|
if bytes.Equal(passwd, []byte(hash)) {
|
|
return true
|
|
}
|
|
return false
|
|
|
|
}
|
|
|
|
func PasswordMatch(passwd []byte, hash string) bool {
|
|
hashComponents := strings.Split(hash, ":")
|
|
if len(hashComponents) != 3 {
|
|
return false
|
|
}
|
|
method := hashComponents[0]
|
|
salt := hashComponents[1]
|
|
controlChecksum := hashComponents[2]
|
|
|
|
switch method {
|
|
case sha256Prefix:
|
|
passwdString := hex.EncodeToString(passwd)
|
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
|
hasher := sha256.New()
|
|
hasher.Write([]byte(passwdString))
|
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
|
if checksum != controlChecksum {
|
|
return false
|
|
}
|
|
case sha512Prefix:
|
|
passwdString := hex.EncodeToString(passwd)
|
|
passwdString = fmt.Sprintf("%s%s", passwdString, salt)
|
|
hasher := sha512.New()
|
|
hasher.Write([]byte(passwdString))
|
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
|
if checksum != controlChecksum {
|
|
return false
|
|
}
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func randomString(n int) string {
|
|
const letters = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
arr := make([]byte, n)
|
|
lettersArrayLen := len(letters)
|
|
for i := range arr {
|
|
arr[i] = letters[rnd.Intn(lettersArrayLen)]
|
|
}
|
|
return string(arr)
|
|
}
|
|
|
|
func randomBytes(n int) []byte {
|
|
arr := make([]byte, n)
|
|
for i := range arr {
|
|
arr[i] = byte(rnd.Intn(256) & 0xFF)
|
|
}
|
|
return arr
|
|
}
|