aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/benchmark/crypto/benchmark_ecc.odin89
-rw-r--r--tests/core/crypto/test_core_crypto_ecdh.odin154
-rw-r--r--tests/core/crypto/test_core_crypto_edwards.odin124
3 files changed, 188 insertions, 179 deletions
diff --git a/tests/benchmark/crypto/benchmark_ecc.odin b/tests/benchmark/crypto/benchmark_ecc.odin
index 16ca798dc..52a1a4ac1 100644
--- a/tests/benchmark/crypto/benchmark_ecc.odin
+++ b/tests/benchmark/crypto/benchmark_ecc.odin
@@ -2,13 +2,14 @@ package benchmark_core_crypto
import "base:runtime"
import "core:encoding/hex"
+import "core:log"
import "core:testing"
import "core:text/table"
import "core:time"
+import "core:crypto"
+import "core:crypto/ecdh"
import "core:crypto/ed25519"
-import "core:crypto/x25519"
-import "core:crypto/x448"
@(private = "file")
ECDH_ITERS :: 10000
@@ -25,6 +26,10 @@ benchmark_crypto_ecc :: proc(t: ^testing.T) {
@(private = "file")
bench_ecdh :: proc() {
+ if !crypto.HAS_RAND_BYTES {
+ log.warnf("ECDH benchmarks skipped, no system entropy source")
+ }
+
tbl: table.Table
table.init(&tbl)
defer table.destroy(&tbl)
@@ -42,61 +47,35 @@ bench_ecdh :: proc() {
)
}
- scalar_bp, scalar := bench_x25519()
- append_tbl(&tbl, "X25519", scalar_bp, scalar)
-
- scalar_bp, scalar = bench_x448()
- append_tbl(&tbl, "X448", scalar_bp, scalar)
-
- log_table(&tbl)
-}
-
-@(private = "file")
-bench_x25519 :: proc() -> (bp, sc: time.Duration) {
- point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
- scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
-
- point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
- scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
- out: [x25519.POINT_SIZE]byte = ---
-
- start := time.tick_now()
- for _ in 0 ..< ECDH_ITERS {
- x25519.scalarmult_basepoint(out[:], scalar[:])
- }
- bp = time.tick_since(start) / ECDH_ITERS
-
- start = time.tick_now()
- for _ in 0 ..< ECDH_ITERS {
- x25519.scalarmult(out[:], scalar[:], point[:])
- }
- sc = time.tick_since(start) / ECDH_ITERS
-
- return
-}
-
-@(private = "file")
-bench_x448 :: proc() -> (bp, sc: time.Duration) {
- point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
- scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
-
- point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
- scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
- out: [x448.POINT_SIZE]byte = ---
-
- start := time.tick_now()
- for _ in 0 ..< ECDH_ITERS {
- x448.scalarmult_basepoint(out[:], scalar[:])
- }
- bp = time.tick_since(start) / ECDH_ITERS
-
- start = time.tick_now()
- for _ in 0 ..< ECDH_ITERS {
- x448.scalarmult(out[:], scalar[:], point[:])
+ for algo in ecdh.Curve {
+ if algo == .Invalid {
+ continue
+ }
+ algo_name := ecdh.CURVE_NAMES[algo]
+
+ priv_key_alice: ecdh.Private_Key
+ start := time.tick_now()
+ for _ in 0 ..< ECDH_ITERS {
+ _ = ecdh.private_key_generate(&priv_key_alice, algo)
+ }
+ bp := time.tick_since(start) / ECDH_ITERS
+
+ pub_key_alice: ecdh.Public_Key
+ ecdh.public_key_set_priv(&pub_key_alice, &priv_key_alice)
+
+ priv_key_bob: ecdh.Private_Key
+ _ = ecdh.private_key_generate(&priv_key_bob, algo)
+ ss := make([]byte, ecdh.SHARED_SECRET_SIZES[algo], context.temp_allocator)
+ start = time.tick_now()
+ for _ in 0 ..< ECDH_ITERS {
+ _ = ecdh.ecdh(&priv_key_bob, &pub_key_alice, ss)
+ }
+ sc := time.tick_since(start) / ECDH_ITERS
+
+ append_tbl(&tbl, algo_name, bp, sc)
}
- sc = time.tick_since(start) / ECDH_ITERS
- return
+ log_table(&tbl)
}
@(private = "file")
diff --git a/tests/core/crypto/test_core_crypto_ecdh.odin b/tests/core/crypto/test_core_crypto_ecdh.odin
new file mode 100644
index 000000000..87c9e8a4d
--- /dev/null
+++ b/tests/core/crypto/test_core_crypto_ecdh.odin
@@ -0,0 +1,154 @@
+package test_core_crypto
+
+import "core:encoding/hex"
+import "core:testing"
+
+import "core:crypto/ecdh"
+
+@(test)
+test_ecdh :: proc(t: ^testing.T) {
+ test_vectors := []struct {
+ curve: ecdh.Curve,
+ scalar: string,
+ point: string,
+ product: string,
+ } {
+ // X25519 Test vectors from RFC 7748
+ {
+ .X25519,
+ "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
+ "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
+ "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
+ },
+ {
+ .X25519,
+ "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
+ "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
+ "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
+ },
+ // X448 Test vectors from RFC 7748
+ {
+ .X448,
+ "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3",
+ "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086",
+ "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f",
+ },
+ {
+ .X448,
+ "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f",
+ "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db",
+ "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d",
+ },
+ // secp256r1 Test vectors (subset) from NIST CAVP
+ {
+ .SECP256R1,
+ "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
+ "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
+ "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
+ },
+ {
+ .SECP256R1,
+ "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
+ "04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
+ "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
+ },
+ }
+
+ for v, _ in test_vectors {
+ raw_scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator)
+ raw_point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator)
+
+ pub_key: ecdh.Public_Key
+ priv_key: ecdh.Private_Key
+
+ ok := ecdh.private_key_set_bytes(&priv_key, v.curve, raw_scalar)
+ testing.expectf(t, ok, "failed to deserialize private key: %v %x", v.curve, raw_scalar)
+
+ ok = ecdh.public_key_set_bytes(&pub_key, v.curve, raw_point)
+ testing.expectf(t, ok, "failed to deserialize public key: %v %x", v.curve, raw_scalar)
+
+ shared_secret := make([]byte, ecdh.shared_secret_size(&pub_key), context.temp_allocator)
+ ok = ecdh.ecdh(&priv_key, &pub_key, shared_secret)
+ testing.expectf(t, ok, "ecdh failed: %v %v %v", v.curve, &priv_key, &pub_key)
+
+ ss_str := string(hex.encode(shared_secret, context.temp_allocator))
+ testing.expectf(
+ t,
+ ss_str == v.product,
+ "Expected %s for %v %s * %s, but got %s instead",
+ v.product,
+ v.curve,
+ v.scalar,
+ v.point,
+ ss_str,
+ )
+ }
+}
+
+@(test)
+test_ecdh_scalar_basemult :: proc(t: ^testing.T) {
+ test_vectors := []struct {
+ curve: ecdh.Curve,
+ scalar : string,
+ point: string,
+ } {
+ // X25519 from RFC 7748 6.1
+ {
+ .X25519,
+ "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
+ "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
+ },
+ {
+ .X25519,
+ "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
+ "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
+ },
+ // X448 from RFC 7748 6.2
+ {
+ .X448,
+ "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b",
+ "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0",
+ },
+ {
+ .X448,
+ "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d",
+ "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609",
+ },
+ // secp256r1 Test vectors (subset) from NIST CAVP
+ {
+ .SECP256R1,
+ "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
+ "04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
+ },
+ {
+ .SECP256R1,
+ "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
+ "04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
+ },
+ }
+
+ for v, _ in test_vectors {
+ raw_scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator)
+
+ priv_key: ecdh.Private_Key
+ pub_key: ecdh.Public_Key
+
+ ok := ecdh.private_key_set_bytes(&priv_key, v.curve, raw_scalar)
+ testing.expectf(t, ok, "failed to deserialize private key: %v %x", v.curve, raw_scalar)
+
+ ecdh.public_key_set_priv(&pub_key, &priv_key)
+ b := make([]byte, ecdh.key_size(&pub_key), context.temp_allocator)
+ ecdh.public_key_bytes(&pub_key, b)
+
+ pub_str := string(hex.encode(b, context.temp_allocator))
+ testing.expectf(
+ t,
+ pub_str == v.point,
+ "Expected %s for %v %s * G, but got %s instead",
+ v.point,
+ v.curve,
+ v.scalar,
+ pub_str,
+ )
+ }
+} \ No newline at end of file
diff --git a/tests/core/crypto/test_core_crypto_edwards.odin b/tests/core/crypto/test_core_crypto_edwards.odin
index a1307da24..2da98000c 100644
--- a/tests/core/crypto/test_core_crypto_edwards.odin
+++ b/tests/core/crypto/test_core_crypto_edwards.odin
@@ -6,8 +6,6 @@ import "core:testing"
import field "core:crypto/_fiat/field_curve25519"
import "core:crypto/ed25519"
import "core:crypto/ristretto255"
-import "core:crypto/x25519"
-import "core:crypto/x448"
@(test)
test_edwards25519_sqrt_ratio_m1 :: proc(t: ^testing.T) {
@@ -625,128 +623,6 @@ test_ed25519 :: proc(t: ^testing.T) {
}
}
-@(test)
-test_x25519 :: proc(t: ^testing.T) {
- // Local copy of this so that the base point doesn't need to be exported.
- _BASE_POINT: [32]byte = {
- 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- }
-
- test_vectors := []struct {
- scalar: string,
- point: string,
- product: string,
- } {
- // Test vectors from RFC 7748
- {
- "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
- "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
- "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
- },
- {
- "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
- "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
- "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
- },
- }
- for v, _ in test_vectors {
- scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator)
- point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator)
-
- derived_point: [x25519.POINT_SIZE]byte
- x25519.scalarmult(derived_point[:], scalar[:], point[:])
- derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator))
-
- testing.expectf(
- t,
- derived_point_str == v.product,
- "Expected %s for %s * %s, but got %s instead",
- v.product,
- v.scalar,
- v.point,
- derived_point_str,
- )
-
- // Abuse the test vectors to sanity-check the scalar-basepoint multiply.
- p1, p2: [x25519.POINT_SIZE]byte
- x25519.scalarmult_basepoint(p1[:], scalar[:])
- x25519.scalarmult(p2[:], scalar[:], _BASE_POINT[:])
- p1_str := string(hex.encode(p1[:], context.temp_allocator))
- p2_str := string(hex.encode(p2[:], context.temp_allocator))
- testing.expectf(
- t,
- p1_str == p2_str,
- "Expected %s for %s * basepoint, but got %s instead",
- p2_str,
- v.scalar,
- p1_str,
- )
- }
-}
-
-@(test)
-test_x448 :: proc(t: ^testing.T) {
- // Local copy of this so that the base point doesn't need to be exported.
- _BASE_POINT: [56]byte = {
- 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- }
-
- test_vectors := []struct {
- scalar: string,
- point: string,
- product: string,
- } {
- // Test vectors from RFC 7748
- {
- "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3",
- "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086",
- "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f",
- },
- {
- "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f",
- "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db",
- "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d",
- },
- }
- for v, _ in test_vectors {
- scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator)
- point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator)
-
- derived_point: [x448.POINT_SIZE]byte
- x448.scalarmult(derived_point[:], scalar[:], point[:])
- derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator))
-
- testing.expectf(
- t,
- derived_point_str == v.product,
- "Expected %s for %s * %s, but got %s instead",
- v.product,
- v.scalar,
- v.point,
- derived_point_str,
- )
-
- // Abuse the test vectors to sanity-check the scalar-basepoint multiply.
- p1, p2: [x448.POINT_SIZE]byte
- x448.scalarmult_basepoint(p1[:], scalar[:])
- x448.scalarmult(p2[:], scalar[:], _BASE_POINT[:])
- p1_str := string(hex.encode(p1[:], context.temp_allocator))
- p2_str := string(hex.encode(p2[:], context.temp_allocator))
- testing.expectf(
- t,
- p1_str == p2_str,
- "Expected %s for %s * basepoint, but got %s instead",
- p2_str,
- v.scalar,
- p1_str,
- )
- }
-}
-
@(private="file")
ge_str :: proc(ge: ^ristretto255.Group_Element) -> string {
b: [ristretto255.ELEMENT_SIZE]byte