aboutsummaryrefslogtreecommitdiff
path: root/ssha.go
diff options
context:
space:
mode:
authorSimon Beck <simon.beck@earthnet.ch>2022-02-08 17:59:59 +0100
committerSimon Beck <simon.beck@earthnet.ch>2022-02-10 20:51:01 +0100
commitf05e41c9aad83f3d45aff620a739a116c32b4c47 (patch)
tree13c8de24260478e90419292ffd6c3035d1f95ee6 /ssha.go
parentdbd900371466edfdc7bb7f09080c6698e4f8e647 (diff)
downloadbottin-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.go78
1 files changed, 36 insertions, 42 deletions
diff --git a/ssha.go b/ssha.go
index 15b8e1d..202ce12 100644
--- a/ssha.go
+++ b/ssha.go
@@ -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")
}