82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
|
package passwd
|
||
|
|
||
|
import (
|
||
|
"crypto/hmac"
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/openwall/yescrypt-go"
|
||
|
"github.com/pedroalbanese/gogost/gost34112012256"
|
||
|
)
|
||
|
|
||
|
type GostYesCrypt struct {
|
||
|
Passwd
|
||
|
}
|
||
|
|
||
|
// Make an MD5Crypt password instance.
|
||
|
func NewGostYesCryptPasswd() PasswdInterface {
|
||
|
m := new(GostYesCrypt)
|
||
|
m.Magic = GOST_YES_CRYPT_MAGIC
|
||
|
m.SetSCryptParams(11, 31)
|
||
|
m.SaltLength = 22
|
||
|
// Set the interface to allow parents to call overriden functions.
|
||
|
m.i = m
|
||
|
return m
|
||
|
}
|
||
|
|
||
|
// Sets the SCrypt params using integers.
|
||
|
func (a *GostYesCrypt) SetSCryptParams(N, r int) (err error) {
|
||
|
Nval, err := IToA64(N)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
rval, err := IToA64(r)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
a.Params = fmt.Sprintf("j%c%c", Nval, rval)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Decode SCrypt params.
|
||
|
func (a *GostYesCrypt) DecodeSCriptParams() (N, r int) {
|
||
|
b64 := []byte(a.Params)
|
||
|
if len(b64) != 3 {
|
||
|
return
|
||
|
}
|
||
|
N = AToI64(b64[1])
|
||
|
r = AToI64(b64[2])
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Hash a password with salt using gost yes crypt standard.
|
||
|
func (a *GostYesCrypt) Hash(password []byte, salt []byte) (hash []byte, err error) {
|
||
|
output := []byte(fmt.Sprintf("%s%s$%s", YES_CRYPT_MAGIC, a.Params, salt))
|
||
|
yescryptHash, err := yescrypt.Hash(password, output)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
bytes := SCryptBase64Decode(yescryptHash[len(output)+1:])
|
||
|
|
||
|
h := gost34112012256.New()
|
||
|
h.Write(password)
|
||
|
hmacKey := h.Sum(nil)
|
||
|
|
||
|
settings := []byte(fmt.Sprintf("%s%s$%s", a.Magic, a.Params, salt))
|
||
|
hm := hmac.New(gost34112012256.New, hmacKey)
|
||
|
hm.Write(settings)
|
||
|
hmacKey = hm.Sum(nil)
|
||
|
hm = hmac.New(gost34112012256.New, hmacKey)
|
||
|
hm.Write(bytes)
|
||
|
b64 := SCryptBase64Encode(hm.Sum(nil))
|
||
|
|
||
|
hash = append(settings, '$')
|
||
|
hash = append(hash, b64...)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Override the passwd hash with salt function to hash with gost yes crypt.
|
||
|
func (a *GostYesCrypt) HashPasswordWithSalt(password []byte, salt []byte) (hash []byte, err error) {
|
||
|
hash, err = a.Hash(password, salt)
|
||
|
return
|
||
|
}
|