From 0cf13c2266344a74ff66d947cc4dc5e9e90d4874 Mon Sep 17 00:00:00 2001 From: Kevin Lewi Date: Sun, 14 Jun 2020 23:25:31 -0700 Subject: [PATCH] Adding CipherSuite trait to handle bundling of underlying crypto primitives --- Cargo.lock | 124 +++++++------- src/ciphersuite.rs | 30 +++- src/lib.rs | 204 ++++++++++++---------- src/opaque.rs | 332 +++++++++++++++++++----------------- src/slow_hash.rs | 5 + src/tests/opaque_ke_test.rs | 103 ++++++----- src/tests/serialization.rs | 19 ++- 7 files changed, 446 insertions(+), 371 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77c5cb7..14e2c6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "ghash 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -131,7 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chacha20" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -144,7 +144,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aead 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chacha20 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "chacha20 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "poly1305 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -169,13 +169,13 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -207,7 +207,7 @@ name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -216,7 +216,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -263,7 +263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -287,7 +287,7 @@ dependencies = [ "aes-gcm 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "chacha20poly1305 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hkdf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -297,9 +297,9 @@ dependencies = [ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "x25519-dalek 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -337,7 +337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "1.0.8" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -369,10 +369,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "1.0.2" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -382,7 +382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -393,7 +393,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -476,7 +476,7 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -495,28 +495,28 @@ dependencies = [ "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.105" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sha2" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -540,27 +540,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "subtle" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.14" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -570,7 +570,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -579,25 +579,25 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.11" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thiserror-impl" -version = "1.0.11" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -611,7 +611,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -619,7 +619,7 @@ name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -651,7 +651,7 @@ name = "x25519-dalek" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -669,10 +669,10 @@ name = "zeroize_derive" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] @@ -693,11 +693,11 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chacha20 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bea8b86bdf2f2b18a0f28fbfed740ee395e6ba1785b4b7123c021172eaab8ef9" +"checksum chacha20 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f6a7ae4c498f8447d86baef0fa0831909333f558866fabcb21600625ac5a31c7" "checksum chacha20poly1305 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "48901293601228db2131606f741db33561f7576b5d19c99cd66222380a7dc863" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" +"checksum curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" @@ -710,17 +710,17 @@ dependencies = [ "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" "checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum poly1305 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5829f50f48e9ddb79f3f7c3097029d0caee30f8286accb241416df603b080b8" "checksum polyval 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec3341498978de3bfd12d1b22f1af1de22818f5473a11e8a6ef997989e3a212" "checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" -"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" +"checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" "checksum proptest 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2520fe6373cf6a3a61e2d200e987c183778ade8d9248ac3e6614ab0edfe4a0c1" "checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" "checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" @@ -733,21 +733,21 @@ dependencies = [ "checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" "checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" "checksum rusty-fork 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" -"checksum serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" -"checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" -"checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +"checksum serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" +"checksum serde_json 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)" = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226" +"checksum sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" "checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" -"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +"checksum subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1" +"checksum syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" +"checksum synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" -"checksum thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344" +"checksum thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479" +"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum universal-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df0c900f2f9b4116803415878ff48b63da9edb268668e08cf9292d7503114a01" "checksum wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" diff --git a/src/ciphersuite.rs b/src/ciphersuite.rs index 7ddfdb6..2275819 100644 --- a/src/ciphersuite.rs +++ b/src/ciphersuite.rs @@ -1,6 +1,30 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. +//! Defines the CipherSuite trait to specify the underlying primitives for OPAQUE + +use crate::{ + errors::InternalPakeError, + group::Group, + keypair::{Key, KeyPair}, + slow_hash::SlowHash, +}; +use generic_array::typenum::{U32, U64}; +use rand_core::{CryptoRng, RngCore}; + +/// Configures the underlying primitives used in OPAQUE pub trait CipherSuite { - type Aead; - type Group; - type Keypair; + type Aead: aead::NewAead + aead::Aead; + type Group: Group; + type KeyFormat: KeyPair + PartialEq; + type SlowHash: SlowHash; + + /// Generating a random key pair given a cryptographic rng + fn generate_random_keypair( + rng: &mut R, + ) -> Result { + Self::KeyFormat::generate_random(rng) + } } diff --git a/src/lib.rs b/src/lib.rs index 38ae658..dfa2e8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,15 +13,20 @@ //! OPAQUE is a protocol between a client and a server. They must first agree on a collection of primitives //! to be kept consistent throughout protocol execution. These include: //! * an authenticated encryption scheme, -//! * a finite cyclic group along with a point representation, and -//! * a keypair type. +//! * a finite cyclic group along with a point representation, +//! * a keypair type, and +//! * a slow hashing function. //! //! We will use the following choices in this example: //! ``` -//! use chacha20poly1305::ChaCha20Poly1305; -//! use curve25519_dalek::ristretto::RistrettoPoint; -//! use opaque_ke::keypair::X25519KeyPair; -//! use opaque_ke::slow_hash::NoOpHash; +//! use opaque_ke::ciphersuite::CipherSuite; +//! struct Default; +//! impl CipherSuite for Default { +//! type Aead = chacha20poly1305::ChaCha20Poly1305; +//! type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! } //! ``` //! //! Note that our choice of slow hashing function in this example, `NoOpHash`, is selected only to ensure @@ -35,9 +40,17 @@ //! ``` //! # use opaque_ke::keypair::{KeyPair, X25519KeyPair, SizedBytes}; //! # use opaque_ke::errors::ProtocolError; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! use rand_core::{OsRng, RngCore}; //! let mut rng = OsRng; -//! let server_kp = X25519KeyPair::generate_random(&mut rng)?; +//! let server_kp = Default::generate_random_keypair(&mut rng)?; //! # Ok::<(), ProtocolError>(()) //! ``` //! The server must persist this keypair for the registration and login steps, where the public component will be @@ -59,11 +72,17 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! use rand_core::{OsRng, RngCore}; //! let mut client_rng = OsRng; -//! let (r1, client_state) = ClientRegistration::::start( +//! let (r1, client_state) = ClientRegistration::::start( //! b"password", //! Some(b"pepper"), //! &mut client_rng, @@ -82,21 +101,23 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! # let mut client_rng = OsRng; -//! # let (r1, client_state) = ClientRegistration::::start( +//! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! let mut server_rng = OsRng; -//! let (r2, server_state) = -//! ServerRegistration::::start( -//! r1, -//! &mut server_rng, -//! )?; +//! let (r2, server_state) = ServerRegistration::::start(r1, &mut server_rng)?; //! # Ok::<(), ProtocolError>(()) //! ``` //! `r2` is returned to the client, and `server_state` must be persisted on the server for the final step of server @@ -112,24 +133,26 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! # let mut client_rng = OsRng; -//! # let (r1, client_state) = ClientRegistration::::start( +//! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; -//! # let (r2, server_state) = -//! # ServerRegistration::::start( -//! # r1, -//! # &mut server_rng, -//! # )?; -//! # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; +//! let (r2, server_state) = ServerRegistration::::start(r1, &mut server_rng)?; +//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?; //! let (r3, kd_key_registration) = -//! client_state.finish::<_, X25519KeyPair, NoOpHash>(r2, server_kp.public(), &mut client_rng)?; +//! client_state.finish(r2, server_kp.public(), &mut client_rng)?; //! # Ok::<(), ProtocolError>(()) //! ``` //! `r3` is sent to the server, and the client can optionally use `kd_key_registration` for applications that choose to @@ -144,24 +167,25 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! # let mut client_rng = OsRng; -//! # let (r1, client_state) = ClientRegistration::::start( +//! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; -//! # let (r2, server_state) = -//! # ServerRegistration::::start( -//! # r1, -//! # &mut server_rng, -//! # )?; -//! # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; -//! # let (r3, kd_key_registration) = -//! # client_state.finish::<_, X25519KeyPair, NoOpHash>(r2, server_kp.public(), &mut client_rng)?; +//! let (r2, server_state) = ServerRegistration::::start(r1, &mut server_rng)?; +//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?; +//! # let (r3, kd_key_registration) = client_state.finish(r2, server_kp.public(), &mut client_rng)?; //! let password_file = server_state.finish(r3)?; //! # Ok::<(), ProtocolError>(()) //! ``` @@ -185,11 +209,17 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! let mut client_rng = OsRng; -//! let (l1, client_state) = ClientLogin::::start( +//! let (l1, client_state) = ClientLogin::::start( //! b"password", //! Some(b"pepper"), //! &mut client_rng, @@ -208,35 +238,33 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! # let mut client_rng = OsRng; -//! # let (r1, client_state) = ClientRegistration::::start( +//! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; -//! # let (r2, server_state) = -//! # ServerRegistration::::start( -//! # r1, -//! # &mut server_rng, -//! # )?; -//! # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; -//! # let (r3, kd_key_registration) = -//! # client_state.finish::<_, X25519KeyPair, NoOpHash>(r2, server_kp.public(), &mut client_rng)?; +//! let (r2, server_state) = ServerRegistration::::start(r1, &mut server_rng)?; +//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?; +//! # let (r3, kd_key_registration) = client_state.finish(r2, server_kp.public(), &mut client_rng)?; //! # let password_file_bytes = server_state.finish(r3)?.to_bytes(); -//! # let (l1, client_state) = ClientLogin::::start( +//! # let (l1, client_state) = ClientLogin::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! use std::convert::TryFrom; -//! let password_file = -//! ServerRegistration::::try_from( -//! &password_file_bytes[..], -//! )?; +//! let password_file = ServerRegistration::::try_from(&password_file_bytes[..])?; //! let mut server_rng = OsRng; //! let (l2, server_state) = //! ServerLogin::start(password_file, &server_kp.private(), l1, &mut server_rng)?; @@ -254,38 +282,39 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! # let mut client_rng = OsRng; -//! # let (r1, client_state) = ClientRegistration::::start( +//! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; -//! # let (r2, server_state) = -//! # ServerRegistration::::start( -//! # r1, -//! # &mut server_rng, -//! # )?; -//! # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; -//! # let (r3, kd_key_registration) = -//! # client_state.finish::<_, X25519KeyPair, NoOpHash>(r2, server_kp.public(), &mut client_rng)?; +//! let (r2, server_state) = ServerRegistration::::start(r1, &mut server_rng)?; +//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?; +//! # let (r3, kd_key_registration) = client_state.finish(r2, server_kp.public(), &mut client_rng)?; //! # let password_file_bytes = server_state.finish(r3)?.to_bytes(); -//! # let (l1, client_state) = ClientLogin::::start( +//! # let (l1, client_state) = ClientLogin::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # use std::convert::TryFrom; //! # let password_file = -//! # ServerRegistration::::try_from( +//! # ServerRegistration::::try_from( //! # &password_file_bytes[..], //! # )?; //! # let (l2, server_state) = //! # ServerLogin::start(password_file, &server_kp.private(), l1, &mut server_rng)?; -//! let (l3, client_shared_secret, kd_key_login) = client_state.finish::<_, NoOpHash>( +//! let (l3, client_shared_secret, kd_key_login) = client_state.finish( //! l2, //! &server_kp.public(), //! &mut client_rng, @@ -309,38 +338,39 @@ //! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # slow_hash::NoOpHash, //! # }; -//! # use curve25519_dalek::ristretto::RistrettoPoint; -//! # use chacha20poly1305::ChaCha20Poly1305; +//! # use opaque_ke::ciphersuite::CipherSuite; +//! # struct Default; +//! # impl CipherSuite for Default { +//! # type Aead = chacha20poly1305::ChaCha20Poly1305; +//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; +//! # type KeyFormat = opaque_ke::keypair::X25519KeyPair; +//! # type SlowHash = opaque_ke::slow_hash::NoOpHash; +//! # } //! # use rand_core::{OsRng, RngCore}; //! # let mut client_rng = OsRng; -//! # let (r1, client_state) = ClientRegistration::::start( +//! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; -//! # let (r2, server_state) = -//! # ServerRegistration::::start( -//! # r1, -//! # &mut server_rng, -//! # )?; -//! # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; -//! # let (r3, kd_key) = -//! # client_state.finish::<_, X25519KeyPair, NoOpHash>(r2, server_kp.public(), &mut client_rng)?; +//! let (r2, server_state) = ServerRegistration::::start(r1, &mut server_rng)?; +//! # let server_kp = Default::generate_random_keypair(&mut server_rng)?; +//! # let (r3, kd_key) = client_state.finish(r2, server_kp.public(), &mut client_rng)?; //! # let password_file_bytes = server_state.finish(r3)?.to_bytes(); -//! # let (l1, client_state) = ClientLogin::::start( +//! # let (l1, client_state) = ClientLogin::::start( //! # b"password", //! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # use std::convert::TryFrom; //! # let password_file = -//! # ServerRegistration::::try_from( +//! # ServerRegistration::::try_from( //! # &password_file_bytes[..], //! # )?; //! # let (l2, server_state) = //! # ServerLogin::start(password_file, &server_kp.private(), l1, &mut server_rng)?; -//! # let (l3, client_shared_secret, kd_key) = client_state.finish::<_, NoOpHash>( +//! # let (l3, client_shared_secret, kd_key) = client_state.finish( //! # l2, //! # &server_kp.public(), //! # &mut client_rng, @@ -358,6 +388,7 @@ pub mod errors; // High-level API pub mod opaque; +pub mod ciphersuite; // Your choice of RKR encryption mod rkr_encryption; // Your choice of KE @@ -369,7 +400,6 @@ mod oprf; // do the oprf on mod group; pub mod slow_hash; -pub mod ciphersuite; #[cfg(test)] mod tests; diff --git a/src/opaque.rs b/src/opaque.rs index 42a27b3..1fff609 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -6,6 +6,7 @@ //! Provides the main OPAQUE API use crate::{ + ciphersuite::CipherSuite, errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError}, group::Group, key_exchange::{ @@ -19,7 +20,7 @@ use crate::{ slow_hash::SlowHash, }; use generic_array::{ - typenum::{Unsigned, U32, U64}, + typenum::{Unsigned, U32}, GenericArray, }; use hkdf::Hkdf; @@ -257,25 +258,23 @@ impl LoginThirdMessage { // ============ /// The state elements the client holds to register itself -pub struct ClientRegistration { +pub struct ClientRegistration { /// A choice of symmetric encryption for the envelope - _aead: PhantomData, + _aead: PhantomData, /// a blinding factor - pub(crate) blinding_factor: Grp::Scalar, + pub(crate) blinding_factor: <::Group as Group>::Scalar, /// the client's password password: Vec, } -impl + aead::Aead, Grp: Group> TryFrom<&[u8]> - for ClientRegistration -{ +impl TryFrom<&[u8]> for ClientRegistration { type Error = ProtocolError; fn try_from(bytes: &[u8]) -> Result { // Check that the message is actually containing an element of the // correct subgroup - let scalar_len = Grp::ScalarLen::to_usize(); + let scalar_len = <::Group as Group>::ScalarLen::to_usize(); let blinding_factor_bytes = GenericArray::from_slice(&bytes[..scalar_len]); - let blinding_factor = Grp::from_scalar_slice(blinding_factor_bytes)?; + let blinding_factor = CS::Group::from_scalar_slice(blinding_factor_bytes)?; let password = bytes[scalar_len..].to_vec(); Ok(Self { _aead: PhantomData, @@ -285,14 +284,10 @@ impl + aead::Aead, Grp: Group> TryFrom<&[u8]> } } -impl ClientRegistration -where - Aead: aead::NewAead + aead::Aead, - Grp: Group, -{ +impl ClientRegistration { pub fn to_bytes(&self) -> Vec { let output: Vec = [ - Grp::scalar_as_bytes(&self.blinding_factor).as_slice(), + CS::Group::scalar_as_bytes(&self.blinding_factor).as_slice(), &self.password, ] .concat(); @@ -300,10 +295,7 @@ where } } -impl ClientRegistration -where - Grp: Group, -{ +impl ClientRegistration { /// Returns an initial "blinded" request to send to the server, as well as a ClientRegistration /// /// # Arguments @@ -314,25 +306,31 @@ where /// ``` /// use opaque_ke::opaque::ClientRegistration; /// # use opaque_ke::errors::ProtocolError; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; /// use rand_core::{OsRng, RngCore}; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut rng = OsRng; - /// let (register_m1, registration_state) = ClientRegistration::::start(b"hunter2", None, &mut rng)?; + /// let (register_m1, registration_state) = ClientRegistration::::start(b"hunter2", None, &mut rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( password: &[u8], pepper: Option<&[u8]>, blinding_factor_rng: &mut R, - ) -> Result<(RegisterFirstMessage, Self), ProtocolError> { + ) -> Result<(RegisterFirstMessage, Self), ProtocolError> { let OprfClientBytes { alpha, blinding_factor, - } = oprf::generate_oprf1::(&password, pepper, blinding_factor_rng)?; + } = oprf::generate_oprf1::(&password, pepper, blinding_factor_rng)?; Ok(( - RegisterFirstMessage:: { alpha }, + RegisterFirstMessage:: { alpha }, Self { _aead: PhantomData, blinding_factor, @@ -347,11 +345,7 @@ type ClientRegistrationFinishResult = ( GenericArray::OutputSize>, ); -impl ClientRegistration -where - Aead: aead::NewAead + aead::Aead, - Grp: Group, -{ +impl ClientRegistration { /// "Unblinds" the server's answer and returns a final message containing /// cryptographic identifiers, to be sent to the server on setup finalization /// @@ -364,29 +358,34 @@ where /// use opaque_ke::{opaque::{ClientRegistration, ServerRegistration}, keypair::{X25519KeyPair, SizedBytes}}; /// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::keypair::KeyPair; - /// # use opaque_ke::slow_hash::NoOpHash; /// use rand_core::{OsRng, RngCore}; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; /// let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, &mut server_rng)?; + /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// let mut client_rng = OsRng; - /// let register_m3 = client_state.finish::<_, X25519KeyPair, NoOpHash>(register_m2, server_kp.public(), &mut client_rng)?; + /// let register_m3 = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` - pub fn finish( + pub fn finish( self, - r2: RegisterSecondMessage, - server_s_pk: &KeyFormat::Repr, + r2: RegisterSecondMessage, + server_s_pk: &<::KeyFormat as KeyPair>::Repr, rng: &mut R, - ) -> Result, ProtocolError> { - let client_static_keypair = KeyFormat::generate_random(rng)?; + ) -> Result, ProtocolError> { + let client_static_keypair = CS::KeyFormat::generate_random(rng)?; - let password_derived_key = get_password_derived_key::( + let password_derived_key = get_password_derived_key::( self.password.clone(), r2.beta, &self.blinding_factor, @@ -399,7 +398,7 @@ where let hmac_key = &okm[DERIVED_KEY_LEN..2 * DERIVED_KEY_LEN]; let kd_key = &okm[2 * DERIVED_KEY_LEN..]; - let envelope = RKRCiphertext::::encrypt( + let envelope = RKRCiphertext::::encrypt( &encryption_key, &hmac_key, &client_static_keypair.private().to_arr(), @@ -418,60 +417,59 @@ where } // This can't be derived because of the use of a phantom parameter -impl Zeroize for ClientRegistration { +impl Zeroize for ClientRegistration { fn zeroize(&mut self) { self.password.zeroize(); self.blinding_factor.zeroize(); } } -impl Drop for ClientRegistration { +impl Drop for ClientRegistration { fn drop(&mut self) { self.zeroize(); } } // This can't be derived because of the use of a phantom parameter -impl Zeroize for ClientLogin { +impl Zeroize for ClientLogin { fn zeroize(&mut self) { self.password.zeroize(); self.blinding_factor.zeroize(); } } -impl Drop for ClientLogin { +impl Drop for ClientLogin { fn drop(&mut self) { self.zeroize(); } } /// The state elements the server holds to record a registration -pub struct ServerRegistration { - envelope: Option>, - client_s_pk: Option, - pub(crate) oprf_key: Grp::Scalar, +pub struct ServerRegistration { + envelope: Option>, + client_s_pk: Option<<::KeyFormat as KeyPair>::Repr>, + pub(crate) oprf_key: <::Group as Group>::Scalar, } -impl TryFrom<&[u8]> for ServerRegistration +impl TryFrom<&[u8]> for ServerRegistration where - Aead: aead::NewAead + aead::Aead, - Grp: Group, - KeyFormat: KeyPair + PartialEq, - ::Len: std::ops::Add<::Len>, + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len: + std::ops::Add<<<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len>, generic_array::typenum::Sum< - ::Len, - ::Len, + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len, + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len, >: generic_array::ArrayLength, { type Error = ProtocolError; fn try_from(server_registration_bytes: &[u8]) -> Result { - let key_len = ::Len::to_usize(); - let scalar_len = Grp::ScalarLen::to_usize(); - let rkr_size = RKRCiphertext::::rkr_with_nonce_size(); + let key_len = + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len::to_usize(); + let scalar_len = <::Group as Group>::ScalarLen::to_usize(); + let rkr_size = RKRCiphertext::::rkr_with_nonce_size(); if server_registration_bytes.len() == scalar_len { return Ok(Self { - oprf_key: Grp::from_scalar_slice(GenericArray::from_slice( + oprf_key: CS::Group::from_scalar_slice(GenericArray::from_slice( server_registration_bytes, ))?, client_s_pk: None, @@ -485,10 +483,11 @@ where "server_registration_bytes", )?; let oprf_key_bytes = GenericArray::from_slice(&checked_bytes[..scalar_len]); - let oprf_key = Grp::from_scalar_slice(oprf_key_bytes)?; - let unchecked_client_s_pk = - KeyFormat::Repr::from_bytes(&checked_bytes[scalar_len..scalar_len + key_len])?; - let client_s_pk = KeyFormat::check_public_key(unchecked_client_s_pk)?; + let oprf_key = CS::Group::from_scalar_slice(oprf_key_bytes)?; + let unchecked_client_s_pk = <::KeyFormat as KeyPair>::Repr::from_bytes( + &checked_bytes[scalar_len..scalar_len + key_len], + )?; + let client_s_pk = CS::KeyFormat::check_public_key(unchecked_client_s_pk)?; Ok(Self { envelope: Some(RKRCiphertext::from_bytes( &checked_bytes[checked_bytes.len() - rkr_size..], @@ -499,19 +498,17 @@ where } } -impl ServerRegistration +impl ServerRegistration where - Aead: aead::NewAead + aead::Aead, - Grp: Group, - KeyFormat: KeyPair + PartialEq, - ::Len: std::ops::Add<::Len>, + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len: + std::ops::Add<<<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len>, generic_array::typenum::Sum< - ::Len, - ::Len, + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len, + <<::KeyFormat as KeyPair>::Repr as SizedBytes>::Len, >: generic_array::ArrayLength, { pub fn to_bytes(&self) -> Vec { - let mut output: Vec = Grp::scalar_as_bytes(&self.oprf_key).to_vec(); + let mut output: Vec = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec(); match &self.client_s_pk { Some(v) => output.extend_from_slice(&v.to_arr()), None => {} @@ -534,26 +531,31 @@ where /// ``` /// use opaque_ke::{opaque::*, keypair::{X25519KeyPair, SizedBytes}}; /// # use opaque_ke::errors::ProtocolError; - /// # use opaque_ke::keypair::KeyPair; /// use rand_core::{OsRng, RngCore}; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; - /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; /// let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, &mut server_rng)?; + /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( - message: RegisterFirstMessage, + message: RegisterFirstMessage, rng: &mut R, - ) -> Result<(RegisterSecondMessage, Self), ProtocolError> { + ) -> Result<(RegisterSecondMessage, Self), ProtocolError> { // RFC: generate oprf_key (salt) and v_u = g^oprf_key - let oprf_key = Grp::random_scalar(rng); + let oprf_key = CS::Group::random_scalar(rng); // Compute beta = alpha^oprf_key - let beta = oprf::generate_oprf2::(message.alpha, &oprf_key)?; + let beta = oprf::generate_oprf2::(message.alpha, &oprf_key)?; Ok(( RegisterSecondMessage { beta }, @@ -574,27 +576,31 @@ where /// # Example /// /// ``` - /// use opaque_ke::{opaque::*, keypair::{X25519KeyPair, SizedBytes}}; + /// use opaque_ke::{opaque::*, keypair::{KeyPair, X25519KeyPair, SizedBytes}}; /// # use opaque_ke::errors::ProtocolError; - /// # use opaque_ke::keypair::KeyPair; - /// # use opaque_ke::slow_hash::NoOpHash; /// use rand_core::{OsRng, RngCore}; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; /// let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, &mut server_rng)?; + /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// let mut client_rng = OsRng; - /// let (register_m3, _opaque_key) = client_state.finish::<_, _, NoOpHash>(register_m2, server_kp.public(), &mut client_rng)?; + /// let (register_m3, _opaque_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// let client_record = server_state.finish(register_m3)?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn finish( self, - message: RegisterThirdMessage, + message: RegisterThirdMessage, ) -> Result { Ok(Self { envelope: Some(message.envelope), @@ -608,27 +614,25 @@ where // ===== /// The state elements the client holds to perform a login -pub struct ClientLogin { +pub struct ClientLogin { /// A choice of symmetric encryption for the envelope - _aead: PhantomData, + _aead: PhantomData, /// A choice of the keypair type - _key_format: PhantomData, + _key_format: PhantomData, /// A blinding factor, which is used to mask (and unmask) secret /// information before transmission - blinding_factor: Grp::Scalar, + blinding_factor: <::Group as Group>::Scalar, /// The user's password password: Vec, ke1_state: KE1State, } -impl + aead::Aead, Grp: Group, KeyFormat: KeyPair> TryFrom<&[u8]> - for ClientLogin -{ +impl TryFrom<&[u8]> for ClientLogin { type Error = ProtocolError; fn try_from(bytes: &[u8]) -> Result { - let scalar_len = Grp::ScalarLen::to_usize(); + let scalar_len = <::Group as Group>::ScalarLen::to_usize(); let blinding_factor_bytes = GenericArray::from_slice(&bytes[..scalar_len]); - let blinding_factor = Grp::from_scalar_slice(blinding_factor_bytes)?; + let blinding_factor = CS::Group::from_scalar_slice(blinding_factor_bytes)?; let ke1_state = KE1State::try_from(&bytes[scalar_len..scalar_len + KE1_STATE_LEN])?; let password = bytes[scalar_len + KE1_STATE_LEN..].to_vec(); Ok(Self { @@ -641,15 +645,10 @@ impl + aead::Aead, Grp: Group, KeyFormat: Key } } -impl ClientLogin -where - Aead: aead::NewAead + aead::Aead, - Grp: Group, - KeyFormat: KeyPair, -{ +impl ClientLogin { pub fn to_bytes(&self) -> Vec { let output: Vec = [ - Grp::scalar_as_bytes(&self.blinding_factor).as_slice(), + CS::Group::scalar_as_bytes(&self.blinding_factor).as_slice(), &self.ke1_state.to_bytes(), &self.password, ] @@ -664,12 +663,7 @@ type ClientLoginFinishResult = ( GenericArray::OutputSize>, ); -impl ClientLogin -where - Aead: aead::NewAead + aead::Aead, - Grp: Group, - KeyFormat: KeyPair, -{ +impl ClientLogin { /// Returns an initial "blinded" password request to send to the server, as well as a ClientLogin /// /// # Arguments @@ -680,26 +674,31 @@ where /// ``` /// use opaque_ke::opaque::ClientLogin; /// # use opaque_ke::errors::ProtocolError; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use opaque_ke::keypair::X25519KeyPair; /// use rand_core::{OsRng, RngCore}; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( password: &[u8], pepper: Option<&[u8]>, rng: &mut R, - ) -> Result<(LoginFirstMessage, Self), ProtocolError> { + ) -> Result<(LoginFirstMessage, Self), ProtocolError> { let OprfClientBytes { alpha, blinding_factor, - } = oprf::generate_oprf1::(&password, pepper, rng)?; + } = oprf::generate_oprf1::(&password, pepper, rng)?; let (ke1_state, ke1_message) = - generate_ke1::<_, KeyFormat>(alpha.to_bytes().to_vec(), rng)?; + generate_ke1::<_, CS::KeyFormat>(alpha.to_bytes().to_vec(), rng)?; let l1 = LoginFirstMessage { alpha, ke1_message }; @@ -728,31 +727,36 @@ where /// # use opaque_ke::opaque::{ClientRegistration, ServerRegistration}; /// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::keypair::{X25519KeyPair, KeyPair}; - /// # use opaque_ke::slow_hash::NoOpHash; /// use rand_core::{OsRng, RngCore}; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; /// # let mut server_rng = OsRng; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; /// # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// # let (register_m2, server_state) = ServerRegistration::::start(register_m1, &mut server_rng)?; - /// # let (register_m3, _opaque_key) = client_state.finish::<_, _, NoOpHash>(register_m2, server_kp.public(), &mut client_rng)?; + /// # let (register_m2, server_state) = ServerRegistration::::start(register_m1, &mut server_rng)?; + /// # let (register_m3, _opaque_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # let p_file = server_state.finish(register_m3)?; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; /// let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; - /// let (login_m3, client_transport, _opaque_key) = client_login_state.finish::<_, NoOpHash>(login_m2, &server_kp.public(), &mut client_rng)?; + /// let (login_m3, client_transport, _opaque_key) = client_login_state.finish(login_m2, &server_kp.public(), &mut client_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` - pub fn finish( + pub fn finish( self, - l2: LoginSecondMessage, - server_s_pk: &KeyFormat::Repr, + l2: LoginSecondMessage, + server_s_pk: &<::KeyFormat as KeyPair>::Repr, _client_e_sk_rng: &mut R, ) -> Result { let l2_bytes: Vec = [l2.beta.to_bytes().as_slice(), &l2.envelope.to_bytes()].concat(); - let password_derived_key = get_password_derived_key::( + let password_derived_key = get_password_derived_key::( self.password.clone(), l2.beta, &self.blinding_factor, @@ -774,7 +778,7 @@ where })?, )?; - let (ke3_state, ke3_message) = generate_ke3::( + let (ke3_state, ke3_message) = generate_ke3::( l2_bytes, l2.ke2_message, &self.ke1_state, @@ -804,6 +808,11 @@ impl TryFrom<&[u8]> for ServerLogin { } } +type ServerLoginStartResult = ( + LoginSecondMessage<::Aead, ::Group>, + ServerLogin, +); + impl ServerLogin { pub fn to_bytes(&self) -> Vec { self.ke2_state.to_bytes() @@ -822,33 +831,33 @@ impl ServerLogin { /// # use opaque_ke::opaque::{ClientRegistration, ServerRegistration}; /// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::keypair::{KeyPair, X25519KeyPair}; - /// # use opaque_ke::slow_hash::NoOpHash; /// use rand_core::{OsRng, RngCore}; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; /// # let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, &mut server_rng)?; - /// # let (register_m3, _opaque_key) = client_state.finish::<_, _, NoOpHash>(register_m2, server_kp.public(), &mut client_rng)?; + /// ServerRegistration::::start(register_m1, &mut server_rng)?; + /// # let (register_m3, _opaque_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # let p_file = server_state.finish(register_m3)?; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; /// let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` - pub fn start< - R: RngCore + CryptoRng, - Aead: aead::NewAead + aead::Aead, - Grp: Group, - KeyFormat: KeyPair, - >( - password_file: ServerRegistration, + pub fn start( + password_file: ServerRegistration, server_s_sk: &Key, - l1: LoginFirstMessage, + l1: LoginFirstMessage, rng: &mut R, - ) -> Result<(LoginSecondMessage, Self), ProtocolError> { + ) -> Result, ProtocolError> { let l1_bytes = &l1.to_bytes(); let beta = oprf::generate_oprf2(l1.alpha, &password_file.oprf_key)?; @@ -859,7 +868,7 @@ impl ServerLogin { let l2_component: Vec = [beta.to_bytes().as_slice(), &envelope.to_bytes()].concat(); - let (ke2_state, ke2_message) = generate_ke2::<_, KeyFormat>( + let (ke2_state, ke2_message) = generate_ke2::<_, CS::KeyFormat>( rng, l1_bytes.to_vec(), l2_component, @@ -891,21 +900,26 @@ impl ServerLogin { /// # use opaque_ke::opaque::{ClientRegistration, ServerRegistration}; /// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::keypair::{KeyPair, X25519KeyPair}; - /// # use opaque_ke::slow_hash::NoOpHash; /// use rand_core::{OsRng, RngCore}; - /// use chacha20poly1305::ChaCha20Poly1305; - /// use curve25519_dalek::ristretto::RistrettoPoint; + /// use opaque_ke::ciphersuite::CipherSuite; + /// struct Default; + /// impl CipherSuite for Default { + /// type Aead = chacha20poly1305::ChaCha20Poly1305; + /// type Group = curve25519_dalek::ristretto::RistrettoPoint; + /// type KeyFormat = opaque_ke::keypair::X25519KeyPair; + /// type SlowHash = opaque_ke::slow_hash::NoOpHash; + /// } /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; /// # let (register_m2, server_state) = - /// ServerRegistration::::start(register_m1, &mut server_rng)?; - /// # let (register_m3, _opaque_key) = client_state.finish::<_, _, NoOpHash>(register_m2, server_kp.public(), &mut client_rng)?; + /// ServerRegistration::::start(register_m1, &mut server_rng)?; + /// # let (register_m3, _opaque_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # let p_file = server_state.finish(register_m3)?; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; /// let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; - /// let (login_m3, client_transport, _opaque_key) = client_login_state.finish::<_, NoOpHash>(login_m2, &server_kp.public(), &mut client_rng)?; + /// let (login_m3, client_transport, _opaque_key) = client_login_state.finish(login_m2, &server_kp.public(), &mut client_rng)?; /// let mut server_transport = server_login_state.finish(login_m3)?; /// # Ok::<(), ProtocolError>(()) /// ``` diff --git a/src/slow_hash.rs b/src/slow_hash.rs index ce71545..7a502a5 100644 --- a/src/slow_hash.rs +++ b/src/slow_hash.rs @@ -3,17 +3,22 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. +//! Trait specifying a slow hashing function + use crate::errors::InternalPakeError; use generic_array::GenericArray; use sha2::{Digest, Sha256}; +/// Used for the slow hashing function in OPAQUE pub trait SlowHash { + /// Computes the slow hashing function fn hash( input: GenericArray::OutputSize>, ) -> Result, InternalPakeError>; } +/// A no-op hash which simply returns its input pub struct NoOpHash; impl SlowHash for NoOpHash { diff --git a/src/tests/opaque_ke_test.rs b/src/tests/opaque_ke_test.rs index a9d666a..2696a83 100644 --- a/src/tests/opaque_ke_test.rs +++ b/src/tests/opaque_ke_test.rs @@ -4,12 +4,12 @@ // LICENSE file in the root directory of this source tree. use crate::{ + ciphersuite::CipherSuite, errors::*, group::Group, key_exchange::NONCE_LEN, - keypair::{Key, KeyPair, X25519KeyPair}, + keypair::{Key, KeyPair}, opaque::*, - slow_hash::NoOpHash, tests::mock_rng::CycleRng, }; use aes_gcm::Aes256Gcm; @@ -21,6 +21,14 @@ use std::convert::TryFrom; // Tests // ===== +struct AesgcmX255193dhNoSlowHash; +impl CipherSuite for AesgcmX255193dhNoSlowHash { + type Aead = Aes256Gcm; + type Group = EdwardsPoint; + type KeyFormat = crate::keypair::X25519KeyPair; + type SlowHash = crate::slow_hash::NoOpHash; +} + pub struct TestVectorParameters { pub client_s_pk: Vec, pub client_s_sk: Vec, @@ -215,10 +223,10 @@ fn generate_parameters() -> TestVectorParameters { let mut rng = OsRng; // Inputs - let server_s_kp = X25519KeyPair::generate_random(&mut rng).unwrap(); - let server_e_kp = X25519KeyPair::generate_random(&mut rng).unwrap(); - let client_s_kp = X25519KeyPair::generate_random(&mut rng).unwrap(); - let client_e_kp = X25519KeyPair::generate_random(&mut rng).unwrap(); + let server_s_kp = AesgcmX255193dhNoSlowHash::generate_random_keypair(&mut rng).unwrap(); + let server_e_kp = AesgcmX255193dhNoSlowHash::generate_random_keypair(&mut rng).unwrap(); + let client_s_kp = AesgcmX255193dhNoSlowHash::generate_random_keypair(&mut rng).unwrap(); + let client_e_kp = AesgcmX255193dhNoSlowHash::generate_random_keypair(&mut rng).unwrap(); let password = b"password"; let pepper = b"pepper"; let mut blinding_factor_raw = [0u8; 64]; @@ -233,7 +241,7 @@ fn generate_parameters() -> TestVectorParameters { rng.fill_bytes(&mut server_nonce); let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_raw.to_vec()); - let (r1, client_registration) = ClientRegistration::::start( + let (r1, client_registration) = ClientRegistration::::start( password, Some(pepper), &mut blinding_factor_registration_rng, @@ -245,8 +253,7 @@ fn generate_parameters() -> TestVectorParameters { let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec()); let (r2, server_registration) = - ServerRegistration::::start(r1, &mut oprf_key_rng) - .unwrap(); + ServerRegistration::::start(r1, &mut oprf_key_rng).unwrap(); let r2_bytes = r2.to_bytes().to_vec(); let oprf_key = server_registration.oprf_key; let oprf_key_bytes = EdwardsPoint::scalar_as_bytes(&oprf_key); @@ -258,11 +265,7 @@ fn generate_parameters() -> TestVectorParameters { let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce); let (r3, opaque_key_registration) = client_registration - .finish::<_, X25519KeyPair, NoOpHash>( - r2, - server_s_kp.public(), - &mut finish_registration_rng, - ) + .finish(r2, server_s_kp.public(), &mut finish_registration_rng) .unwrap(); let r3_bytes = r3.to_bytes().to_vec(); @@ -275,7 +278,7 @@ fn generate_parameters() -> TestVectorParameters { client_login_start.extend_from_slice(&client_nonce); let mut client_login_start_rng = CycleRng::new(client_login_start); - let (l1, client_login) = ClientLogin::::start( + let (l1, client_login) = ClientLogin::::start( password, Some(pepper), &mut client_login_start_rng, @@ -297,7 +300,7 @@ fn generate_parameters() -> TestVectorParameters { let mut client_e_sk_rng = CycleRng::new(client_e_kp.private().to_vec()); let (l3, client_shared_secret, _opaque_key_login) = client_login - .finish::<_, NoOpHash>(l2, server_s_kp.public(), &mut client_e_sk_rng) + .finish(l2, server_s_kp.public(), &mut client_e_sk_rng) .unwrap(); let l3_bytes = l3.to_bytes().to_vec(); @@ -344,7 +347,7 @@ fn generate_test_vectors() { fn test_r1() -> Result<(), PakeError> { let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); let mut blinding_factor_rng = CycleRng::new(parameters.blinding_factor_raw); - let (r1, client_registration) = ClientRegistration::::start( + let (r1, client_registration) = ClientRegistration::::start( ¶meters.password, Some(¶meters.pepper), &mut blinding_factor_rng, @@ -362,12 +365,11 @@ fn test_r1() -> Result<(), PakeError> { fn test_r2() -> Result<(), PakeError> { let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); let mut oprf_key_rng = CycleRng::new(parameters.oprf_key); - let (r2, server_registration) = - ServerRegistration::::start( - RegisterFirstMessage::try_from(¶meters.r1[..]).unwrap(), - &mut oprf_key_rng, - ) - .unwrap(); + let (r2, server_registration) = ServerRegistration::::start( + RegisterFirstMessage::try_from(¶meters.r1[..]).unwrap(), + &mut oprf_key_rng, + ) + .unwrap(); assert_eq!(hex::encode(parameters.r2), hex::encode(r2.to_bytes())); assert_eq!( hex::encode(¶meters.server_registration_state), @@ -383,11 +385,11 @@ fn test_r3() -> Result<(), PakeError> { let client_s_sk_and_nonce: Vec = [parameters.client_s_sk, parameters.envelope_nonce].concat(); let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce); - let (r3, opaque_key_registration) = ClientRegistration::::try_from( + let (r3, opaque_key_registration) = ClientRegistration::::try_from( ¶meters.client_registration_state[..], ) .unwrap() - .finish::( + .finish( RegisterSecondMessage::try_from(¶meters.r2[..]).unwrap(), &Key::try_from(parameters.server_s_pk).unwrap(), &mut finish_registration_rng, @@ -407,11 +409,10 @@ fn test_r3() -> Result<(), PakeError> { fn test_password_file() -> Result<(), PakeError> { let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); - let server_registration = - ServerRegistration::::try_from( - ¶meters.server_registration_state[..], - ) - .unwrap(); + let server_registration = ServerRegistration::::try_from( + ¶meters.server_registration_state[..], + ) + .unwrap(); let password_file = server_registration .finish(RegisterThirdMessage::try_from(¶meters.r3[..]).unwrap()) .unwrap(); @@ -434,7 +435,7 @@ fn test_l1() -> Result<(), PakeError> { ] .concat(); let mut client_login_start_rng = CycleRng::new(client_login_start); - let (l1, client_login) = ClientLogin::::start( + let (l1, client_login) = ClientLogin::::start( ¶meters.password, Some(¶meters.pepper), &mut client_login_start_rng, @@ -453,7 +454,7 @@ fn test_l2() -> Result<(), PakeError> { let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); let mut server_e_sk_rng = CycleRng::new(parameters.server_e_sk); - let (l2, server_login) = ServerLogin::start::<_, Aes256Gcm, _, X25519KeyPair>( + let (l2, server_login) = ServerLogin::start::( ServerRegistration::try_from(¶meters.password_file[..]).unwrap(), &Key::try_from(parameters.server_s_sk).unwrap(), LoginFirstMessage::::try_from(¶meters.l1[..]).unwrap(), @@ -475,16 +476,15 @@ fn test_l3() -> Result<(), PakeError> { let mut client_e_sk_rng = CycleRng::new(parameters.client_e_sk.to_vec()); let (l3, shared_secret, opaque_key_login) = - ClientLogin::::try_from( - ¶meters.client_login_state[..], - ) - .unwrap() - .finish::<_, NoOpHash>( - LoginSecondMessage::::try_from(¶meters.l2[..]).unwrap(), - &Key::try_from(parameters.server_s_pk)?, - &mut client_e_sk_rng, - ) - .unwrap(); + ClientLogin::::try_from(¶meters.client_login_state[..]) + .unwrap() + .finish( + LoginSecondMessage::::try_from(¶meters.l2[..]) + .unwrap(), + &Key::try_from(parameters.server_s_pk)?, + &mut client_e_sk_rng, + ) + .unwrap(); assert_eq!( hex::encode(¶meters.shared_secret), @@ -522,31 +522,24 @@ fn test_complete_flow( ) -> Result<(), ProtocolError> { let mut client_rng = OsRng; let mut server_rng = OsRng; - let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - let (register_m1, client_state) = ClientRegistration::::start( + let server_kp = AesgcmX255193dhNoSlowHash::generate_random_keypair(&mut server_rng)?; + let (register_m1, client_state) = ClientRegistration::::start( registration_password, None, &mut client_rng, )?; let (register_m2, server_state) = - ServerRegistration::::start( - register_m1, - &mut server_rng, - )?; + ServerRegistration::::start(register_m1, &mut server_rng)?; let (register_m3, registration_opaque_key) = - client_state.finish::<_, _, NoOpHash>(register_m2, server_kp.public(), &mut client_rng)?; + client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; let p_file = server_state.finish(register_m3)?; let (login_m1, client_login_state) = - ClientLogin::::start( - login_password, - None, - &mut client_rng, - )?; + ClientLogin::::start(login_password, None, &mut client_rng)?; let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; let client_login_result = - client_login_state.finish::<_, NoOpHash>(login_m2, &server_kp.public(), &mut client_rng); + client_login_state.finish(login_m2, &server_kp.public(), &mut client_rng); if hex::encode(registration_password) == hex::encode(login_password) { let (login_m3, client_shared_secret, login_opaque_key) = client_login_result?; diff --git a/src/tests/serialization.rs b/src/tests/serialization.rs index 4c37fdb..ab11285 100644 --- a/src/tests/serialization.rs +++ b/src/tests/serialization.rs @@ -4,6 +4,7 @@ // LICENSE file in the root directory of this source tree. use crate::{ + ciphersuite::CipherSuite, group::Group, keypair::{KeyPair, SizedBytes, X25519KeyPair}, opaque::*, @@ -16,6 +17,14 @@ use chacha20poly1305::ChaCha20Poly1305; use rand_core::{OsRng, RngCore}; use std::convert::TryFrom; +struct Default; +impl CipherSuite for Default { + type Aead = ChaCha20Poly1305; + type Group = RistrettoPoint; + type KeyFormat = crate::keypair::X25519KeyPair; + type SlowHash = crate::slow_hash::NoOpHash; +} + fn random_ristretto_point() -> RistrettoPoint { let mut rng = OsRng; let mut bits = [0u8; 64]; @@ -30,7 +39,7 @@ fn client_registration_roundtrip() { let sc = ::random_scalar(&mut rng); // serialization order: scalar, password let bytes: Vec = [&sc.as_bytes()[..], &pw[..]].concat(); - let reg = ClientRegistration::::try_from(&bytes[..]).unwrap(); + let reg = ClientRegistration::::try_from(&bytes[..]).unwrap(); let reg_bytes = reg.to_bytes(); assert_eq!(reg_bytes, bytes); } @@ -43,7 +52,7 @@ fn server_registration_roundtrip() { let sc = ::random_scalar(&mut rng); let mut oprf_bytes: Vec = vec![]; oprf_bytes.extend_from_slice(sc.as_bytes()); - let reg = ServerRegistration::::try_from( + let reg = ServerRegistration::::try_from( &oprf_bytes[..], ) .unwrap(); @@ -55,14 +64,14 @@ fn server_registration_roundtrip() { let mut mock_rkr_bytes = vec![0u8; rkr_size]; rng.fill_bytes(&mut mock_rkr_bytes); println!("{}", mock_rkr_bytes.len()); - let mock_client_kp = X25519KeyPair::generate_random(&mut rng).unwrap(); + let mock_client_kp = Default::generate_random_keypair(&mut rng).unwrap(); // serialization order: scalar, public key, envelope let mut bytes = Vec::::new(); bytes.extend_from_slice(sc.as_bytes()); bytes.extend_from_slice(&mock_client_kp.public().to_arr()); bytes.extend_from_slice(&mock_rkr_bytes); let reg = - ServerRegistration::::try_from(&bytes[..]) + ServerRegistration::::try_from(&bytes[..]) .unwrap(); let reg_bytes = reg.to_bytes(); assert_eq!(reg_bytes, bytes); @@ -91,7 +100,7 @@ fn register_second_message_roundtrip() { #[test] fn register_third_message_roundtrip() { let mut rng = OsRng; - let skp = X25519KeyPair::generate_random(&mut rng).unwrap(); + let skp = Default::generate_random_keypair(&mut rng).unwrap(); let pubkey_bytes = skp.public().to_arr(); let mut encryption_key = [0u8; 32];