diff options
author | Simon Beck <simon.beck@earthnet.ch> | 2022-02-08 17:59:59 +0100 |
---|---|---|
committer | Simon Beck <simon.beck@earthnet.ch> | 2022-02-10 20:51:01 +0100 |
commit | f05e41c9aad83f3d45aff620a739a116c32b4c47 (patch) | |
tree | 13c8de24260478e90419292ffd6c3035d1f95ee6 /ssha.go | |
parent | dbd900371466edfdc7bb7f09080c6698e4f8e647 (diff) | |
download | bottin-f05e41c9aad83f3d45aff620a739a116c32b4c47.tar.gz bottin-f05e41c9aad83f3d45aff620a739a116c32b4c47.zip |
Improve password hash handling
This adds support for more hash algorithms. Also a stored password will
be updated to SSHA512 upon a successful bind. It will also automatically
hash a cleartext password if the `userpassword` field is modified with
a cleartext one.
Hashes supported:
* SSHA
* SSHA256
* SSHA512
Diffstat (limited to 'ssha.go')
-rw-r--r-- | ssha.go | 78 |
1 files changed, 36 insertions, 42 deletions
@@ -1,59 +1,53 @@ package main import ( - "bytes" - "crypto/rand" - "crypto/sha1" - "encoding/base64" - "fmt" - "strings" - - log "github.com/sirupsen/logrus" + "errors" + + "github.com/jsimonetti/pwscheme/ssha" + "github.com/jsimonetti/pwscheme/ssha256" + "github.com/jsimonetti/pwscheme/ssha512" +) + +const ( + SSHA = "{SSHA}" + SSHA256 = "{SSHA256}" + SSHA512 = "{SSHA512}" ) -// Encode encodes the []byte of raw password -func SSHAEncode(rawPassPhrase []byte) string { - hash := makeSSHAHash(rawPassPhrase, makeSalt()) - b64 := base64.StdEncoding.EncodeToString(hash) - return fmt.Sprintf("{ssha}%s", b64) +// Encode encodes the string to ssha512 +func SSHAEncode(rawPassPhrase string) (string, error) { + return ssha512.Generate(rawPassPhrase, 16) } // Matches matches the encoded password and the raw password -func SSHAMatches(encodedPassPhrase string, rawPassPhrase []byte) bool { - if !strings.EqualFold(encodedPassPhrase[:6], "{ssha}") { - return false - } - - bhash, err := base64.StdEncoding.DecodeString(encodedPassPhrase[6:]) +func SSHAMatches(encodedPassPhrase string, rawPassPhrase string) (bool, error) { + hashType, err := determineHashType(encodedPassPhrase) if err != nil { - return false + return false, errors.New("invalid password hash stored") } - salt := bhash[20:] - - newssha := makeSSHAHash(rawPassPhrase, salt) - if bytes.Compare(newssha, bhash) != 0 { - return false + switch hashType { + case SSHA: + return ssha.Validate(rawPassPhrase, encodedPassPhrase) + case SSHA256: + return ssha256.Validate(rawPassPhrase, encodedPassPhrase) + case SSHA512: + return ssha512.Validate(rawPassPhrase, encodedPassPhrase) } - return true -} -// makeSalt make a 32 byte array containing random bytes. -func makeSalt() []byte { - sbytes := make([]byte, 32) - _, err := rand.Read(sbytes) - if err != nil { - log.Panicf("Could not read random bytes: %s", err) - } - return sbytes + return false, errors.New("no matching hash type found") } -// makeSSHAHash make hasing using SHA-1 with salt. This is not the final output though. You need to append {SSHA} string with base64 of this hash. -func makeSSHAHash(passphrase, salt []byte) []byte { - sha := sha1.New() - sha.Write(passphrase) - sha.Write(salt) +func determineHashType(hash string) (string, error) { + if len(hash) >= 7 && string(hash[0:6]) == SSHA { + return SSHA, nil + } + if len(hash) >= 10 && string(hash[0:9]) == SSHA256 { + return SSHA256, nil + } + if len(hash) >= 10 && string(hash[0:9]) == SSHA512 { + return SSHA512, nil + } - h := sha.Sum(nil) - return append(h, salt...) + return "", errors.New("no valid hash found") } |