| // Copyright 2023 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package kyber | |
| import ( | |
| "bufio" | |
| "bytes" | |
| "crypto/sha3" | |
| "encoding/hex" | |
| "flag" | |
| "os" | |
| "strings" | |
| "testing" | |
| ) | |
| 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) | |
| } | |
| } |