diff options
author | Gibheer <gibheer+git@zero-knowledge.org> | 2021-12-02 17:54:14 +0100 |
---|---|---|
committer | Gibheer <gibheer+git@zero-knowledge.org> | 2021-12-02 17:54:14 +0100 |
commit | fa05045d31c05c8928020f05f1d281901d983b2b (patch) | |
tree | 2ed3bac60302bfb14535a169f4b3e10d18fc6120 /cmd/monfront/pw.go | |
parent | 41d4805d584161ca16b8187194385e47c36422a6 (diff) |
cmd/monfront - import monfront from separate repository
This is the import from the separate monfront repository. The history
could not be imported, but this should suffice.
Diffstat (limited to 'cmd/monfront/pw.go')
-rw-r--r-- | cmd/monfront/pw.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/cmd/monfront/pw.go b/cmd/monfront/pw.go new file mode 100644 index 0000000..d06e9f2 --- /dev/null +++ b/cmd/monfront/pw.go @@ -0,0 +1,99 @@ +package main + +import ( + "bytes" + "crypto/rand" + "encoding/base64" + "fmt" + "strings" + + "golang.org/x/crypto/scrypt" +) + +type ( + pwHash struct { + salt []byte + hash []byte + } +) + +// Create a new password hash. +func newHash(pw string) (*pwHash, error) { + hash := pwHash{} + if err := hash.genSalt(); err != nil { + return nil, err + } + h, err := hash.Hash(pw) + if err != nil { + return nil, err + } + hash.hash = h + return &hash, nil +} + +// generate a hash for the given salt and password +func (p *pwHash) Hash(pw string) ([]byte, error) { + if len(p.salt) == 0 { + return []byte{}, fmt.Errorf("salt not initialized") + } + // constants taken from https://godoc.org/golang.org/x/crypto/scrypt + hash, err := scrypt.Key([]byte(pw), p.salt, 32768, 8, 1, 32) + if err != nil { + return []byte{}, fmt.Errorf("could not compute hash: %s", err) + } + return hash, nil +} + +// genSalt generates 8 bytes of salt. +func (p *pwHash) genSalt() error { + salt := make([]byte, 8) + _, err := rand.Read(salt) + p.salt = salt + return err +} + +// compare a hash to a password and return true, when it matches. +func (p *pwHash) compare(pw string) (bool, error) { + hash, err := p.Hash(pw) + if err != nil { + return false, fmt.Errorf("could not check password") + } + if bytes.Compare(p.hash, hash) == 0 { + return true, nil + } + return false, nil +} + +// Encode a hash and salt to a string. +func (p *pwHash) String() string { + return fmt.Sprintf( + "1$%s$%s", + base64.StdEncoding.EncodeToString(p.salt), + base64.StdEncoding.EncodeToString(p.hash), + ) +} + +// Parse a hash from a file or anywhere. +func (p *pwHash) Parse(raw string) error { + if len(raw) == 0 { + return fmt.Errorf("no hash found") + } + parts := strings.Split(raw, "$") + if len(parts) != 3 { + return fmt.Errorf("format error") + } + if parts[0] != "1" { + return fmt.Errorf("unknown hash version") + } + salt, err := base64.StdEncoding.DecodeString(parts[1]) + if err != nil { + return fmt.Errorf("could not parse salt: %s", err) + } + hash, err := base64.StdEncoding.DecodeString(parts[2]) + if err != nil { + return fmt.Errorf("could not parse salt: %s", err) + } + p.salt = salt + p.hash = hash + return nil +} |