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 * SSHA512pull/14/head
parent
dbd9003714
commit
f05e41c9aa
@ -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") |
||||
} |
||||
|
Loading…
Reference in new issue