package sm2m

import (
	"fmt"
	"testing"

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

func TestSign(t *testing.T) {

	rnd := make([]byte, 32)
	clientKey, clientTempKey, _ := ClientGenSignKey_one(nil)
	_, _ = grand.GenerateRandom(rnd)
	serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, rnd)
	err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
	if err != nil {
		t.Fatal("client's public key and server's public key are not equal.")
	}

	d := realPrivateKey(serverKey, clientKey)
	if !publicKey.Equals(&d.PublicKey) {
		t.Fatal("client's public key and server's public key are not equal.")
	}

	fmt.Println("clientKey:", clientKey)
	fmt.Println("serverKey:", serverKey)

	// c := NewClientSignContext(pk, grand.Reader)
	c := new(ClientSignContext)
	e := make([]byte, 32)
	out, err := c.Initial(e)
	if err != nil {
		t.Fatal(err)
	}
	fmt.Printf("clientData: %x\n", out)
	out, err = ServerSign(serverKey, out, grand.Reader)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("serverData: %x\n", out)
	sig, err := c.Final(clientKey, out)
	if err != nil {
		t.Fatal(err)
	}
	fmt.Println(sig)

	if !sm2.Verify(e, publicKey, sig) {
		t.Fatal("verify failed")
	}
}

func TestSignFuzz(t *testing.T) {

	rnd := make([]byte, 32)
	_, _ = grand.GenerateRandom(rnd)

	clientKey, clientTempKey, _ := ClientGenSignKey_one(rnd)
	_, _ = grand.GenerateRandom(rnd)
	serverKey, serverTempKey, publicKey, _ := ServerGenSignKey(clientTempKey, rnd)
	err := ClientGenSignKey_two(clientKey, serverTempKey, publicKey)
	if err != nil {
		t.Fatal("client's public key and server's public key are not equal.")
	}
	fmt.Println("clientKey:", clientKey)
	fmt.Println("serverKey:", serverKey)

	for i := 0; i < 10000000; i++ {
		// c := NewClientSignContext(pk, grand.Reader)
		c := new(ClientSignContext)
		e := make([]byte, 32)
		_, _ = grand.GenerateRandom(e)

		out, err := c.Initial(e)
		if err != nil {
			t.Fatal(err)
		}
		out, err = ServerSign(serverKey, out, grand.Reader)
		if err != nil {
			t.Fatal(err)
		}

		sig, err := c.Final(clientKey, out)
		if err != nil {
			t.Fatal(err)
		}

		if !sm2.Verify(e, publicKey, sig) {
			fmt.Printf("e=%x\n", e)
			t.Fatal("verify failed")
		}
		if i > 0 && i%1000 == 0 {
			fmt.Println(i, " pass")
		}
	}
}
