1
0
mirror of https://github.com/Luzifer/password.git synced 2024-09-19 18:32:57 +00:00
password/hasher/hasher.go
Knut Ahlers 6a76611a12
Implement JSON output with password hashes
Signed-off-by: Knut Ahlers <knut@ahlers.me>
2017-10-06 22:54:45 +02:00

95 lines
2.4 KiB
Go

package hasher
import (
"crypto"
"crypto/rand"
_ "crypto/sha1"
_ "crypto/sha256"
_ "crypto/sha512"
"fmt"
"math/big"
"golang.org/x/crypto/bcrypt"
"github.com/tredoe/osutil/user/crypt"
_ "github.com/tredoe/osutil/user/crypt/apr1_crypt"
_ "github.com/tredoe/osutil/user/crypt/sha256_crypt"
_ "github.com/tredoe/osutil/user/crypt/sha512_crypt"
)
type hasherFunc func(password string) (string, error)
var (
implementations = map[string]hasherFunc{
"htpasswd_apr1": implHTAPR1,
"htpasswd_bcrypt": implBcrypt,
"htpasswd_sha256": implHTSHA256,
"htpasswd_sha512": implHTSHA512,
"sha1": implSHA1,
"sha256": implSHA256,
"sha512": implSHA512,
}
saltSet = []byte(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./`)
saltSize = 12
)
func GetHashMap(password string) (map[string]string, error) {
result := map[string]string{}
for name, hf := range implementations {
h, err := hf(password)
if err != nil {
return nil, err
}
result[name] = h
}
return result, nil
}
func getSalt() ([]byte, error) {
salt := make([]byte, saltSize)
saltSetLength := big.NewInt(int64(len(saltSet)))
for i := 0; i < saltSize; i++ {
pos, err := rand.Int(rand.Reader, saltSetLength)
if err != nil {
return nil, err
}
salt[i] = saltSet[pos.Int64()]
}
return salt, nil
}
func implBcrypt(password string) (string, error) {
bc, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(bc), err
}
func genericHT(password, prefix string) (string, error) {
salt, err := getSalt()
if err != nil {
return "", err
}
return crypt.NewFromHash(prefix+string(salt)).Generate([]byte(password), append([]byte(prefix), salt...))
}
func implHTAPR1(password string) (string, error) { return genericHT(password, "$apr1$") }
func implHTSHA256(password string) (string, error) { return genericHT(password, "$5$") }
func implHTSHA512(password string) (string, error) { return genericHT(password, "$6$") }
func generic(password string, h crypto.Hash) (string, error) {
w := h.New()
w.Write([]byte(password))
return fmt.Sprintf("%x", w.Sum(nil)), nil
}
func implSHA1(password string) (string, error) { return generic(password, crypto.SHA1) }
func implSHA256(password string) (string, error) { return generic(password, crypto.SHA256) }
func implSHA512(password string) (string, error) { return generic(password, crypto.SHA512) }