1/* Copyright (c) 2023, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15package kyber 16 17import ( 18 "bufio" 19 "bytes" 20 "encoding/hex" 21 "golang.org/x/crypto/sha3" 22 "os" 23 "strings" 24 "testing" 25) 26 27func TestVectors(t *testing.T) { 28 in, err := os.Open("../../../../crypto/kyber/kyber_tests.txt") 29 if err != nil { 30 t.Error(err) 31 return 32 } 33 defer in.Close() 34 35 scanner := bufio.NewScanner(in) 36 var priv *PrivateKey 37 var encodedPublicKey *[PublicKeySize]byte 38 var ciphertext *[CiphertextSize]byte 39 sharedSecret := make([]byte, 32) 40 41 lineNo := 0 42 for scanner.Scan() { 43 lineNo++ 44 line := scanner.Text() 45 46 parts := strings.Split(line, "=") 47 if len(parts) != 2 || strings.HasPrefix(line, "count ") { 48 continue 49 } 50 key := strings.TrimSpace(parts[0]) 51 value, err := hex.DecodeString(strings.TrimSpace(parts[1])) 52 if err != nil { 53 t.Errorf("bad hex value on line %d: %q", lineNo, parts[1]) 54 return 55 } 56 57 switch key { 58 case "generateEntropy": 59 priv, encodedPublicKey = NewPrivateKey((*[64]byte)(value)) 60 case "encapEntropyPreHash": 61 hashedEntropy := sha3.Sum256(value) 62 ciphertext = priv.Encap(sharedSecret, &hashedEntropy) 63 decapSharedSecret := make([]byte, len(sharedSecret)) 64 priv.Decap(decapSharedSecret, ciphertext) 65 if !bytes.Equal(sharedSecret, decapSharedSecret) { 66 t.Errorf("instance on line %d did not round trip", lineNo) 67 return 68 } 69 case "pk": 70 if !bytes.Equal(encodedPublicKey[:], value) { 71 t.Errorf("bad 'pk' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, encodedPublicKey) 72 return 73 } 74 case "sk": 75 encodedPrivateKey := priv.Marshal() 76 if !bytes.Equal(encodedPrivateKey[:], value) { 77 t.Errorf("bad 'sk' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, encodedPrivateKey) 78 return 79 } 80 case "ct": 81 if !bytes.Equal(ciphertext[:], value) { 82 t.Errorf("bad 'ct' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, ciphertext[:]) 83 return 84 } 85 case "ss": 86 if !bytes.Equal(sharedSecret[:], value) { 87 t.Errorf("bad 'ss' value on line %d:\nwant: %x\ncalc: %x", lineNo, value, sharedSecret[:]) 88 return 89 } 90 } 91 } 92} 93 94func TestIteration(t *testing.T) { 95 h := sha3.NewShake256() 96 97 for i := 0; i < 4096; i++ { 98 var generateEntropy [64]byte 99 h.Read(generateEntropy[:]) 100 var encapEntropy [32]byte 101 h.Read(encapEntropy[:]) 102 103 priv, encodedPublicKey := NewPrivateKey(&generateEntropy) 104 h.Reset() 105 h.Write(encodedPublicKey[:]) 106 encodedPrivateKey := priv.Marshal() 107 h.Write(encodedPrivateKey[:]) 108 109 var sharedSecret [32]byte 110 ciphertext := priv.Encap(sharedSecret[:], &encapEntropy) 111 h.Write(ciphertext[:]) 112 h.Write(sharedSecret[:]) 113 114 var decapSharedSecret [32]byte 115 priv.Decap(decapSharedSecret[:], ciphertext) 116 if !bytes.Equal(decapSharedSecret[:], sharedSecret[:]) { 117 t.Errorf("Decap failed on iteration %d", i) 118 return 119 } 120 } 121 122 var result [16]byte 123 h.Read(result[:]) 124 const expected = "18c6cd04eaebb33b20bb1e8e2762d30d" 125 if hex.EncodeToString(result[:]) != expected { 126 t.Errorf("iteration test produced %x, but should be %v", result, expected) 127 } 128} 129