package sm2m

import (
	"crypto/rand"
	"io"
	"math/big"

	"xdx.jelly/xgcl/gerrors"
	"xdx.jelly/xgcl/gmath"
	"xdx.jelly/xgcl/sm/sm2"
)

// ClientGenAuthKey 生成客户端授权密钥
// dc' = dc * r
func ClientGenAuthKey(clientKey *sm2.PrivateKey, rnd io.Reader) (*sm2.PrivateKey, []byte, error) {
	var r *big.Int
	var err error
	for r == nil || gmath.IsBigInt0(r) {
		r, err = rand.Int(rnd, sm2.OrderN())
		if err != nil {
			return nil, nil, gerrors.WithAnnotating(ErrInvalidInput, "input rnd must be nil, []byte or io.Reader")
		}
	}

	authKey := sm2.NewPrivateKey()

	authKey.D.Mul(clientKey.D, r)
	authKey.D.Mod(authKey.D, sm2.OrderN())
	return authKey, gmath.BigIntToNByte(r, sm2.ByteSize()), nil
}

// ServerGenAuthKey 生成服务端授权密钥
// // ds' = ds / r
func ServerGenAuthKey(serverKey *sm2.PrivateKey, r []byte) (*sm2.PrivateKey, error) {
	bigR := new(big.Int).SetBytes(r)
	if gmath.IsBigInt0(bigR) || bigR.Cmp(sm2.OrderN()) >= 0 {
		return nil, gerrors.WithAnnotating(ErrInvalidInput, "input r is zero or bigger than order N")
	}
	bigR.ModInverse(bigR, sm2.OrderN())
	authKey := sm2.NewPrivateKey()
	authKey.D.Mul(serverKey.D, bigR)
	authKey.D.Mod(authKey.D, sm2.OrderN())
	return authKey, nil
}
