package sm9

import (
	"math/big"

	"xdx.jelly/xgcl/gmath"
	"xdx.jelly/xgcl/internal/kdf"
	"xdx.jelly/xgcl/sm/sm3"
)

const (
	macSize    = sm3.Size
	macKeySize = sm3.Size
)

func mac(key, msg []byte) []byte {
	ret := sm3.Sum(msg, key)
	return ret[:]
}

// const hlen = 320 / 8

var Kdf = kdf.StdKdf.Kdf

// h are fixed TODO: make it change with params
func _h(out, n *big.Int, tag byte, z ...[]byte) {
	ha := make([]byte, 64)
	s0 := sm3.NewDigest()
	s1 := sm3.NewDigest()

	_, _ = s0.Write([]byte{tag})
	for _, w := range z {
		_, _ = s0.Write(w)
	}
	buf := make([]byte, 4)
	buf[3] = 1

	*s1 = *s0
	_, _ = s1.Write(buf)
	d := s1.Sum(nil)
	copy(ha, d)
	buf[3] = 2

	_, _ = s0.Write(buf)
	d = s0.Sum(nil)
	copy(ha[32:], d)

	out.SetBytes(ha[:40])
	out.Mod(out, n)
	out.Add(out, gmath.BigInt1)
}

// H1 H1函数
func H1(z ...[]byte) *big.Int {
	r := new(big.Int)
	_h(r, nMinusOne, 1, z...)
	return r
}

// H2 H2函数
func H2(z ...[]byte) *big.Int {
	r := new(big.Int)
	_h(r, nMinusOne, 2, z...)
	return r
}

// ////////////////////////////////////////////// local functions
// hashToG1 hash id to a point of G1, (px, py) are KGC's master key
// return (x,y) = H1(id||hid)g1 + BasePoint, BasePoint相当于做一个平移。
// 可以理解为id在某个KGC下的公钥
func hashToG1(id []byte, base *G1, hid byte) *G1 {
	h := H1(id, []byte{hid})
	g := new(G1).ScalarBaseMult(h)
	g.Add(g, base)
	return g
}

// genKey return a key of length keylen, key = kdf(cx||cy||e(p,q)^k||id)
// k could be nil, then e(p,q)^k=e(p,q)
// func genKey(key, id []byte, c, p *G1, q *G2, k *big.Int)[]byte{
func genKey(key, id []byte, c *G1, w *GT) []byte {
	_ = Kdf(key,
		c.Marshal(),
		w.Marshal(),
		id)
	return key
}
