diff --git a/crypto/curve25519/x25519_test.cc b/crypto/curve25519/x25519_test.cc index 3e0a27e7..2b50891f 100644 --- a/crypto/curve25519/x25519_test.cc +++ b/crypto/curve25519/x25519_test.cc @@ -21,6 +21,7 @@ #include #include "../internal.h" +#include "../test/file_test.h" #include "../test/test_util.h" @@ -124,3 +125,25 @@ TEST(X25519Test, DISABLED_IteratedLarge) { EXPECT_EQ(Bytes(kExpected), Bytes(scalar)); } + +TEST(X25519Test, Wycheproof) { + FileTestGTest("third_party/wycheproof/x25519_test.txt", [](FileTest *t) { + t->IgnoreInstruction("curve"); + t->IgnoreAttribute("curve"); + + // Our implementation tolerates the Wycheproof "acceptable" + // inputs. Wycheproof's valid vs. acceptable criteria does not match our + // X25519 return value, so we test only the overall output. + t->IgnoreAttribute("result"); + + std::vector priv, pub, shared; + ASSERT_TRUE(t->GetBytes(&priv, "private")); + ASSERT_TRUE(t->GetBytes(&pub, "public")); + ASSERT_TRUE(t->GetBytes(&shared, "shared")); + ASSERT_EQ(32u, priv.size()); + ASSERT_EQ(32u, pub.size()); + uint8_t secret[32]; + X25519(secret, priv.data(), pub.data()); + EXPECT_EQ(Bytes(secret), Bytes(shared)); + }); +} diff --git a/crypto/test/file_test.h b/crypto/test/file_test.h index 002b350f..a164e99a 100644 --- a/crypto/test/file_test.h +++ b/crypto/test/file_test.h @@ -154,6 +154,9 @@ class FileTest { // missing. It should only be used after a |HasAttribute| call. const std::string &GetAttributeOrDie(const std::string &key); + // IgnoreAttribute marks the attribute with key |key| as used. + void IgnoreAttribute(const std::string &key) { HasAttribute(key); } + // GetBytes looks up the attribute with key |key| and decodes it as a byte // string. On success, it writes the result to |*out| and returns // true. Otherwise it returns false with an error to |stderr|. The value may @@ -173,6 +176,9 @@ class FileTest { // HasInstruction returns true if the current test has an instruction. bool HasInstruction(const std::string &key); + // IgnoreInstruction marks the instruction with key |key| as used. + void IgnoreInstruction(const std::string &key) { HasInstruction(key); } + // GetInstruction looks up the instruction with key |key|. It sets // |*out_value| to the value (empty string if the instruction has no value) // and returns true if it exists and returns false with an error to |stderr| diff --git a/sources.cmake b/sources.cmake index ee0f9e69..d2fea88b 100644 --- a/sources.cmake +++ b/sources.cmake @@ -59,4 +59,5 @@ set( crypto/x509/some_names1.pem crypto/x509/some_names2.pem crypto/x509/some_names3.pem + third_party/wycheproof/x25519_test.txt ) diff --git a/third_party/wycheproof/convert_wycheproof.go b/third_party/wycheproof/convert_wycheproof.go new file mode 100644 index 00000000..312a4177 --- /dev/null +++ b/third_party/wycheproof/convert_wycheproof.go @@ -0,0 +1,255 @@ +/* Copyright (c) 2018, 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. */ + +// convert_wycheproof.go converts Wycheproof test vectors into a format more +// easily consumed by BoringSSL. +package main + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "sort" + "strings" +) + +type wycheproofTest struct { + Algorithm string `json:"algorithm"` + GeneratorVersion string `json:"generatorVersion"` + NumberOfTests int `json:"numberOfTests"` + Notes map[string]string `json:"notes"` + Header []string `json:"header"` + // encoding/json does not support collecting unused keys, so we leave + // everything past this point as generic. + TestGroups []map[string]interface{} `json:"testGroups"` +} + +func sortedKeys(m map[string]interface{}) []string { + keys := make([]string, 0, len(m)) + for k, _ := range m { + keys = append(keys, k) + } + sort.Strings(keys) + return keys +} + +func printAttribute(w io.Writer, key string, valueI interface{}, isInstruction bool) error { + switch value := valueI.(type) { + case float64: + if float64(int(value)) != value { + panic(key + "was not an integer.") + } + if isInstruction { + if _, err := fmt.Fprintf(w, "[%s = %d]\n", key, int(value)); err != nil { + return err + } + } else { + if _, err := fmt.Fprintf(w, "%s = %d\n", key, int(value)); err != nil { + return err + } + } + case string: + if strings.Contains(value, "\n") { + panic(key + " contained a newline.") + } + if isInstruction { + if _, err := fmt.Fprintf(w, "[%s = %s]\n", key, value); err != nil { + return err + } + } else { + if _, err := fmt.Fprintf(w, "%s = %s\n", key, value); err != nil { + return err + } + } + case map[string]interface{}: + for _, k := range sortedKeys(value) { + if err := printAttribute(w, key+"."+k, value[k], isInstruction); err != nil { + return err + } + } + default: + panic(fmt.Sprintf("Unknown type for %q: %T", key, valueI)) + } + return nil +} + +func printComment(w io.Writer, in string) error { + const width = 80 - 2 + lines := strings.Split(in, "\n") + for _, line := range lines { + for { + if len(line) <= width { + if _, err := fmt.Fprintf(w, "# %s\n", line); err != nil { + return err + } + break + } + + // Find the last space we can break at. + n := strings.LastIndexByte(line[:width+1], ' ') + if n < 0 { + // The next word is too long. Wrap as soon as that word ends. + n = strings.IndexByte(line[width+1:], ' ') + if n < 0 { + // This was the last word. + if _, err := fmt.Fprintf(w, "# %s\n", line); err != nil { + return nil + } + break + } + n += width + 1 + } + if _, err := fmt.Fprintf(w, "# %s\n", line[:n]); err != nil { + return err + } + line = line[n+1:] // Ignore the space. + } + } + return nil +} + +func isSupportedCurve(curve string) bool { + switch curve { + case "brainpoolP224r1", "brainpoolP224t1", "brainpoolP256r1", "brainpoolP256t1", "brainpoolP320r1", "brainpoolP320t1", "brainpoolP384r1", "brainpoolP384t1", "brainpoolP512r1", "brainpoolP512t1", "secp256k1": + return false + case "edwards25519", "curve25519", "secp224r1", "secp256r1", "secp384r1", "secp521r1": + return true + default: + panic("Unknown curve: " + curve) + } +} + +func convertWycheproof(jsonPath, txtPath string) error { + jsonData, err := ioutil.ReadFile(jsonPath) + if err != nil { + return err + } + + var w wycheproofTest + if err := json.Unmarshal(jsonData, &w); err != nil { + return err + } + + f, err := os.OpenFile(txtPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + return err + } + defer f.Close() + if _, err := fmt.Fprintf(f, `# Imported from Wycheproof's %s. +# This file is generated by convert_wycheproof.go. Do not edit by hand. +# +# Algorithm: %s +# Generator version: %s + +`, jsonPath, w.Algorithm, w.GeneratorVersion); err != nil { + return err + } + + for _, group := range w.TestGroups { + // Skip tests with unsupported curves. We filter these out at + // conversion time to avoid unnecessarily inflating + // crypto_test_data.cc. + if curve, ok := group["curve"]; ok && !isSupportedCurve(curve.(string)) { + continue + } + if keyI, ok := group["key"]; ok { + if key, ok := keyI.(map[string]interface{}); ok { + if curve, ok := key["curve"]; ok && !isSupportedCurve(curve.(string)) { + continue + } + } + } + + for _, k := range sortedKeys(group) { + // Wycheproof files always include both keyPem and + // keyDer. Skip keyPem as they contain newlines. We + // process keyDer more easily. + if k == "type" || k == "tests" || k == "keyPem" { + continue + } + if err := printAttribute(f, k, group[k], true); err != nil { + return err + } + } + fmt.Fprintf(f, "\n") + tests := group["tests"].([]interface{}) + for _, testI := range tests { + test := testI.(map[string]interface{}) + // Skip tests with unsupported curves. + if curve, ok := test["curve"]; ok && !isSupportedCurve(curve.(string)) { + continue + } + if comment, ok := test["comment"]; ok { + if err := printComment(f, comment.(string)); err != nil { + return err + } + } + for _, k := range sortedKeys(test) { + if k == "comment" || k == "flags" || k == "tcId" { + continue + } + if err := printAttribute(f, k, test[k], false); err != nil { + return err + } + } + if flags, ok := test["flags"]; ok { + for _, flag := range flags.([]interface{}) { + if note, ok := w.Notes[flag.(string)]; ok { + if err := printComment(f, note); err != nil { + return err + } + } + } + } + if _, err := fmt.Fprintf(f, "\n"); err != nil { + return err + } + } + } + return nil +} + +func main() { + jsonPaths := []string{ + "x25519_test.json", + + // TODO(davidben): The following tests still need test drivers. + // "aes_cbc_pkcs5_test.json", + // "aes_gcm_siv_test.json", + // "aes_gcm_test.json", + // "chacha20_poly1305_test.json", + // "dsa_test.json", + // "ecdh_test.json", + // "ecdsa_secp224r1_sha224_test.json", + // "ecdsa_secp224r1_sha256_test.json", + // "ecdsa_secp256r1_sha256_test.json", + // "ecdsa_secp384r1_sha384_test.json", + // "ecdsa_secp384r1_sha512_test.json", + // "ecdsa_secp521r1_sha512_test.json", + // "eddsa_test.json", + // "rsa_signature_test.json", + } + for _, jsonPath := range jsonPaths { + if !strings.HasSuffix(jsonPath, ".json") { + panic(jsonPath) + } + txtPath := jsonPath[:len(jsonPath)-len(".json")] + ".txt" + if err := convertWycheproof(jsonPath, txtPath); err != nil { + fmt.Fprintf(os.Stderr, "Error converting %s: %s\n", jsonPath, err) + os.Exit(1) + } + } +} diff --git a/third_party/wycheproof/x25519_test.txt b/third_party/wycheproof/x25519_test.txt new file mode 100644 index 00000000..d474128c --- /dev/null +++ b/third_party/wycheproof/x25519_test.txt @@ -0,0 +1,532 @@ +# Imported from Wycheproof's x25519_test.json. +# This file is generated by convert_wycheproof.go. Do not edit by hand. +# +# Algorithm: X25519 +# Generator version: 0.4 + +[curve = curve25519] + +# normal case +curve = curve25519 +private = 4852834d9d6b77dadeabaaf2e11dca66d19fe74993a7bec36c6e16a0983feaba +public = 9c647d9ae589b9f58fdc3ca4947efbc915c4b2e08e744a0edf469dac59c8f85a +result = valid +shared = 87b7f212b627f7a54ca5e0bcdaddd5389d9de6156cdbcf8ebe14ffbcfb436551 + +# public key on twist +curve = curve25519 +private = 588c061a50804ac488ad774ac716c3f5ba714b2712e048491379a500211998a8 +public = 63aa40c6e38346c5caf23a6df0a5e6c80889a08647e551b3563449befcfc9733 +result = acceptable +shared = b1a707519495ffffb298ff941716b06dfab87cf8d91123fe2be9a233dda22212 +# Public keys are either points on curve25519 or points on its twist. +# Implementations may either reject such keys or compute X25519 using the twist. +# If a point multiplication is performed then it is important that the result is +# correct, since otherwise attacks with invalid keys are possible. + +# public key on twist +curve = curve25519 +private = b05bfd32e55325d9fd648cb302848039000b390e44d521e58aab3b29a6960ba8 +public = 0f83c36fded9d32fadf4efa3ae93a90bb5cfa66893bc412c43fa7287dbb99779 +result = acceptable +shared = 67dd4a6e165533534c0e3f172e4ab8576bca923a5f07b2c069b4c310ff2e935b +# Public keys are either points on curve25519 or points on its twist. +# Implementations may either reject such keys or compute X25519 using the twist. +# If a point multiplication is performed then it is important that the result is +# correct, since otherwise attacks with invalid keys are possible. + +# public key on twist +curve = curve25519 +private = 70e34bcbe1f47fbc0fddfd7c1e1aa53d57bfe0f66d243067b424bb6210bed19c +public = 0b8211a2b6049097f6871c6c052d3c5fc1ba17da9e32ae458403b05bb283092a +result = acceptable +shared = 4a0638cfaa9ef1933b47f8939296a6b25be541ef7f70e844c0bcc00b134de64a +# Public keys are either points on curve25519 or points on its twist. +# Implementations may either reject such keys or compute X25519 using the twist. +# If a point multiplication is performed then it is important that the result is +# correct, since otherwise attacks with invalid keys are possible. + +# public key on twist +curve = curve25519 +private = 68c1f3a653a4cdb1d37bba94738f8b957a57beb24d646e994dc29a276aad458d +public = 343ac20a3b9c6a27b1008176509ad30735856ec1c8d8fcae13912d08d152f46c +result = acceptable +shared = 399491fce8dfab73b4f9f611de8ea0b27b28f85994250b0f475d585d042ac207 +# Public keys are either points on curve25519 or points on its twist. +# Implementations may either reject such keys or compute X25519 using the twist. +# If a point multiplication is performed then it is important that the result is +# correct, since otherwise attacks with invalid keys are possible. + +# public key on twist +curve = curve25519 +private = d877b26d06dff9d9f7fd4c5b3769f8cdd5b30516a5ab806be324ff3eb69ea0b2 +public = fa695fc7be8d1be5bf704898f388c452bafdd3b8eae805f8681a8d15c2d4e142 +result = acceptable +shared = 2c4fe11d490a53861776b13b4354abd4cf5a97699db6e6c68c1626d07662f758 +# Public keys are either points on curve25519 or points on its twist. +# Implementations may either reject such keys or compute X25519 using the twist. +# If a point multiplication is performed then it is important that the result is +# correct, since otherwise attacks with invalid keys are possible. + +# public key = 0 +curve = curve25519 +private = 207494038f2bb811d47805bcdf04a2ac585ada7f2f23389bfd4658f9ddd4debc +public = 0000000000000000000000000000000000000000000000000000000000000000 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key = 1 +curve = curve25519 +private = 202e8972b61c7e61930eb9450b5070eae1c670475685541f0476217e4818cfab +public = 0100000000000000000000000000000000000000000000000000000000000000 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# edge case on twist +curve = curve25519 +private = 38dde9f3e7b799045f9ac3793d4a9277dadeadc41bec0290f81f744f73775f84 +public = 0200000000000000000000000000000000000000000000000000000000000000 +result = acceptable +shared = 9a2cfe84ff9c4a9739625cae4a3b82a906877a441946f8d7b3d795fe8f5d1639 + +# edge case on twist +curve = curve25519 +private = 9857a914e3c29036fd9a442ba526b5cdcdf28216153e636c10677acab6bd6aa5 +public = 0300000000000000000000000000000000000000000000000000000000000000 +result = acceptable +shared = 4da4e0aa072c232ee2f0fa4e519ae50b52c1edd08a534d4ef346c2e106d21d60 + +# edge case on twist +curve = curve25519 +private = 48e2130d723305ed05e6e5894d398a5e33367a8c6aac8fcdf0a88e4b42820db7 +public = ffffff030000f8ffff1f0000c0ffffff000000feffff070000f0ffff3f000000 +result = acceptable +shared = 9ed10c53747f647f82f45125d3de15a1e6b824496ab40410ffcc3cfe95760f3b + +# edge case on twist +curve = curve25519 +private = 28f41011691851b3a62b641553b30d0dfddcb8fffcf53700a7be2f6a872e9fb0 +public = 000000fcffff070000e0ffff3f000000ffffff010000f8ffff0f0000c0ffff7f +result = acceptable +shared = cf72b4aa6aa1c9f894f4165b86109aa468517648e1f0cc70e1ab08460176506b + +# edge case on twist +curve = curve25519 +private = 18a93b6499b9f6b3225ca02fef410e0adec23532321d2d8ef1a6d602a8c65b83 +public = 00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffff7f +result = acceptable +shared = 5d50b62836bb69579410386cf7bb811c14bf85b1c7b17e5924c7ffea91ef9e12 + +# edge case on twist +curve = curve25519 +private = c01d1305a1338a1fcac2ba7e2e032b427e0b04903165aca957d8d0553d8717b0 +public = eaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = 19230eb148d5d67c3c22ab1daeff80a57eae4265ce2872657b2c8099fc698e50 + +# edge case for public key +curve = curve25519 +private = 386f7f16c50731d64f82e6a170b142a4e34f31fd7768fcb8902925e7d1e21abe +public = 0400000000000000000000000000000000000000000000000000000000000000 +result = valid +shared = 0fcab5d842a078d7a71fc59b57bfb4ca0be6873b49dcdb9f44e14ae8fbdfa542 + +# edge case for public key +curve = curve25519 +private = e023a289bd5e90fa2804ddc019a05ef3e79d434bb6ea2f522ecb643a75296e95 +public = ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000 +result = valid +shared = 54ce8f2275c077e3b1306a3939c5e03eef6bbb88060544758d9fef59b0bc3e4f + +# edge case for public key +curve = curve25519 +private = 68f010d62ee8d926053a361c3a75c6ea4ebdc8606ab285003a6f8f4076b01e83 +public = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03 +result = valid +shared = f136775c5beb0af8110af10b20372332043cab752419678775a223df57c9d30d + +# edge case for public key +curve = curve25519 +private = 58ebcb35b0f8845caf1ec630f96576b62c4b7b6c36b29deb2cb0084651755c96 +public = fffffffbfffffbffffdfffffdffffffffefffffefffff7fffff7ffffbfffff3f +result = valid +shared = bf9affd06b844085586460962ef2146ff3d4533d9444aab006eb88cc3054407d + +# edge case for public key +curve = curve25519 +private = 188c4bc5b9c44b38bb658b9b2ae82d5b01015e093184b17cb7863503a783e1bb +public = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f +result = valid +shared = d480de04f699cb3be0684a9cc2e31281ea0bc5a9dcc157d3d20158d46ca5246d + +# edge case for public key +curve = curve25519 +private = e06c11bb2e13ce3dc7673f67f5482242909423a9ae95ee986a988d98faee23a2 +public = fffffffffeffff7ffffffffffeffff7ffffffffffeffff7ffffffffffeffff7f +result = valid +shared = 4c4401cce6b51e4cb18f2790246c9bf914db667750a1cb89069092af07292276 + +# edge case for public key +curve = curve25519 +private = c0658c46dde18129293877535b1162b6f9f5414a23cf4d2cbc140a4d99da2b8f +public = ebffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = valid +shared = 578ba8cc2dbdc575afcf9df2b3ee6189f5337d6854c79b4ce165ea12293b3a0f + +# public key with low order +curve = curve25519 +private = 10255c9230a97a30a458ca284a629669293a31890cda9d147febc7d1e22d6bb1 +public = e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 78f1e8edf14481b389448dac8f59c70b038e7cf92ef2c7eff57a72466e115296 +public = 5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = a0a05a3e8f9f44204d5f8059a94ac7dfc39a49ac016dd743dbfa43c5d671fd88 +public = ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = d0dbb3ed1906663f15420af31f4eaf6509d9a9949723500605ad7c1c6e7450a9 +public = edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = c0b1d0eb22b244fe3291140072cdd9d989b5f0ecd96c100feb5bca241c1d9f8f +public = eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 480bf45f594942a8bc0f3353c6e8b8853d77f351f1c2ca6c2d1abf8a00b4229c +public = 0000000000000000000000000000000000000000000000000000000000000080 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 30f993fcf8514fc89bd8db14cd43ba0d4b2530e73c4276a05e1b145d420cedb4 +public = 0100000000000000000000000000000000000000000000000000000000000080 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = c04974b758380e2a5b5df6eb09bb2f6b3434f982722a8e676d3da251d1b3de83 +public = e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 502a31373db32446842fe5add3e024022ea54f274182afc3d9f1bb3d39534eb5 +public = 5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 90fa6417b0e37030fd6e43eff2abaef14c6793117a039cf621318ba90f4e98be +public = ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 78ad3f26027f1c9fdd975a1613b947779bad2cf2b741ade01840885a30bb979c +public = edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key with low order +curve = curve25519 +private = 98e23de7b1e0926ed9c87e7b14baf55f497a1d7096f93977680e44dc1c7b7b8b +public = eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000000 + +# public key >= p +curve = curve25519 +private = f01e48dafac9d7bcf589cbc382c878d18bda3550589ffb5d50b523bebe329dae +public = efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = bd36a0790eb883098c988b21786773de0b3a4df162282cf110de18dd484ce74b + +# public key >= p +curve = curve25519 +private = 288796bc5aff4b81a37501757bc0753a3c21964790d38699308debc17a6eaf8d +public = f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = b4e0dd76da7b071728b61f856771aa356e57eda78a5b1655cc3820fb5f854c5c + +# public key >= p +curve = curve25519 +private = 98df845f6651bf1138221f119041f72b6dbc3c4ace7143d99fd55ad867480da8 +public = f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = 6fdf6c37611dbd5304dc0f2eb7c9517eb3c50e12fd050ac6dec27071d4bfc034 + +# public key >= p +curve = curve25519 +private = f09498e46f02f878829e78b803d316a2ed695d0498a08abdf8276930e24edcb0 +public = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +result = acceptable +shared = 4c8fc4b1c6ab88fb21f18f6d4c810240d4e94651ba44f7a2c863cec7dc56602d + +# public key >= p +curve = curve25519 +private = 1813c10a5c7f21f96e17f288c0cc37607c04c5f5aea2db134f9e2ffc66bd9db8 +public = 0200000000000000000000000000000000000000000000000000000000000080 +result = acceptable +shared = 1cd0b28267dc541c642d6d7dca44a8b38a63736eef5c4e6501ffbbb1780c033c + +# public key >= p +curve = curve25519 +private = 7857fb808653645a0beb138a64f5f4d733a45ea84c3cda11a9c06f7e7139149e +public = 0300000000000000000000000000000000000000000000000000000000000080 +result = acceptable +shared = 8755be01c60a7e825cff3e0e78cb3aa4333861516aa59b1c51a8b2a543dfa822 + +# public key >= p +curve = curve25519 +private = e03aa842e2abc56e81e87b8b9f417b2a1e5913c723eed28d752f8d47a59f498f +public = 0400000000000000000000000000000000000000000000000000000000000080 +result = acceptable +shared = 54c9a1ed95e546d27822a360931dda60a1df049da6f904253c0612bbdc087476 + +# public key >= p +curve = curve25519 +private = f8f707b7999b18cb0d6b96124f2045972ca274bfc154ad0c87038c24c6d0d4b2 +public = daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = cc1f40d743cdc2230e1043daba8b75e810f1fbab7f255269bd9ebb29e6bf494f + +# public key >= p +curve = curve25519 +private = a034f684fa631e1a348118c1ce4c98231f2d9eec9ba5365b4a05d69a785b0796 +public = dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 54998ee43a5b007bf499f078e736524400a8b5c7e9b9b43771748c7cdf880412 + +# public key >= p +curve = curve25519 +private = 30b6c6a0f2ffa680768f992ba89e152d5bc9893d38c9119be4f767bfab6e0ca5 +public = dcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = ead9b38efdd723637934e55ab717a7ae09eb86a21dc36a3feeb88b759e391e09 + +# public key >= p +curve = curve25519 +private = 901b9dcf881e01e027575035d40b43bdc1c5242e030847495b0c7286469b6591 +public = eaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 602ff40789b54b41805915fe2a6221f07a50ffc2c3fc94cf61f13d7904e88e0e + +# public key >= p +curve = curve25519 +private = 8046677c28fd82c9a1bdb71a1a1a34faba1225e2507fe3f54d10bd5b0d865f8e +public = ebffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = e00ae8b143471247ba24f12c885536c3cb981b58e1e56b2baf35c12ae1f79c26 + +# public key >= p +curve = curve25519 +private = 602f7e2f68a846b82cc269b1d48e939886ae54fd636c1fe074d710127d472491 +public = efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 98cb9b50dd3fc2b0d4f2d2bf7c5cfdd10c8fcd31fc40af1ad44f47c131376362 + +# public key >= p +curve = curve25519 +private = 60887b3dc72443026ebedbbbb70665f42b87add1440e7768fbd7e8e2ce5f639d +public = f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 38d6304c4a7e6d9f7959334fb5245bd2c754525d4c91db950206926234c1f633 + +# public key >= p +curve = curve25519 +private = 78d31dfa854497d72d8def8a1b7fb006cec2d8c4924647c93814ae56faeda495 +public = f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 786cd54996f014a5a031ec14db812ed08355061fdb5de680a800ac521f318e23 + +# public key >= p +curve = curve25519 +private = c04c5baefa8302ddded6a4bb957761b4eb97aefa4fc3b8043085f96a5659b3a5 +public = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +result = acceptable +shared = 29ae8bc73e9b10a08b4f681c43c3e0ac1a171d31b38f1a48efba29ae639ea134 + +# RFC 7748 +curve = curve25519 +private = a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44 +public = e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c +result = valid +shared = c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552 + +# RFC 7748 +curve = curve25519 +private = 4866e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba4d +public = e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413 +result = valid +shared = 95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957 + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 0ab4e76380d84dde4f6833c58f2a9fb8f83bb0169b172be4b6e0592887741a36 +result = acceptable +shared = 0200000000000000000000000000000000000000000000000000000000000000 + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 89e10d5701b4337d2d032181538b1064bd4084401ceca1fd12663a1959388000 +result = valid +shared = 0900000000000000000000000000000000000000000000000000000000000000 + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 2b55d3aa4a8f80c8c0b2ae5f933e85af49beac36c2fa7394bab76c8933f8f81d +result = valid +shared = 1000000000000000000000000000000000000000000000000000000000000000 + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 63e5b1fe9601fe84385d8866b0421262f78fbfa5aff9585e626679b18547d959 +result = acceptable +shared = feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = e428f3dac17809f827a522ce32355058d07369364aa78902ee10139b9f9dd653 +result = valid +shared = fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = b3b50e3ed3a407b95de942ef74575b5ab8a10c09ee103544d60bdfed8138ab2b +result = acceptable +shared = f9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 213fffe93d5ea8cd242e462844029922c43c77c9e3e42f562f485d24c501a20b +result = valid +shared = f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 91b232a178b3cd530932441e6139418f72172292f1da4c1834fc5ebfefb51e3f +result = valid +shared = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03 + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 045c6e11c5d332556c7822fe94ebf89b56a3878dc27ca079103058849fabcb4f +result = acceptable +shared = e5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 1ca2190b71163539063c35773bda0c9c928e9136f0620aeb093f099197b7f74e +result = acceptable +shared = e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = f76e9010ac33c5043b2d3b76a842171000c4916222e9e85897a0aec7f6350b3c +result = valid +shared = ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = bb72688d8f8aa7a39cd6060cd5c8093cdec6fe341937c3886a99346cd07faa55 +result = acceptable +shared = dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 88fddea193391c6a5933ef9b71901549447205aae9da928a6b91a352ba10f41f +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000000002 + +# edge case for shared secret +curve = curve25519 +private = a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63 +public = 303b392f153116cad9cc682a00ccc44c95ff0d3bbe568beb6c4e739bafdc2c68 +result = acceptable +shared = 0000000000000000000000000000000000000000000000000000000000008000 + +# checking for overflow +curve = curve25519 +private = c81724704000b26d31703cc97e3a378d56fad8219361c88cca8bd7c5719b12b2 +public = fd300aeb40e1fa582518412b49b208a7842b1e1f056a040178ea4141534f652d +result = valid +shared = b734105dc257585d73b566ccb76f062795ccbec89128e52b02f3e59639f13c46 + +# checking for overflow +curve = curve25519 +private = c81724704000b26d31703cc97e3a378d56fad8219361c88cca8bd7c5719b12b2 +public = c8ef79b514d7682677bc7931e06ee5c27c9b392b4ae9484473f554e6678ecc2e +result = valid +shared = 647a46b6fc3f40d62141ee3cee706b4d7a9271593a7b143e8e2e2279883e4550 + +# checking for overflow +curve = curve25519 +private = c81724704000b26d31703cc97e3a378d56fad8219361c88cca8bd7c5719b12b2 +public = 64aeac2504144861532b7bbcb6c87d67dd4c1f07ebc2e06effb95aecc6170b2c +result = valid +shared = 4ff03d5fb43cd8657a3cf37c138cadcecce509e4eba089d0ef40b4e4fb946155 + +# checking for overflow +curve = curve25519 +private = c81724704000b26d31703cc97e3a378d56fad8219361c88cca8bd7c5719b12b2 +public = bf68e35e9bdb7eee1b50570221860f5dcdad8acbab031b14974cc49013c49831 +result = valid +shared = 21cee52efdbc812e1d021a4af1e1d8bc4db3c400e4d2a2c56a3926db4d99c65b + +# checking for overflow +curve = curve25519 +private = c81724704000b26d31703cc97e3a378d56fad8219361c88cca8bd7c5719b12b2 +public = 5347c491331a64b43ddc683034e677f53dc32b52a52a577c15a83bf298e99f19 +result = valid +shared = 18cb89e4e20c0c2bd324305245266c9327690bbe79acb88f5b8fb3f74eca3e52 + +# private key == -1 (mod order) +curve = curve25519 +private = a023cdd083ef5bb82f10d62e59e15a6800000000000000000000000000000050 +public = 258e04523b8d253ee65719fc6906c657192d80717edc828fa0af21686e2faa75 +result = valid +shared = 258e04523b8d253ee65719fc6906c657192d80717edc828fa0af21686e2faa75 + +# private key == 1 (mod order) on twist +curve = curve25519 +private = 58083dd261ad91eff952322ec824c682ffffffffffffffffffffffffffffff5f +public = 2eae5ec3dd494e9f2d37d258f873a8e6e9d0dbd1e383ef64d98bb91b3e0be035 +result = acceptable +shared = 2eae5ec3dd494e9f2d37d258f873a8e6e9d0dbd1e383ef64d98bb91b3e0be035 +