40 lines
974 B
Go
40 lines
974 B
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/base64"
|
||
|
|
||
|
crypthash "github.com/sergeymakinen/go-crypt/hash"
|
||
|
"github.com/sergeymakinen/go-crypt/sha512"
|
||
|
)
|
||
|
|
||
|
// for some reason, no implementation of crypt's sha512 is clean enough :(
|
||
|
|
||
|
func sha512crypt(password, seed []byte) (string, error) {
|
||
|
// loose salt entropy because of character restriction in the salt
|
||
|
salt := []byte(base64.RawStdEncoding.EncodeToString(seed))[:sha512.MaxSaltLength]
|
||
|
// - base64 allows '+' where the salt accepts '.'
|
||
|
for i, c := range salt {
|
||
|
if c == '+' {
|
||
|
salt[i] = '.'
|
||
|
}
|
||
|
}
|
||
|
|
||
|
scheme := struct {
|
||
|
HashPrefix string
|
||
|
Rounds uint32 `hash:"param:rounds,omitempty"`
|
||
|
Salt []byte
|
||
|
Sum [86]byte
|
||
|
}{
|
||
|
HashPrefix: sha512.Prefix,
|
||
|
Rounds: sha512.DefaultRounds,
|
||
|
Salt: salt,
|
||
|
}
|
||
|
|
||
|
key, err := sha512.Key([]byte(password), scheme.Salt, scheme.Rounds)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
crypthash.LittleEndianEncoding.Encode(scheme.Sum[:], key)
|
||
|
return crypthash.Marshal(scheme)
|
||
|
}
|