diff options
Diffstat (limited to 'pwhash.go')
| -rw-r--r-- | pwhash.go | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/pwhash.go b/pwhash.go new file mode 100644 index 0000000..d05f6b5 --- /dev/null +++ b/pwhash.go @@ -0,0 +1,51 @@ +package sym + +import ( + "crypto/pbkdf2" + "crypto/sha256" + "fmt" + "os" + + "golang.org/x/term" +) + +const defaultPBKDF2Iters = 35_000_000 + +//go:generate go tool stringer -type=pwHash -linecomment +type pwHash int8 + +const ( + pwHashInvalid pwHash = iota + pwHashPBKDF2_HMAC_SHA256 // PBKDF2-HMAC-SHA256 +) + +type hashMetadata struct { + PasswordHashType pwHash + Iterations int32 + SaltSize int8 +} + +func (h *hashMetadata) validate() error { + if h.PasswordHashType != pwHashPBKDF2_HMAC_SHA256 { + return fmt.Errorf("invalid hash type %q", h.PasswordHashType) + } + if h.Iterations <= 0 || h.Iterations > defaultPBKDF2Iters { + return fmt.Errorf("too many iterations") + } + if h.SaltSize <= 0 || h.SaltSize > defaultSaltSize { + return fmt.Errorf("salt size too long") + } + return nil +} + +func (h *hashMetadata) hashPassword(password string, salt []byte) ([]byte, error) { + return pbkdf2.Key(sha256.New, password, salt, int(h.Iterations), 32) +} + +func termReadPassword() (string, error) { + pw, err := term.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + return "", err + } + return string(pw), nil +} |
