| /* 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" |
| "golang.org/x/crypto/sha3" |
| "os" |
| "strings" |
| "testing" |
| ) |
| |
| func TestVectors(t *testing.T) { |
| in, err := os.Open("../../../../crypto/kyber/kyber_tests.txt") |
| 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) |
| } |
| } |