htpasswd: implement sha256 and sha512 algorithms #2

Merged
amery merged 1 commits from pr-karasz-shas into master 1 year ago
  1. 88
      htpasswd/htpasswd.go
  2. 4
      htpasswd/htpasswd_test.go
  3. 8
      htpasswd/htpasswd_testdata

88
htpasswd/htpasswd.go

@ -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)
Review

default:?

`default:`?
}
@ -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))

4
htpasswd/htpasswd_test.go

@ -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 {

8
htpasswd/htpasswd_testdata

@ -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=

Loading…
Cancel
Save