Peter Kurfer
9ea9a8f658
Some checks failed
Go build / build (push) Failing after 1m58s
- setup ent scheme - add command to create users - document API - add helpers to create migrations - add command to run migrations - add basic compose file
81 lines
1.8 KiB
Go
81 lines
1.8 KiB
Go
package services
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding"
|
|
"encoding/base64"
|
|
"errors"
|
|
)
|
|
|
|
var (
|
|
_ encoding.TextMarshaler = (*PasswordHash)(nil)
|
|
_ encoding.TextUnmarshaler = (*PasswordHash)(nil)
|
|
)
|
|
|
|
var ErrPasswordHashFormat = errors.New("invalid password hash format")
|
|
|
|
type hashParams interface {
|
|
Algorithm() string
|
|
encoding.TextMarshaler
|
|
encoding.TextUnmarshaler
|
|
}
|
|
|
|
type PasswordHash struct {
|
|
Hash []byte
|
|
Salt []byte
|
|
Params hashParams
|
|
}
|
|
|
|
func (p *PasswordHash) MarshalText() (text []byte, err error) {
|
|
buf := bytes.NewBuffer(make([]byte, 0, 256))
|
|
buf.WriteRune('$')
|
|
buf.WriteString(p.Params.Algorithm())
|
|
buf.WriteRune('$')
|
|
|
|
params, err := p.Params.MarshalText()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
buf.Write(params)
|
|
buf.WriteRune('$')
|
|
|
|
encodedSalt := make([]byte, base64.RawStdEncoding.EncodedLen(len(p.Salt)))
|
|
base64.RawStdEncoding.Encode(encodedSalt, p.Salt)
|
|
buf.Write(encodedSalt)
|
|
buf.WriteRune('$')
|
|
|
|
encodedCipherText := make([]byte, base64.RawStdEncoding.EncodedLen(len(p.Hash)))
|
|
base64.RawStdEncoding.Encode(encodedCipherText, p.Hash)
|
|
buf.Write(encodedCipherText)
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func (p *PasswordHash) UnmarshalText(text []byte) error {
|
|
split := bytes.Split(text, []byte("$"))
|
|
if len(split) < 6 {
|
|
return ErrPasswordHashFormat
|
|
}
|
|
|
|
p.Params = paramsForAlgorithm(string(split[1]))
|
|
|
|
if err := p.Params.UnmarshalText(split[len(split)-3]); err != nil {
|
|
return err
|
|
}
|
|
|
|
salt := split[len(split)-2]
|
|
|
|
p.Salt = make([]byte, base64.RawStdEncoding.DecodedLen(len(salt)))
|
|
if _, err := base64.RawStdEncoding.Decode(p.Salt, salt); err != nil {
|
|
return err
|
|
}
|
|
|
|
hash := split[len(split)-1]
|
|
p.Hash = make([]byte, base64.RawStdEncoding.DecodedLen(len(hash)))
|
|
if _, err := base64.RawStdEncoding.Decode(p.Hash, hash); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|