package sm2a

import (
	"bytes"
	"encoding/hex"
	"testing"

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

var signStdData = struct {
	e         string
	clientKey string
	serverKey string
	publicKey string
	sig       string
	k1        string
	k2        string
}{
	"5D1D20948D88FC76CF1AB994AFA484AF1603A61920D860635EABAA9D518848B0",
	"5F16B93817200830863BB55A523E131563C639880DA8D5F663C9CA32E872C621",
	"5749BD354348F66F9905254E784C97BDE700DB7968219829F2DB5EC80D0AB0DF",
	"C31ED61795626AA8D8D26BB17359160F3CCB63786D50DF2C350C9DD27539DBDA5C2D7FAE4D9360CC77F9C0F7E66DB80ED35CF9969E68A0496BE1120020A4396A",
	"B5E3ADF54DFAAB5E383BD01B1CDFBCAB93EFBA28D38BD0596ADE4BF2E14315E8EF337B8EAA38A82D2674ED1E6481B49DDDB556086938120C0C0EBE146C3CBEE8",
	"29D9F41BBE10C7A06064AFE3ADB5E23393FBA3981ADDBF146F87C7F7CA8645C6",
	"29D9F41BBE10C7A06064AFE3ADB5E23393FBA3981ADDBF146F87C7F7CA8645C6",
}

func SignStdTest() bool {
	dc := sm2.NewPrivateKey()
	dc.SetString(signStdData.clientKey, 16)
	ds := sm2.NewPrivateKey()
	ds.SetString(signStdData.serverKey, 16)
	// 协同计算签名
	e, _ := hex.DecodeString(signStdData.e)
	buf, _ := hex.DecodeString(signStdData.publicKey)
	pk := sm2.NewPublicKey()
	pk.SetBytes(buf)

	k1, _ := hex.DecodeString(signStdData.k1)
	clientSign := NewClientSignContext(pk, bytes.NewReader(k1))
	buf, _ = clientSign.Initial(e)
	k2, _ := hex.DecodeString(signStdData.k2)
	buf, _ = ServerSign(ds, pk, buf, bytes.NewReader(k2))
	sig, _ := clientSign.Final(dc, buf)

	buf, _ = hex.DecodeString(signStdData.sig)
	if !sm2.Verify(e, pk, sig) || bytes.Compare(sig.Bytes(), buf) != 0 {
		return false
	}
	return true
}

var decStdData = struct {
	msg       string
	clientKey string
	serverKey string
	publicKey string
	cipher    string
}{
	"1234567812345678",
	"A70B23314F7B21CD1C7A40F3FC7CA2DB2AC0481FD7E20F392805B6B96A0411F5",
	"D2DF651440C395E7B017CA5AA4B4DC5D9F482DAAEE86C973B57BA33D981E35A5",
	"CE33FE6C69EFE72ADC8135150F6F934D5CAB106B012CE8A63B4C97CFBB85E39086B1EA8943E79C46CBC5080D003255FF9A5E72D057563DA3417C5CB543B38D36",
	"1BE948BCF838D742398251CBDA2CD695F65CF001E8558BA8C9D6FAD716BA98572464D07B3C72FDAE759871E5E2582BD74913A7CEB68C3D8F96A60B97857B539525A814397F94CAC93A45D4F53E7B5AE49B2515E0921A2D6856A817D40B5303173481981EC6E3C17F90CBD296B54AD092",
}

func decTest() bool {
	dc := sm2.NewPrivateKey()
	dc.SetString(decStdData.clientKey, 16)
	ds := sm2.NewPrivateKey()
	ds.SetString(decStdData.serverKey, 16)
	buf, _ := hex.DecodeString(decStdData.publicKey)
	pk := sm2.NewPublicKey()
	pk.SetBytes(buf)

	cipher := sm2.NewCipher()
	buf, _ = hex.DecodeString(decStdData.cipher)
	cipher.SetBytes(buf)
	clientDecCtx := NewClientDecContext()
	buf, _ = clientDecCtx.Decrypt_one(cipher)
	buf, _ = ServerDecrypt(buf, ds)
	plain, _ := clientDecCtx.Decrypt_two(buf, dc)
	if string(plain) != decStdData.msg {
		return false
	}
	return true

}

var ExchangeStdData = struct {
	sponsorClientKey   string
	sponsorServerKey   string
	sponsorPubKey      string
	responsorClientKey string
	responsorServerKey string
	responsorPubKey    string
	k1                 string
	k2                 string
	key                string
}{
	"F51259452B6AA06628413B6B3AD1BDB73999385D649BEA82D294BA24187B9EDE",
	"1027D73961109348B3178E4F037ADEA699076768ED18BF4727DA37C79A1AAF95",
	"3F371664CF68ABB6DCF99D5286E4DA85848A2D2B1C7A5EF40EAD8890028101229EA360323FD4E591D6920D423CB4AC9AC4977F95830149B34A11F0FE8AB4924C",
	"4BAC27CF1C30006AF721879A4C8C68D8EF75B11FC485C1431BB2EA0D61131B36",
	"25A87003DDC27BCF631EF747035B75466157D4AF0C9ACDA1FE523963FFA39757",
	"A5768900DD340CE2689A19A99791226F6DD696D627BF86620B5D682AE0FB0729B0C2728839E2CE5724E84F805D12E5F3B42C8BFAF312B8210063AEDA0B17D3EA",
	"37441408A82D69DBCFC11D9B4D1E477D879B22D1CC159F1BD957CCD1CE727F47",
	"165216E57689D8B400C434BA96D097CBB04ABAD4067B71D4EEAEBC645B93FBBC",
	"5C4E57CD8179D829A315AB6CC7110BF5",
}

func exchangeStdTest() bool {
	sponsorClientKey := sm2.NewPrivateKey()
	sponsorClientKey.SetString(ExchangeStdData.sponsorClientKey, 16)
	sponsorServerKey := sm2.NewPrivateKey()
	sponsorServerKey.SetString(ExchangeStdData.sponsorServerKey, 16)
	sponsorPublicKey := sm2.NewPublicKey()
	buf, _ := hex.DecodeString(ExchangeStdData.sponsorPubKey)
	sponsorPublicKey.SetBytes(buf)

	responsorClientKey := sm2.NewPrivateKey()
	responsorClientKey.SetString(ExchangeStdData.responsorClientKey, 16)
	responsorServerKey := sm2.NewPrivateKey()
	responsorServerKey.SetString(ExchangeStdData.responsorServerKey, 16)
	responsorPublicKey := sm2.NewPublicKey()
	buf, _ = hex.DecodeString(ExchangeStdData.responsorPubKey)
	responsorPublicKey.SetBytes(buf)

	sponsor := []byte("alice")
	responsor := []byte("bob")
	keyLength := 16

	cs := NewClientSponsor(sponsor, sponsorClientKey, sponsorPublicKey)
	cr := NewClientResponsor(responsor, responsorClientKey, responsorPublicKey)
	k1, _ := hex.DecodeString(ExchangeStdData.k1)
	k2, _ := hex.DecodeString(ExchangeStdData.k2)
	tempKeyOfSponsor, err := cs.GenerateAgreementData(k1)
	if err != nil {
		return false

	}
	toServer, err := cr.GenerateAgreementDataAndKey_1of2(sponsorPublicKey, tempKeyOfSponsor)
	if err != nil {
		return false

	}
	toClient, err := ServerKeyExchange(toServer, responsorServerKey)
	if err != nil {
		return false

	}
	keyOfResponsor, tempKeyOfResponsor, err := cr.GenerateAgreementDataAndKey_2of2(keyLength, sponsor, sponsorPublicKey, toClient, k2)
	if err != nil {
		return false

	}
	toServer, err = cs.GenerateKey_1of2(responsorPublicKey, tempKeyOfResponsor)
	if err != nil {
		return false

	}
	toClient, err = ServerKeyExchange(toServer, sponsorServerKey)
	if err != nil {
		return false

	}
	keyOfSponsor, err := cs.GenerateKey_2of2(keyLength, responsor, toClient, responsorPublicKey, sponsorClientKey)
	if err != nil {
		return false

	}
	key, _ := hex.DecodeString(ExchangeStdData.key)
	if bytes.Compare(keyOfResponsor, keyOfSponsor) != 0 || bytes.Compare(keyOfResponsor, key) != 0 {
		return false
	}
	return true
}

func TestSignStd(t *testing.T) {
	if !SignStdTest() {
		t.Fatal("测试失败")
	}

	if !exchangeStdTest() {
		t.Fatal("测试失败")
	}

	if !decTest() {
		t.Fatal("测试失败")
	}
}
