go-passwd/gost_yes_crypt.go
2024-09-07 18:53:27 -05:00

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
}