github.com/cloudflare/circl@v1.5.0/dh/sidh/sike_test.go (about)

     1  package sidh
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"crypto/rand"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"io"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/cloudflare/circl/dh/sidh/internal/common"
    15  	. "github.com/cloudflare/circl/internal/test"
    16  )
    17  
    18  type sikeVec struct {
    19  	id      uint8
    20  	name    string
    21  	kem     *KEM
    22  	KatFile string
    23  	PkB     string
    24  	PrB     string
    25  }
    26  
    27  var tdataSike = map[uint8]sikeVec{
    28  	Fp434: {
    29  		Fp434, "P-434", NewSike434(rand.Reader),
    30  		"testdata/PQCkemKAT_374.rsp",
    31  		"1BD0A2E81307B6F96461317DDF535ACC0E59C742627BAE60D27605E10FAF722D" +
    32  			"22A73E184CB572A12E79DCD58C6B54FB01442114CBE9010B6CAEC25D04C16C5E" +
    33  			"42540C1524C545B8C67614ED4183C9FA5BD0BE45A7F89FBC770EE8E7E5E391C7" +
    34  			"EE6F35F74C29E6D9E35B1663DA01E48E9DEB2347512D366FDE505161677055E3" +
    35  			"EF23054D276E817E2C57025DA1C10D2461F68617F2D11256EEE4E2D7DBDF6C8E" +
    36  			"34F3A0FD00C625428CB41857002159DAB94267ABE42D630C6AAA91AF837C7A67" +
    37  			"40754EA6634C45454C51B0BB4D44C3CCCCE4B32C00901CF69C008D013348379B" +
    38  			"2F9837F428A01B6173584691F2A6F3A3C4CF487D20D261B36C8CDB1BC158E2A5" +
    39  			"162A9DA4F7A97AA0879B9897E2B6891B672201F9AEFBF799C27B2587120AC586" +
    40  			"A511360926FB7DA8EBF5CB5272F396AE06608422BE9792E2CE9BEF21BF55B7EF" +
    41  			"F8DC7EC8C99910D3F800",
    42  		"4B622DE1350119C45A9F2E2EF3DC5DF56A27FCDFCDDAF58CD69B903752D68C20" +
    43  			"0934E160B234E49EDE247601",
    44  	},
    45  	Fp503: {
    46  		Fp503, "P-503", NewSike503(rand.Reader),
    47  		"testdata/PQCkemKAT_434.rsp",
    48  		"4032A90B6C036B7D2A83878AD116641AD319E420235A505F3F5C3DEC27C87A6C" +
    49  			"BA0792201D6E7B196C582D43CAF86CB2C7DEFA6598B543C946CDDF62EF9A328C" +
    50  			"8719B66BA5052231DAE13AF7D9CDEBB4ED327773C7AE0818F41AF1D28CD78B16" +
    51  			"C996232528235C8392B8FCFD925CB311B2A801B0402A90E527261EA32F2BEF67" +
    52  			"7C544908D5509B8AB7D7BF20456727AD358AD585306A0B28F6B2AA583CE8A3E0" +
    53  			"BB92D8CD55347D39D4E3C30D3D0F96EABB721A6968CDD143FE9227643CF697FB" +
    54  			"2DF0B71322B5EA1505D0DDBF70A2FD1193011F3BC18AA1E127C614B76969DCDA" +
    55  			"45A2072B519A1074FDA49F5C828450C6A007BF8D7CDDD5D2FC112119C679CA3A" +
    56  			"B16C6960B25F6C681A7DCED0F0E3901740D3DBF3A33011EB7DA460E8ADA80EE3" +
    57  			"45B2B71420950A9A803E4F11330EB91CCABB1EEE4D875A109D7724ABD201272C" +
    58  			"0B4981BDCDFA70F3430A89D2A88EEED474CF0CFAC65CE883F44B4722FA280C6F" +
    59  			"A9C4724D414B35AF69D6ECB21BFDA23BFF6B66C22C2451DC8E1C",
    60  		"7BF6938C975658AEB8B4D37CFFBDE25D97E561F36C219A0E8FE645816DBBC7ED7B57" +
    61  			"7700AE8DC3138E97A0C3F6F002065C92A0B1B8180208",
    62  	},
    63  	Fp751: {
    64  		Fp751, "P-751", NewSike751(rand.Reader),
    65  		"testdata/PQCkemKAT_644.rsp",
    66  		"E1A758EC0D418BFE86D8077B5BB169133C06C1F2A067D8B202D9D058FFC51F63" +
    67  			"FD26155A6577C74BA7F1A27E7BA51982517B923615DEB00BE408920A07831DF5" +
    68  			"978CFDDD0BF690A264353A4A16B666F90586D7F89A193CE09375D389C1379A7A" +
    69  			"528581C3ACB002CD2DC4F0FD672568FF9050BA8365C7FEFC5E6ED089B921DE68" +
    70  			"04091A0744DE3EB14D426A3F7DA215C50312617C1C2697243980D06056F2CCE8" +
    71  			"8AE7AE73C7343C0B7104C9F2870A94FED744CF6E94630514B6CEAB0E64733BB6" +
    72  			"FA67B931E5D8206010475CBE8BC587248D65D89D8CD9C8BBFA93E8B5F9EB9130" +
    73  			"773DED665D52ABBD91C4C8C255F73C0FC82501AE33330E9F308DE7177CBF83E4" +
    74  			"E26E334D7CB09019E638147FC58ED372AF660F14C194BC80E9666325C98E0F80" +
    75  			"877271D4A6BF514F603703D8A697874CD50A34D92F5AAEA84633CCF96801BD51" +
    76  			"7BF425DEE4A32AAF06684052473EA14643C3D535440FB2240A988D09F297C5A3" +
    77  			"88CB3DE60ED943F124034B90EFF611221F80F78EC124956338A105F6636B063D" +
    78  			"7E48BFBD5D614310FB97D86F122E4AE6F9DDF4977A93ED7D0CE2A94E346A1A03" +
    79  			"D3219CF21907B85A5BCDC713F93A4406A22E03B1655A66E1F6741A2F953E6FE0" +
    80  			"868B2614BABEF1943BBBCB1B66D3E7017E533EA84F291240B56AB33EF1DC3F3D" +
    81  			"E99DBF9E8BE51A0076E462BCDD825EA96D7F63C99177C305C257B31461F4C23D" +
    82  			"43115F0220409E8880BBB2468586D03461E807BE824B693874911B2B52AF06FD" +
    83  			"BDC47F5A0159729641A7C950AB9E03F2DC045135",
    84  		"0001020304050607080900010203040506070809000102030405060708090102" +
    85  			"8626ED79D451140800E03B59B956F8210E556067407D13DC90FA9E8B872BFB8F" +
    86  			"AB0A7289852106E40538D3575C500201",
    87  	},
    88  }
    89  
    90  // Encrypt, Decrypt, check if input/output plaintext is the same.
    91  func testPKERoundTrip(t *testing.T, v sikeVec) {
    92  	// Message to be encrypted
    93  	var pt [common.MaxMsgBsz]byte
    94  	params := common.Params(v.id)
    95  	ct := make([]byte, v.kem.CiphertextSize())
    96  	msg := make([]byte, params.MsgLen)
    97  	for i := range msg {
    98  		msg[i] = byte(i)
    99  	}
   100  
   101  	// Import keys
   102  	pkB := NewPublicKey(params.ID, KeyVariantSike)
   103  	skB := NewPrivateKey(params.ID, KeyVariantSike)
   104  	pkHex, err := hex.DecodeString(v.PkB)
   105  	CheckNoErr(t, err, "Test vector wrong")
   106  	skHex, err := hex.DecodeString(v.PrB)
   107  	CheckNoErr(t, err, "Test vector wrong")
   108  	err = pkB.Import(pkHex)
   109  	CheckNoErr(t, err, "Public key import failed")
   110  	err = skB.Import(skHex)
   111  	CheckNoErr(t, err, "Private key import failed")
   112  	err = v.kem.encrypt(ct, rand.Reader, pkB, msg[:])
   113  	CheckNoErr(t, err, "PKE roundtrip - encryption failed")
   114  	ptLen, err := v.kem.decrypt(pt[:], skB, ct)
   115  	CheckNoErr(t, err, "PKE roundtrip - description failed")
   116  
   117  	if !bytes.Equal(pt[:ptLen], msg[:]) {
   118  		t.Errorf("Decryption failed \n got : %X\n exp : %X", pt[:ptLen], msg)
   119  	}
   120  }
   121  
   122  // Generate key and check if can encrypt.
   123  func testPKEKeyGeneration(t *testing.T, v sikeVec) {
   124  	var err error
   125  	params := common.Params(v.id)
   126  	var pt [common.MaxMsgBsz]byte
   127  	msg := make([]byte, params.MsgLen)
   128  	ct := make([]byte, v.kem.CiphertextSize())
   129  	// static buffer to ensure no overrides
   130  	pk := NewPublicKey(v.id, KeyVariantSike)
   131  	sk := NewPrivateKey(v.id, KeyVariantSike)
   132  
   133  	for i := range msg {
   134  		msg[i] = byte(i)
   135  	}
   136  
   137  	err = sk.Generate(rand.Reader)
   138  	CheckNoErr(t, err, "PKE key generation")
   139  	sk.GeneratePublicKey(pk)
   140  
   141  	err = v.kem.encrypt(ct, rand.Reader, pk, msg[:])
   142  	CheckNoErr(t, err, "PKE encryption")
   143  	ptLen, err := v.kem.decrypt(pt[:], sk, ct)
   144  	CheckNoErr(t, err, "PKE key decryption")
   145  
   146  	if !bytes.Equal(pt[:ptLen], msg[:]) {
   147  		t.Fatalf("Decryption failed \n got : %X\n exp : %X", pt, msg)
   148  	}
   149  }
   150  
   151  func testNegativePKE(t *testing.T, v sikeVec) {
   152  	var err error
   153  	var msg [common.MaxMsgBsz]byte
   154  	ct := make([]byte, v.kem.CiphertextSize())
   155  	pk := NewPublicKey(v.id, KeyVariantSike)
   156  	sk := NewPrivateKey(v.id, KeyVariantSike)
   157  
   158  	// Generate key
   159  	err = sk.Generate(rand.Reader)
   160  	CheckNoErr(t, err, "key generation")
   161  	sk.GeneratePublicKey(pk)
   162  
   163  	// bytelen(msg) - 1
   164  	err = v.kem.encrypt(ct, rand.Reader, pk, msg[:v.kem.params.KemSize+8-1])
   165  	CheckIsErr(t, err, "PKE encryption doesn't fail")
   166  	for _, v := range ct {
   167  		if v != 0 {
   168  			t.Fatal("Returned ciphertext must be not changed")
   169  		}
   170  	}
   171  }
   172  
   173  func testKEMRoundTrip(t *testing.T, pkB, skB []byte, v sikeVec) {
   174  	// Import keys
   175  	var err error
   176  	var ssE [common.MaxSharedSecretBsz]byte
   177  	var ssD [common.MaxSharedSecretBsz]byte
   178  	pk := NewPublicKey(v.id, KeyVariantSike)
   179  	sk := NewPrivateKey(v.id, KeyVariantSike)
   180  	ct := make([]byte, v.kem.CiphertextSize())
   181  	ssBsz := v.kem.SharedSecretSize()
   182  
   183  	err = pk.Import(pkB)
   184  	CheckNoErr(t, err, "Public key import failed")
   185  	err = sk.Import(skB)
   186  	CheckNoErr(t, err, "Private key import failed")
   187  
   188  	v.kem.Reset()
   189  	err = v.kem.Encapsulate(ct, ssE[:], pk)
   190  	CheckNoErr(t, err, "Encapsulation failed")
   191  	v.kem.Reset()
   192  	err = v.kem.Decapsulate(ssD[:ssBsz], sk, pk, ct)
   193  	CheckNoErr(t, err, "Decapsulation failed")
   194  
   195  	if !bytes.Equal(ssE[:v.kem.SharedSecretSize()], ssD[:v.kem.SharedSecretSize()]) {
   196  		t.Errorf("Shared secrets from decapsulation and encapsulation differ [%s]", v.name)
   197  	}
   198  }
   199  
   200  func testKEMKeyGeneration(t *testing.T, v sikeVec) {
   201  	var ssE [common.MaxSharedSecretBsz]byte
   202  	var ssD [common.MaxSharedSecretBsz]byte
   203  	ct := make([]byte, v.kem.CiphertextSize())
   204  
   205  	sk := NewPrivateKey(v.id, KeyVariantSike)
   206  	pk := NewPublicKey(v.id, KeyVariantSike)
   207  	CheckNoErr(t, sk.Generate(rand.Reader), "error: key generation")
   208  	sk.GeneratePublicKey(pk)
   209  
   210  	// calculated shared secret
   211  	v.kem.Reset()
   212  	err := v.kem.Encapsulate(ct, ssE[:], pk)
   213  	CheckNoErr(t, err, "encapsulation failed")
   214  	v.kem.Reset()
   215  	err = v.kem.Decapsulate(ssD[:v.kem.SharedSecretSize()], sk, pk, ct)
   216  	CheckNoErr(t, err, "decapsulation failed")
   217  
   218  	if !bytes.Equal(ssE[:], ssD[:]) {
   219  		t.Fatalf("KEM failed \n encapsulated: %X\n decapsulated: %X", ssD[:], ssE[:])
   220  	}
   221  }
   222  
   223  func testNegativeKEM(t *testing.T, v sikeVec) {
   224  	var ssE [common.MaxSharedSecretBsz]byte
   225  	var ssD [common.MaxSharedSecretBsz]byte
   226  	var ssTmp [common.MaxSharedSecretBsz]byte
   227  	ct := make([]byte, v.kem.CiphertextSize())
   228  	ssBsz := v.kem.SharedSecretSize()
   229  
   230  	sk := NewPrivateKey(v.id, KeyVariantSike)
   231  	pk := NewPublicKey(v.id, KeyVariantSike)
   232  	CheckNoErr(t, sk.Generate(rand.Reader), "error: key generation")
   233  	sk.GeneratePublicKey(pk)
   234  
   235  	v.kem.Reset()
   236  	err := v.kem.Encapsulate(ct, ssE[:], pk)
   237  	CheckNoErr(t, err, "pre-requisite for a test failed")
   238  
   239  	// Try decapsulate too small ciphertext
   240  	v.kem.Reset()
   241  	CheckNoErr(
   242  		t,
   243  		CheckPanic(func() { _ = v.kem.Decapsulate(ssTmp[:ssBsz], sk, pk, ct[:len(ct)-2]) }),
   244  		"Decapsulation must panic if ciphertext is too small")
   245  
   246  	ctTmp := make([]byte, len(ct)+1)
   247  	// Try decapsulate too big ciphertext
   248  	v.kem.Reset()
   249  	CheckNoErr(
   250  		t,
   251  		CheckPanic(func() { _ = v.kem.Decapsulate(ssTmp[:ssBsz], sk, pk, ctTmp) }),
   252  		"Decapsulation must panic if ciphertext is too big")
   253  
   254  	// Change ciphertext
   255  	ct[0] = ct[0] - 1
   256  	v.kem.Reset()
   257  	err = v.kem.Decapsulate(ssD[:ssBsz], sk, pk, ct)
   258  	CheckNoErr(t, err, "decapsulation returns error when invalid ciphertext provided")
   259  
   260  	if bytes.Equal(ssE[:], ssD[:]) {
   261  		// no idea how this could ever happen, but it would be very bad
   262  		t.Error("critical error")
   263  	}
   264  
   265  	// Try encapsulating with SIDH key
   266  	pkSidh := NewPublicKey(v.id, KeyVariantSidhB)
   267  	prSidh := NewPrivateKey(v.id, KeyVariantSidhB)
   268  	v.kem.Reset()
   269  	CheckNoErr(
   270  		t,
   271  		CheckPanic(func() { _ = v.kem.Encapsulate(ct, ssE[:], pkSidh) }),
   272  		"encapsulation accepts SIDH public key")
   273  
   274  	// Try decapsulating with SIDH key
   275  	v.kem.Reset()
   276  	CheckNoErr(
   277  		t,
   278  		CheckPanic(func() { _ = v.kem.Decapsulate(ssD[:ssBsz], prSidh, pk, ct) }),
   279  		"encapsulation accepts SIDH public key")
   280  }
   281  
   282  // In case invalid ciphertext is provided, SIKE's decapsulation must
   283  // return same (but unpredictable) result for a given key.
   284  func testNegativeKEMSameWrongResult(t *testing.T, v sikeVec) {
   285  	var ssE [common.MaxSharedSecretBsz]byte
   286  	var ssD1 [common.MaxSharedSecretBsz]byte
   287  	var ssD2 [common.MaxSharedSecretBsz]byte
   288  	ct := make([]byte, v.kem.CiphertextSize())
   289  	ssBsz := v.kem.SharedSecretSize()
   290  
   291  	sk := NewPrivateKey(v.id, KeyVariantSike)
   292  	pk := NewPublicKey(v.id, KeyVariantSike)
   293  	CheckNoErr(t, sk.Generate(rand.Reader), "error: key generation")
   294  	sk.GeneratePublicKey(pk)
   295  
   296  	v.kem.Reset()
   297  	err := v.kem.Encapsulate(ct, ssE[:], pk)
   298  	CheckNoErr(t, err, "pre-requisite for a test failed")
   299  
   300  	// make ciphertext wrong
   301  	ct[0] = ct[0] - 1
   302  	v.kem.Reset()
   303  	err = v.kem.Decapsulate(ssD1[:ssBsz], sk, pk, ct)
   304  	CheckNoErr(t, err, "pre-requisite for a test failed")
   305  
   306  	// change secret keysecond decapsulation must be done with same, but imported private key
   307  	var expSk [common.MaxSikePrivateKeyBsz]byte
   308  	sk.Export(expSk[:])
   309  
   310  	// create new private key
   311  	sk = NewPrivateKey(v.id, KeyVariantSike)
   312  	CheckNoErr(t, sk.Import(expSk[:sk.Size()]), "import failed")
   313  
   314  	// try decapsulating again.
   315  	v.kem.Reset()
   316  	err = v.kem.Decapsulate(ssD2[:ssBsz], sk, pk, ct)
   317  	CheckNoErr(t, err, "pre-requisite for a test failed")
   318  
   319  	// ssD1 must be same as ssD2
   320  	if !bytes.Equal(ssD1[:], ssD2[:]) {
   321  		t.Error("decapsulation is insecure")
   322  	}
   323  
   324  	// ssD1 and ssD2 must be different than ssE
   325  	if bytes.Equal(ssE[:], ssD1[:]) || bytes.Equal(ssE[:], ssD2[:]) {
   326  		// this test requires that decapsulation returns wrong result
   327  		t.Errorf("test implementation error")
   328  	}
   329  }
   330  
   331  func testKAT(t *testing.T, v sikeVec) {
   332  	ssGot := make([]byte, v.kem.SharedSecretSize())
   333  	testDecapsulation := func(pk, sk, ct, ssExpected []byte) {
   334  		pubKey := NewPublicKey(v.id, KeyVariantSike)
   335  		prvKey := NewPrivateKey(v.id, KeyVariantSike)
   336  		if pubKey.Import(pk) != nil || prvKey.Import(sk) != nil {
   337  			panic("sike test: can't load KAT")
   338  		}
   339  
   340  		err := v.kem.Decapsulate(ssGot, prvKey, pubKey, ct)
   341  		CheckNoErr(t, err, "sike test: can't perform decapsulation KAT")
   342  		if !bytes.Equal(ssGot, ssExpected) {
   343  			t.Fatalf("KAT decapsulation failed\n")
   344  		}
   345  	}
   346  
   347  	readAndCheckLine := func(r *bufio.Reader) []byte {
   348  		// Read next line from buffer
   349  		line, isPrefix, err := r.ReadLine()
   350  		if err != nil || isPrefix {
   351  			panic("Wrong format of input file")
   352  		}
   353  
   354  		// Function expects that line is in format "KEY = HEX_VALUE". Get
   355  		// value, which should be a hex string
   356  		hexst := strings.Split(string(line), "=")[1]
   357  		hexst = strings.TrimSpace(hexst)
   358  		// Convert value to byte string
   359  		ret, err := hex.DecodeString(hexst)
   360  		if err != nil {
   361  			panic("Wrong format of input file")
   362  		}
   363  		return ret
   364  	}
   365  
   366  	testKeygen := func(pk, sk []byte) {
   367  		// Import provided private key
   368  		prvKey := NewPrivateKey(v.id, KeyVariantSike)
   369  		pubKey := NewPublicKey(v.id, KeyVariantSike)
   370  		pubKeyBytes := make([]byte, pubKey.Size())
   371  		CheckNoErr(t, prvKey.Import(sk), "Can't load KAT")
   372  
   373  		// Generate public key
   374  		prvKey.GeneratePublicKey(pubKey)
   375  		pubKey.Export(pubKeyBytes)
   376  		if !bytes.Equal(pubKeyBytes, pk) {
   377  			t.Errorf("Public key differ [%s]", v.name)
   378  		}
   379  	}
   380  
   381  	f, err := os.Open(v.KatFile)
   382  	if err != nil {
   383  		t.Fatal(err)
   384  	}
   385  
   386  	r := bufio.NewReader(f)
   387  	for {
   388  		line, isPrefix, err := r.ReadLine()
   389  		if err != nil || isPrefix {
   390  			if err == io.EOF {
   391  				break
   392  			} else {
   393  				t.Fatal(err)
   394  			}
   395  		}
   396  		if len(strings.TrimSpace(string(line))) == 0 || line[0] == '#' {
   397  			continue
   398  		}
   399  
   400  		// count
   401  		_ = strings.Split(string(line), "=")[1]
   402  		// seed
   403  		_ = readAndCheckLine(r)
   404  		// pk
   405  		pk := readAndCheckLine(r)
   406  		// sk (secret key in test vector is concatenation of
   407  		// MSG + SECRET_BOB_KEY + PUBLIC_BOB_KEY. We use only MSG+SECRET_BOB_KEY
   408  		sk := readAndCheckLine(r)
   409  		sk = sk[:v.kem.params.MsgLen+int(v.kem.params.B.SecretByteLen)]
   410  		// ct
   411  		ct := readAndCheckLine(r)
   412  		// ss
   413  		ss := readAndCheckLine(r)
   414  
   415  		testKeygen(pk, sk)
   416  		testDecapsulation(pk, sk, ct, ss)
   417  		testKEMRoundTrip(t, pk, sk, v)
   418  	}
   419  }
   420  
   421  // Interface to "testing"
   422  
   423  /* -------------------------------------------------------------------------
   424     Wrappers for 'testing' SIDH
   425     -------------------------------------------------------------------------*/
   426  
   427  func testSike(t *testing.T, m *map[uint8]sikeVec, f func(*testing.T, sikeVec)) {
   428  	for i := range *m {
   429  		v := (*m)[i]
   430  		t.Run(v.name, func(t *testing.T) { f(t, v) })
   431  	}
   432  }
   433  
   434  func TestPKERoundTrip(t *testing.T)     { testSike(t, &tdataSike, testPKERoundTrip) }
   435  func TestPKEKeyGeneration(t *testing.T) { testSike(t, &tdataSike, testPKEKeyGeneration) }
   436  func TestNegativePKE(t *testing.T)      { testSike(t, &tdataSike, testNegativePKE) }
   437  func TestKEMKeyGeneration(t *testing.T) { testSike(t, &tdataSike, testKEMKeyGeneration) }
   438  func TestNegativeKEM(t *testing.T)      { testSike(t, &tdataSike, testNegativeKEM) }
   439  func TestKAT(t *testing.T)              { testSike(t, &tdataSike, testKAT) }
   440  func TestNegativeKEMSameWrongResult(t *testing.T) {
   441  	testSike(t, &tdataSike, testNegativeKEMSameWrongResult)
   442  }
   443  
   444  func TestKEMRoundTrip(t *testing.T) {
   445  	for _, val := range tdataSike {
   446  		//		fmt.Printf("\tTesting: %s\n", val.name)
   447  		pk, err := hex.DecodeString(val.PkB)
   448  		CheckNoErr(t, err, "public key B not a number")
   449  		sk, err := hex.DecodeString(val.PrB)
   450  		CheckNoErr(t, err, "private key B not a number")
   451  		testKEMRoundTrip(t, pk, sk, val)
   452  	}
   453  }
   454  
   455  /* -------------------------------------------------------------------------
   456     Benchmarking
   457     -------------------------------------------------------------------------*/
   458  
   459  func benchSike(t *testing.B, m *map[uint8]sikeVec, f func(*testing.B, sikeVec)) {
   460  	for i := range *m {
   461  		v := (*m)[i]
   462  		t.Run(v.name, func(t *testing.B) { f(t, v) })
   463  	}
   464  }
   465  
   466  func benchKeygen(b *testing.B, v sikeVec) {
   467  	pub := NewPublicKey(v.id, KeyVariantSike)
   468  	prv := NewPrivateKey(v.id, KeyVariantSike)
   469  	_ = prv.Generate(rand.Reader)
   470  
   471  	b.ResetTimer()
   472  	for n := 0; n < b.N; n++ {
   473  		prv.GeneratePublicKey(pub)
   474  	}
   475  }
   476  
   477  func benchmarkEncaps(b *testing.B, v sikeVec) {
   478  	pub := NewPublicKey(v.id, KeyVariantSike)
   479  	prv := NewPrivateKey(v.id, KeyVariantSike)
   480  
   481  	if prv.Generate(rand.Reader) != nil {
   482  		b.FailNow()
   483  	}
   484  	prv.GeneratePublicKey(pub)
   485  
   486  	var ct [common.MaxCiphertextBsz]byte
   487  	var ss [common.MaxSharedSecretBsz]byte
   488  
   489  	b.ResetTimer()
   490  	for n := 0; n < b.N; n++ {
   491  		v.kem.Reset()
   492  		_ = v.kem.Encapsulate(ct[:], ss[:], pub)
   493  	}
   494  }
   495  
   496  func benchmarkDecaps(b *testing.B, v sikeVec) {
   497  	var ct [common.MaxCiphertextBsz]byte
   498  	var ss [common.MaxSharedSecretBsz]byte
   499  	ssBsz := v.kem.SharedSecretSize()
   500  
   501  	pkA := NewPublicKey(v.id, KeyVariantSike)
   502  	prvA := NewPrivateKey(v.id, KeyVariantSike)
   503  	pkB := NewPublicKey(v.id, KeyVariantSike)
   504  	prvB := NewPrivateKey(v.id, KeyVariantSike)
   505  
   506  	if prvA.Generate(rand.Reader) != nil || prvB.Generate(rand.Reader) != nil {
   507  		b.FailNow()
   508  	}
   509  
   510  	prvA.GeneratePublicKey(pkA)
   511  	prvB.GeneratePublicKey(pkB)
   512  
   513  	v.kem.Reset()
   514  	err := v.kem.Encapsulate(ct[:], ss[:], pkA)
   515  	if err != nil {
   516  		b.FailNow()
   517  	}
   518  
   519  	ctSlc := ct[:v.kem.CiphertextSize()]
   520  
   521  	b.ResetTimer()
   522  	for n := 0; n < b.N; n++ {
   523  		v.kem.Reset()
   524  		_ = v.kem.Decapsulate(ss[:ssBsz], prvA, pkB, ctSlc)
   525  	}
   526  }
   527  
   528  func BenchmarkKeygen(b *testing.B) { benchSike(b, &tdataSike, benchKeygen) }
   529  func BenchmarkEncaps(b *testing.B) { benchSike(b, &tdataSike, benchmarkEncaps) }
   530  func BenchmarkDecaps(b *testing.B) { benchSike(b, &tdataSike, benchmarkDecaps) }
   531  
   532  func ExampleKEM() {
   533  	// Alice's key pair
   534  	prvA := NewPrivateKey(Fp503, KeyVariantSike)
   535  	pubA := NewPublicKey(Fp503, KeyVariantSike)
   536  	// Bob's key pair
   537  	prvB := NewPrivateKey(Fp503, KeyVariantSike)
   538  	pubB := NewPublicKey(Fp503, KeyVariantSike)
   539  	// Generate keypair for Alice
   540  	err := prvA.Generate(rand.Reader)
   541  	if err != nil {
   542  		panic(err)
   543  	}
   544  	prvA.GeneratePublicKey(pubA)
   545  	// Generate keypair for Bob
   546  	err = prvB.Generate(rand.Reader)
   547  	if err != nil {
   548  		panic(err)
   549  	}
   550  	prvB.GeneratePublicKey(pubB)
   551  	// Initialize internal KEM structures
   552  	kem := NewSike503(rand.Reader)
   553  	// Create buffers for ciphertext, shared secret received
   554  	// from encapsulation and shared secret from decapsulation
   555  	ct := make([]byte, kem.CiphertextSize())
   556  	ssE := make([]byte, kem.SharedSecretSize())
   557  	ssD := make([]byte, kem.SharedSecretSize())
   558  	// Alice performs encapsulation with Bob's public key
   559  	err = kem.Encapsulate(ct, ssE, pubB)
   560  	if err != nil {
   561  		panic(err)
   562  	}
   563  	// Bob performs decapsulation with his key pair
   564  	err = kem.Decapsulate(ssD, prvB, pubB, ct)
   565  	if err != nil {
   566  		panic(err)
   567  	}
   568  	fmt.Printf("%t\n", bytes.Equal(ssE, ssD))
   569  
   570  	// Bob performs encapsulation with Alice's public key
   571  	err = kem.Encapsulate(ct, ssE, pubA)
   572  	if err != nil {
   573  		panic(err)
   574  	}
   575  	// Alice performs decapsulation with hers key pair
   576  	err = kem.Decapsulate(ssD, prvA, pubA, ct)
   577  	if err != nil {
   578  		panic(err)
   579  	}
   580  	fmt.Printf("%t\n", bytes.Equal(ssE, ssD))
   581  
   582  	// Output:
   583  	// true
   584  	// true
   585  }