htpasswd: implement sha256 and sha512 algorithms
Signed-off-by: Nagy Károly Gábriel <k@jpi.io>
This commit is contained in:
@@ -5,6 +5,8 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -30,6 +32,10 @@ const (
|
||||
HashSHA HashAlgorithm = "sha"
|
||||
// HashSSHA Salted SHA
|
||||
HashSSHA HashAlgorithm = "ssha"
|
||||
// HashSHA256 256 variant of SHA
|
||||
HashSHA256 HashAlgorithm = "sha256"
|
||||
// HashSHA512 512 variant of SHA
|
||||
HashSHA512 HashAlgorithm = "sha512"
|
||||
)
|
||||
|
||||
// ParseHtpasswdFile parses a .htpasswd file
|
||||
@@ -174,6 +180,10 @@ func verifyPass(pass, hash string, alg HashAlgorithm) error {
|
||||
return verifySHA(pass, hash)
|
||||
case HashSSHA:
|
||||
return verifySSHA(pass, hash)
|
||||
case HashSHA256:
|
||||
return verifySHA256(pass, hash)
|
||||
case HashSHA512:
|
||||
return verifySHA512(pass, hash)
|
||||
}
|
||||
return fmt.Errorf("unsupported hash algorithm %v", alg)
|
||||
}
|
||||
@@ -235,6 +245,53 @@ func verifySSHA(password, hashedPassword string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifySHA256(password, hashedPassword string) error {
|
||||
eppS := hashedPassword[3:]
|
||||
hash, err := base64.StdEncoding.DecodeString(eppS)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot base64 decode")
|
||||
}
|
||||
|
||||
sha := sha256.New()
|
||||
_, err = sha.Write([]byte(password))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sum := sha.Sum(nil)
|
||||
|
||||
if !bytes.Equal(sum, hash) {
|
||||
return fmt.Errorf("wrong password")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifySHA512(password, hashedPassword string) error {
|
||||
eppS := hashedPassword[3:]
|
||||
hash, err := base64.StdEncoding.DecodeString(eppS)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot base64 decode")
|
||||
}
|
||||
|
||||
sha := sha512.New()
|
||||
_, err = sha.Write([]byte(password))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sum := sha.Sum(nil)
|
||||
|
||||
if !bytes.Equal(sum, hash) {
|
||||
return fmt.Errorf("wrong password")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pp Passwds) toByte() []byte {
|
||||
pass := []byte{}
|
||||
for name, hash := range pp {
|
||||
@@ -254,6 +311,10 @@ func identifyHash(h string) (HashAlgorithm, error) {
|
||||
return HashSHA, nil
|
||||
case strings.HasPrefix(h, "{SSHA}"):
|
||||
return HashSSHA, nil
|
||||
case strings.HasPrefix(h, "$5$"):
|
||||
return HashSHA256, nil
|
||||
case strings.HasPrefix(h, "$6$"):
|
||||
return HashSHA512, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unsupported hash algorithm")
|
||||
@@ -274,6 +335,12 @@ func createHash(passwd string, algo HashAlgorithm) (string, error) {
|
||||
case HashSSHA:
|
||||
prefix = "{SSHA}"
|
||||
hash, err = hashSSha(passwd)
|
||||
case HashSHA256:
|
||||
prefix = "$5$"
|
||||
hash, err = hashSha256(passwd)
|
||||
case HashSHA512:
|
||||
prefix = "$6$"
|
||||
hash, err = hashSha512(passwd)
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -303,6 +370,27 @@ func hashSha(passwd string) (string, error) {
|
||||
passwordSum := []byte(s.Sum(nil))
|
||||
return base64.StdEncoding.EncodeToString(passwordSum), nil
|
||||
}
|
||||
|
||||
func hashSha256(passwd string) (string, error) {
|
||||
s := sha256.New()
|
||||
_, err := s.Write([]byte(passwd))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
passwordSum := []byte(s.Sum(nil))
|
||||
return base64.StdEncoding.EncodeToString(passwordSum), nil
|
||||
}
|
||||
|
||||
func hashSha512(passwd string) (string, error) {
|
||||
s := sha512.New()
|
||||
_, err := s.Write([]byte(passwd))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
passwordSum := []byte(s.Sum(nil))
|
||||
return base64.StdEncoding.EncodeToString(passwordSum), nil
|
||||
}
|
||||
|
||||
func hashSSha(passwd string) (string, error) {
|
||||
s := sha1.New()
|
||||
_, err := s.Write([]byte(passwd))
|
||||
|
||||
@@ -33,6 +33,8 @@ func TestCreateUser(t *testing.T) {
|
||||
{"bcrypt", "123456@", HashBCrypt, nil},
|
||||
{"ssha", "123456@", HashSSHA, nil},
|
||||
{"sha", "123456@", HashSHA, nil},
|
||||
{"sha256", "123456@", HashSHA256, nil},
|
||||
{"sha512", "123456@", HashSHA512, nil},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@@ -62,6 +64,8 @@ func TestVerifyPassword(t *testing.T) {
|
||||
{"bcrypt", "123456@", nil},
|
||||
{"ssha", "123456@", nil},
|
||||
{"sha", "123456@", nil},
|
||||
{"sha256", "123456@", nil},
|
||||
{"sha512", "123456@", nil},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
bcrypt:$2a$10$9NdvqvFl9Yz9FM2D.i9Na.K1CiNF1ldk9hgRR57lYJiRBUnGt2THq
|
||||
ssha:{SSHA}7fPHbfKv92vC/IFhKdnEKSTBKubvta9a
|
||||
apr1:$apr1$v0FnbGJM$b2P3y1ltZYHakDaHrWx3N1
|
||||
bcrypt:$2a$10$pBSUext6NDsFYrm8GviW.OFe6SczH91INRC3YmsfE3HJp/fPmRaee
|
||||
ssha:{SSHA}LoTRQgCdeGIeJ3nxDQMCmQSWdnMEsLqj
|
||||
sha512:$6$78RjySv19bx/knbdL6q1cpoV8WblZwc3x+wmPGQUvrSycxc4liKbksvDr9HZj76hgRuZZCyEngP+WEJmePArCQ==
|
||||
sha:{SHA}YEn9/RmoXLdbyB9TEDJ0OqWoPy8=
|
||||
apr1:$apr1$U9.3kynN$MCKs53Oz35J0OYrSxfheW.
|
||||
sha256:$5$ufJ2S16IOhB6XLTGrVLqGQBKv/odjE3rypxnUDLqaS0=
|
||||
|
||||
Reference in New Issue
Block a user