blob: fccbaf787493ca7d1a6da426b2b6f5e8b5c396da [file] [log] [blame]
/* Copyright (c) 2023, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
package kyber
import (
"bufio"
"bytes"
"encoding/hex"
"flag"
"os"
"strings"
"testing"
"golang.org/x/crypto/sha3"
)
var testVectorsPath = flag.String("test-vectors", "../../../../crypto/kyber/kyber_tests.txt", "The path to the test vectors to use")
func TestVectors(t *testing.T) {
in, err := os.Open(*testVectorsPath)
if err != nil {
t.Error(err)
return
}
defer in.Close()
scanner := bufio.NewScanner(in)
var priv *PrivateKey
var encodedPublicKey *[PublicKeySize]byte
var ciphertext *[CiphertextSize]byte
sharedSecret := make([]byte, 32)
lineNo := 0
for scanner.Scan() {
lineNo++
line := scanner.Text()
parts := strings.Split(line, "=")
if len(parts) != 2 || strings.HasPrefix(line, "count ") {
continue
}
key := strings.TrimSpace(parts[0])
value, err := hex.DecodeString(strings.TrimSpace(parts[1]))
if err != nil {
t.Errorf("bad hex value on line %d: %q", lineNo, parts[1])
return
}
switch key {
case "generateEntropy":
priv, encodedPublicKey = NewPrivateKey((*[64]byte)(value))
case "encapEntropyPreHash":
hashedEntropy := sha3.Sum256(value)
ciphertext = priv.Encap(sharedSecret, &hashedEntropy)
decapSharedSecret := make([]byte, len(sharedSecret))
priv.Decap(decapSharedSecret, ciphertext)
if !bytes.Equal(sharedSecret, decapSharedSecret) {
t.Errorf("instance on line %d did not round trip", lineNo)
return
}
case "pk":
if !bytes.Equal(encodedPublicKey[:], value) {
t.Errorf("bad 'pk' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, encodedPublicKey)
return
}
case "sk":
encodedPrivateKey := priv.Marshal()
if !bytes.Equal(encodedPrivateKey[:], value) {
t.Errorf("bad 'sk' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, encodedPrivateKey)
return
}
case "ct":
if !bytes.Equal(ciphertext[:], value) {
t.Errorf("bad 'ct' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, ciphertext[:])
return
}
case "ss":
if !bytes.Equal(sharedSecret[:], value) {
t.Errorf("bad 'ss' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, sharedSecret[:])
return
}
}
}
}
func TestIteration(t *testing.T) {
h := sha3.NewShake256()
for i := 0; i < 4096; i++ {
var generateEntropy [64]byte
h.Read(generateEntropy[:])
var encapEntropy [32]byte
h.Read(encapEntropy[:])
priv, encodedPublicKey := NewPrivateKey(&generateEntropy)
h.Reset()
h.Write(encodedPublicKey[:])
encodedPrivateKey := priv.Marshal()
h.Write(encodedPrivateKey[:])
var sharedSecret [32]byte
ciphertext := priv.Encap(sharedSecret[:], &encapEntropy)
h.Write(ciphertext[:])
h.Write(sharedSecret[:])
var decapSharedSecret [32]byte
priv.Decap(decapSharedSecret[:], ciphertext)
if !bytes.Equal(decapSharedSecret[:], sharedSecret[:]) {
t.Errorf("Decap failed on iteration %d", i)
return
}
}
var result [16]byte
h.Read(result[:])
const expected = "18c6cd04eaebb33b20bb1e8e2762d30d"
if hex.EncodeToString(result[:]) != expected {
t.Errorf("iteration test produced %x, but should be %v", result, expected)
}
}