func DeriveKeyHKDF(c Crypto, priv kyber.Scalar, info []byte) kyber.Scalar {
	hkdfR := hkdf.New(c.Hash, toBytes(priv), nil, info)
	return c.NewKeyFromReader(hkdfR)
}
DeriveKeyHKDF builds a key for the given parent key and info using
HKDF (RFC 5869). This function can be set as the CryptoStandard.KeyDeriver
field.
package gopaque
import (
	"bytes"
	"crypto/cipher"
	"fmt"
	"io"
	"golang.org/x/crypto/argon2"
	"crypto/aes"
	"crypto/hmac"
	"go.dedis.ch/kyber/v3"
	"go.dedis.ch/kyber/v3/sign/schnorr"
	"go.dedis.ch/kyber/v3/suites"
	"go.dedis.ch/kyber/v3/util/key"
	"go.dedis.ch/kyber/v3/util/random"
	"golang.org/x/crypto/hkdf"
)
var KyberSuiteDefault = suites.MustFind("Ed25519")
var CryptoDefault Crypto = CryptoStandardDefault
type Crypto interface {
	suites.Suite
	KeyGenerator
	PointHasher
	KeyDeriver
	AuthEncrypter
	Signer
}
type KeyGenerator interface {
	NewKey(stream cipher.Stream) kyber.Scalar
	NewKeyFromReader(r io.Reader) kyber.Scalar
}
type PointHasher interface {
	HashToPoint(msg []byte) kyber.Point
}
type KeyDeriver interface {
	DeriveKey(priv kyber.Scalar, info []byte) kyber.Scalar
}
type AuthEncrypter interface {
	AuthEncrypt(priv kyber.Scalar, plain []byte) ([]byte, error)
	AuthDecrypt(priv kyber.Scalar, enc []byte) ([]byte, error)
}
type Signer interface {
	Sign(priv kyber.Scalar, msg []byte) ([]byte, error)
	Verify(pub kyber.Point, msg, sig []byte) error
}
var CryptoStandardDefault = &CryptoStandard{
	Suite:      KyberSuiteDefault,
	KeyDeriver: DeriveKeyHKDF,
	Signer:     &SignerSchnorr{KyberSuiteDefault},
}
type CryptoStandard struct {
	suites.Suite
	KeyDeriver func(c Crypto, priv kyber.Scalar, info []byte) kyber.Scalar
	Signer
}
func (c *CryptoStandard) NewKey(stream cipher.Stream) kyber.Scalar {
	if stream == nil {
		stream = c.RandomStream()
	}
	if g, _ := c.Suite.(key.Generator); g != nil {
		return g.NewKey(stream)
	}
	return c.Scalar().Pick(stream)
}
func (c *CryptoStandard) NewKeyFromReader(r io.Reader) kyber.Scalar {
	if r == nil {
		return c.NewKey(nil)
	}
	return c.NewKey(random.New(r))
}
func (c *CryptoStandard) HashToPoint(msg []byte) kyber.Point {
	h := c.Hash()
	h.Write(msg)
	x := c.Scalar().SetBytes(h.Sum(nil))
	return c.Point().Mul(x, nil)
}
func (c *CryptoStandard) DeriveKey(priv kyber.Scalar, info []byte) kyber.Scalar {
	return c.KeyDeriver(c, priv, info)
}
func (c *CryptoStandard) AuthEncrypt(priv kyber.Scalar, plain []byte) ([]byte, error) {
	encKey, macKey := c.DeriveKey(priv, []byte("encKey")), c.DeriveKey(priv, []byte("macKey"))
	encBytes, err := c.aesCBCEncrypt(encKey, plain)
	if err != nil {
		return nil, err
	}
	mac := hmac.New(c.Hash, toBytes(macKey))
	mac.Write(encBytes)
	macBytes := mac.Sum(nil)
	return append(encBytes, macBytes...), nil
}
func (c *CryptoStandard) aesCBCEncrypt(priv kyber.Scalar, plain []byte) ([]byte, error) {
	padAmount := byte(aes.BlockSize - (len(plain) % aes.BlockSize))
	if padAmount == 0 {
		padAmount = aes.BlockSize
	}
	padded := make([]byte, len(plain)+int(padAmount))
	copy(padded, plain)
	for i := len(plain); i < len(padded); i++ {
		padded[i] = padAmount
	}
	keyBytes := toBytes(priv)
	if len(keyBytes) > 32 {
		keyBytes = keyBytes[:32]
	}
	block, err := aes.NewCipher(keyBytes[:32])
	if err != nil {
		return nil, err
	}
	enc := make([]byte, aes.BlockSize+len(padded))
	random.Bytes(enc[:aes.BlockSize], c.RandomStream())
	mode := cipher.NewCBCEncrypter(block, enc[:aes.BlockSize])
	mode.CryptBlocks(enc[aes.BlockSize:], padded)
	return enc, nil
}
func (c *CryptoStandard) AuthDecrypt(priv kyber.Scalar, enc []byte) ([]byte, error) {
	encKey, macKey := c.DeriveKey(priv, []byte("encKey")), c.DeriveKey(priv, []byte("macKey"))
	macSize := c.Hash().Size()
	encBytes, macBytes := enc[:len(enc)-macSize], enc[len(enc)-macSize:]
	mac := hmac.New(c.Hash, toBytes(macKey))
	mac.Write(encBytes)
	if !hmac.Equal(mac.Sum(nil), macBytes) {
		return nil, fmt.Errorf("MAC mismatch")
	}
	return c.aesCBCDecrypt(encKey, encBytes)
}
func (c *CryptoStandard) aesCBCDecrypt(priv kyber.Scalar, enc []byte) ([]byte, error) {
	if len(enc) < aes.BlockSize || len(enc)%aes.BlockSize != 0 {
		return nil, fmt.Errorf("Invalid enc size")
	}
	keyBytes := toBytes(priv)
	if len(keyBytes) > 32 {
		keyBytes = keyBytes[:32]
	}
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return nil, err
	}
	decPadded := make([]byte, len(enc[aes.BlockSize:]))
	mode := cipher.NewCBCDecrypter(block, enc[:aes.BlockSize])
	mode.CryptBlocks(decPadded, enc[aes.BlockSize:])
	padAmount := decPadded[len(decPadded)-1]
	if padAmount == 0 || padAmount > aes.BlockSize {
		return nil, fmt.Errorf("Pad validation fail")
	}
	for i := 1; i <= int(padAmount); i++ {
		if decPadded[len(decPadded)-i] != padAmount {
			return nil, fmt.Errorf("Pad validation fail")
		}
	}
	return decPadded[:len(decPadded)-int(padAmount)], nil
}