package sm2m

import (
	"testing"

	"xdx.jelly/xgcl/grand"
	"xdx.jelly/xgcl/sm/sm2"
)

func TestAuthKey(t *testing.T) {
	// Generate key
	clientKey, clientTempKey, err := ClientGenSignKey_one(grand.GetRandom(sm2.ByteSize()))
	if err != nil {
		t.Log()
		t.Fail()
		return
	}

	serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, grand.GetRandom(sm2.ByteSize()))
	if err != nil {
		t.Log()
		t.Fail()
		return
	}

	if err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey); err != nil {
		t.Log()
		t.Fail()
		return
	}
	t.Log("======= 协同密钥 =========")
	t.Logf("ClientKey=%v\nServerKey=%v\nPublicKey=%v", clientKey, serverKey, publicKey)

	d := realPrivateKey(clientKey, serverKey)
	t.Logf("Real private key: %v", d)
	t.Logf("Real public key: %v", sm2.GenPublicKey(d))

	t.Log("================ Signature Test==============")
	c := NewClientSignContext(publicKey, grand.Reader)
	e := grand.GetRandom(sm2.ByteSize())
	out, _ := c.Initial(e)
	out, _ = ServerSign(serverKey, out, grand.Reader)
	sig, _ := c.Final(clientKey, out)
	t.Logf("Signature: %v", sig)
	isValid := sm2.Verify(e, publicKey, sig)
	if !isValid {
		t.Log("verify success")
		t.Fail()
		return
	}
	t.Logf("verify = %v", isValid)

	t.Log("========== auth key ===========")
	clientAuthKey, randomFactor, err := ClientGenAuthKey(clientKey, grand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	serverAuthKey, err := ServerGenAuthKey(serverKey, randomFactor)
	if err != nil {
		t.Fatal(err)
	}
	ad := realPrivateKey(clientAuthKey, serverAuthKey)
	if ad.D.Cmp(d.D) != 0 {
		t.Log("auth key generate failed")
		t.Fail()
		return
	}
	t.Logf("Real auth private key: %v", ad)
	t.Logf("Real auth public key: %v", sm2.GenPublicKey(ad))
	t.Log("================ Signature Test (auth key)==============")
	c = NewClientSignContext(publicKey, grand.Reader)
	e = grand.GetRandom(sm2.ByteSize())
	out, _ = c.Initial(e)
	out, _ = ServerSign(serverAuthKey, out, grand.Reader)
	sig, _ = c.Final(clientAuthKey, out)
	t.Logf("Signature: %v", sig)
	isValid = sm2.Verify(e, publicKey, sig)
	if !isValid {
		t.Log("verify success")
		t.Fail()
		return
	}
	t.Logf("verify = %v", isValid)

}
