Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba8e940e08 | ||
|
|
ac08801f18 | ||
|
|
a49e089e54 | ||
|
|
37f98b3742 | ||
|
|
fa0fb48654 | ||
|
|
4da6bbce0c | ||
|
|
a457d82793 | ||
|
|
782eeb7090 | ||
|
|
bb7d17a102 | ||
|
|
7f84984f61 |
@@ -2,7 +2,6 @@ name: Rust CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- tls
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, repoened, synchronize]
|
||||
@@ -16,16 +15,19 @@ jobs:
|
||||
backend_feature:
|
||||
- u64_backend
|
||||
- u32_backend
|
||||
toolchain:
|
||||
- nightly
|
||||
- 1.41.0
|
||||
name: test
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install nightly toolchain
|
||||
- name: Install ${{ matrix.toolchain }} toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
@@ -75,6 +77,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolchain:
|
||||
- nightly
|
||||
- 1.41.0
|
||||
name: test simple_login command-line example
|
||||
steps:
|
||||
- name: install expect
|
||||
@@ -85,7 +91,7 @@ jobs:
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- name: Run expect (which then runs cargo run)
|
||||
@@ -95,6 +101,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolchain:
|
||||
- nightly
|
||||
- 1.41.0
|
||||
name: test digital_locker command-line example
|
||||
steps:
|
||||
- name: install expect
|
||||
@@ -105,7 +115,7 @@ jobs:
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- name: Run expect (which then runs cargo run)
|
||||
@@ -118,7 +128,7 @@ jobs:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install nightly toolchain
|
||||
- name: Install stable toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.0 (March 1, 2020)
|
||||
|
||||
* Removed dependency on generic-bytes-derive package
|
||||
|
||||
## 0.4.0 (February 26, 2020)
|
||||
|
||||
* Adherence to protocol format described in
|
||||
https://tools.ietf.org/html/draft-irtf-cfrg-opaque-03
|
||||
* Renamed to_bytes() and try_from() to serialize() and deserialize() for
|
||||
top-level structs
|
||||
* Conformed all message type parameters to be parameterized in the
|
||||
Ciphersuite object
|
||||
|
||||
## 0.3.1 (February 11, 2020)
|
||||
|
||||
* Re-exporting the rand library (and including it as a dependency instead of
|
||||
|
||||
Generated
+35
-53
@@ -109,6 +109,12 @@ version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
@@ -218,7 +224,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
@@ -228,7 +234,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
@@ -239,7 +245,7 @@ version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"const_fn",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
@@ -254,7 +260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
@@ -314,11 +320,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
checksum = "cf36e65a80337bea855cd4ef9b8401ffce06a7baedf2e85ec467b1ac3f6e82b6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
@@ -356,16 +362,6 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
@@ -385,24 +381,13 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-bytes-derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4257fe99e64e321c197164da8ae22f7a3c074a5b2519072866e2d38bc1ca59e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
@@ -413,7 +398,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
@@ -510,7 +495,7 @@ version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -530,13 +515,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.19.1"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2"
|
||||
checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -573,7 +558,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-ke"
|
||||
version = "0.3.1"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
@@ -584,7 +569,6 @@ dependencies = [
|
||||
"displaydoc",
|
||||
"generic-array",
|
||||
"generic-bytes",
|
||||
"generic-bytes-derive",
|
||||
"hex",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
@@ -690,9 +674,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -718,7 +702,7 @@ checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.0",
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
"rand_hc 0.3.0",
|
||||
]
|
||||
|
||||
@@ -739,7 +723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -753,9 +737,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
|
||||
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
]
|
||||
@@ -775,7 +759,7 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||
dependencies = [
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -814,9 +798,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -887,14 +871,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
version = "7.1.0"
|
||||
version = "6.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8227301bfc717136f0ecbd3d064ba8199e44497a0bdd46bb01ede4387cfd2cec"
|
||||
checksum = "6f0d5e7b0219a3eadd5439498525d4765c59b7c993ef0c12244865cd2d988413"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"dirs-next",
|
||||
"fs2",
|
||||
"libc",
|
||||
"log",
|
||||
"memchr",
|
||||
@@ -1012,7 +994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"cpuid-bool 0.1.2",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
@@ -1041,7 +1023,7 @@ version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"rand 0.8.3",
|
||||
"redox_syscall",
|
||||
@@ -1172,7 +1154,7 @@ version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
|
||||
+3
-4
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "opaque-ke"
|
||||
version = "0.3.1"
|
||||
version = "0.5.0"
|
||||
repository = "https://github.com/novifinancial/opaque-ke"
|
||||
keywords = ["cryptography", "crypto", "opaque", "passwords", "authentication"]
|
||||
description = "An implementation of the OPAQUE password-authenticated key exchange protocol"
|
||||
@@ -22,10 +22,9 @@ digest = "0.9.0"
|
||||
displaydoc = "0.1.7"
|
||||
generic-array = "0.14.4"
|
||||
generic-bytes = { version = "0.1.0" }
|
||||
generic-bytes-derive = { version = "0.1.0" }
|
||||
hkdf = "0.10.0"
|
||||
hmac = "0.10.1"
|
||||
rand = "0.8.3"
|
||||
rand = "0.8"
|
||||
scrypt = { version = "0.5.0", optional = true }
|
||||
subtle = { version = "2.3.0", default-features = false }
|
||||
thiserror = "1.0.22"
|
||||
@@ -41,7 +40,7 @@ lazy_static = "1.4.0"
|
||||
serde_json = "1.0.60"
|
||||
sha2 = "0.9.2"
|
||||
proptest = "0.10.1"
|
||||
rustyline = "7.0.0"
|
||||
rustyline = "6.3.0"
|
||||
|
||||
[[bench]]
|
||||
name = "oprf"
|
||||
|
||||
@@ -22,14 +22,14 @@ Installation
|
||||
Add the following line to the dependencies of your `Cargo.toml`:
|
||||
|
||||
```
|
||||
opaque-ke = "0.3.1"
|
||||
opaque-ke = "0.5.0"
|
||||
```
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
- [OPAQUE academic publication](https://eprint.iacr.org/2018/163.pdf), including formal definitions and a proof of security
|
||||
- [draft-irtf-cfrg-opaque-02](https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-02.html), containing a detailed (byte-level) specification for OPAQUE
|
||||
- [draft-irtf-cfrg-opaque-03](https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-03.html), containing a detailed (byte-level) specification for OPAQUE
|
||||
- ["Let's talk about PAKE"](https://blog.cryptographyengineering.com/2018/10/19/lets-talk-about-pake/), an introductory blog post written by Matthew Green that covers OPAQUE
|
||||
|
||||
Contributors
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use generic_array::arr;
|
||||
use opaque_ke::{
|
||||
group::Group,
|
||||
oprf::{blind_shim, evaluate_shim, unblind_and_finalize_shim},
|
||||
oprf::{blind_shim, evaluate_shim, finalize_shim},
|
||||
};
|
||||
use rand::{prelude::ThreadRng, thread_rng};
|
||||
use sha2::Sha512;
|
||||
@@ -57,9 +57,9 @@ fn oprf3(c: &mut Criterion) {
|
||||
let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap();
|
||||
let beta = evaluate_shim::<RistrettoPoint>(alpha, &salt);
|
||||
|
||||
c.bench_function("unblind_and_finalize with Ristretto", move |b| {
|
||||
c.bench_function("finalize with Ristretto", move |b| {
|
||||
b.iter(|| {
|
||||
let _res = unblind_and_finalize_shim::<RistrettoPoint, Sha512>(&token, beta).unwrap();
|
||||
let _res = finalize_shim::<RistrettoPoint, Sha512>(&token, beta).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ targets = [
|
||||
# The path where the advisory database is cloned/fetched into
|
||||
db-path = "~/.cargo/advisory-db"
|
||||
# The url of the advisory database to use
|
||||
db-url = "https://github.com/rustsec/advisory-db"
|
||||
db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||
# The lint level for security vulnerabilities
|
||||
vulnerability = "deny"
|
||||
# The lint level for unmaintained crates
|
||||
|
||||
@@ -28,7 +28,6 @@ use chacha20poly1305::aead::{Aead, NewAead};
|
||||
use chacha20poly1305::{ChaCha20Poly1305, Key, Nonce};
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
use std::convert::TryFrom;
|
||||
use std::process::exit;
|
||||
|
||||
use opaque_ke::{
|
||||
@@ -129,7 +128,7 @@ fn register_locker(
|
||||
|
||||
Locker {
|
||||
contents: ciphertext,
|
||||
password_file: password_file.to_bytes(),
|
||||
password_file: password_file.serialize(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +149,8 @@ fn open_locker(
|
||||
|
||||
// Client sends credential_request_bytes to server
|
||||
|
||||
let password_file = ServerRegistration::<Default>::try_from(&locker.password_file[..]).unwrap();
|
||||
let password_file =
|
||||
ServerRegistration::<Default>::deserialize(&locker.password_file[..]).unwrap();
|
||||
let mut server_rng = OsRng;
|
||||
let server_login_start_result = ServerLogin::start(
|
||||
&mut server_rng,
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::process::exit;
|
||||
|
||||
use opaque_ke::{
|
||||
@@ -84,7 +83,7 @@ fn account_registration(
|
||||
.state
|
||||
.finish(RegistrationUpload::deserialize(&message_bytes[..]).unwrap())
|
||||
.unwrap();
|
||||
password_file.to_bytes()
|
||||
password_file.serialize()
|
||||
}
|
||||
|
||||
// Password-based login between a client and server
|
||||
@@ -104,7 +103,7 @@ fn account_login(
|
||||
|
||||
// Client sends credential_request_bytes to server
|
||||
|
||||
let password_file = ServerRegistration::<Default>::try_from(password_file_bytes).unwrap();
|
||||
let password_file = ServerRegistration::<Default>::deserialize(password_file_bytes).unwrap();
|
||||
let mut server_rng = OsRng;
|
||||
let server_login_start_result = ServerLogin::start(
|
||||
&mut server_rng,
|
||||
|
||||
+15
-27
@@ -6,10 +6,12 @@
|
||||
use crate::{
|
||||
errors::{utils::check_slice_size_atleast, InternalPakeError, PakeError, ProtocolError},
|
||||
hash::Hash,
|
||||
serialization::{serialize, tokenize},
|
||||
keypair::Key,
|
||||
serialization::serialize,
|
||||
};
|
||||
use digest::Digest;
|
||||
use generic_array::{typenum::Unsigned, GenericArray};
|
||||
use generic_bytes::SizedBytes;
|
||||
use hkdf::Hkdf;
|
||||
use hmac::{Hmac, Mac, NewMac};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
@@ -47,12 +49,7 @@ pub(crate) struct InnerEnvelope {
|
||||
|
||||
impl InnerEnvelope {
|
||||
pub(crate) fn serialize(&self) -> Vec<u8> {
|
||||
[
|
||||
&[self.mode as u8],
|
||||
&self.nonce[..],
|
||||
&serialize(&self.ciphertext, 2)[..],
|
||||
]
|
||||
.concat()
|
||||
[&[self.mode as u8], &self.nonce[..], &self.ciphertext[..]].concat()
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize(input: &[u8]) -> Result<(Self, Vec<u8>), ProtocolError> {
|
||||
@@ -63,23 +60,22 @@ impl InnerEnvelope {
|
||||
}
|
||||
let mode = InnerEnvelopeMode::try_from(input[0])?;
|
||||
|
||||
let key_len = <Key as SizedBytes>::Len::to_usize();
|
||||
|
||||
let bytes = &input[1..];
|
||||
if bytes.len() < NONCE_LEN {
|
||||
if bytes.len() < NONCE_LEN + key_len {
|
||||
return Err(ProtocolError::VerificationError(
|
||||
PakeError::SerializationError,
|
||||
));
|
||||
}
|
||||
|
||||
let nonce = &bytes[..NONCE_LEN];
|
||||
let (ciphertext, remainder) = tokenize(&bytes[NONCE_LEN..], 2)?;
|
||||
|
||||
Ok((
|
||||
Self {
|
||||
mode,
|
||||
nonce: nonce.to_vec(),
|
||||
ciphertext,
|
||||
nonce: bytes[..NONCE_LEN].to_vec(),
|
||||
ciphertext: bytes[NONCE_LEN..NONCE_LEN + key_len].to_vec(),
|
||||
},
|
||||
remainder,
|
||||
bytes[NONCE_LEN + key_len..].to_vec(),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -113,11 +109,6 @@ pub(crate) struct OpenedInnerEnvelope<D: Hash> {
|
||||
}
|
||||
|
||||
impl<D: Hash> Envelope<D> {
|
||||
/// The additional number of bytes added to the plaintext
|
||||
pub(crate) fn additional_size() -> usize {
|
||||
NONCE_LEN + <D as Digest>::OutputSize::to_usize()
|
||||
}
|
||||
|
||||
fn hmac_key_size() -> usize {
|
||||
<D as Digest>::OutputSize::to_usize()
|
||||
}
|
||||
@@ -173,9 +164,8 @@ impl<D: Hash> Envelope<D> {
|
||||
server_s_pk: &[u8],
|
||||
optional_ids: Option<(Vec<u8>, Vec<u8>)>,
|
||||
) -> Result<(Self, GenericArray<u8, <D as Digest>::OutputSize>), InternalPakeError> {
|
||||
let plaintext = serialize(&client_s_sk, 2);
|
||||
let aad = construct_aad(server_s_pk, &optional_ids);
|
||||
Self::seal_raw(rng, key, &plaintext, &aad, mode_from_ids(&optional_ids))
|
||||
Self::seal_raw(rng, key, &client_s_sk, &aad, mode_from_ids(&optional_ids))
|
||||
}
|
||||
|
||||
/// Uses a key to convert the plaintext into an envelope, authenticated by the aad field.
|
||||
@@ -244,15 +234,13 @@ impl<D: Hash> Envelope<D> {
|
||||
let aad = construct_aad(server_s_pk, optional_ids);
|
||||
let opened = self.open_raw(key, &aad)?;
|
||||
|
||||
let (client_s_sk, remainder) = tokenize(&opened.plaintext, 2)
|
||||
.map_err(|_| InternalPakeError::UnexpectedEnvelopeContentsError)?;
|
||||
if !remainder.is_empty() {
|
||||
// Should not have anything else in plaintext
|
||||
if opened.plaintext.len() != <Key as SizedBytes>::Len::to_usize() {
|
||||
// Plaintext should consist of a single key
|
||||
return Err(InternalPakeError::UnexpectedEnvelopeContentsError);
|
||||
}
|
||||
|
||||
Ok(OpenedEnvelope {
|
||||
client_s_sk,
|
||||
client_s_sk: opened.plaintext,
|
||||
export_key: opened.export_key,
|
||||
})
|
||||
}
|
||||
@@ -305,7 +293,7 @@ fn construct_aad(server_s_pk: &[u8], optional_ids: &Option<(Vec<u8>, Vec<u8>)>)
|
||||
.iter()
|
||||
.flat_map(|(l, r)| [serialize(l, 2), serialize(r, 2)].concat())
|
||||
.collect();
|
||||
[serialize(server_s_pk, 2), ids].concat()
|
||||
[server_s_pk.to_vec(), ids].concat()
|
||||
}
|
||||
|
||||
pub(crate) fn mode_from_ids(optional_ids: &Option<(Vec<u8>, Vec<u8>)>) -> InnerEnvelopeMode {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ use zeroize::Zeroize;
|
||||
|
||||
/// A prime-order subgroup of a base field (EC, prime-order field ...). This
|
||||
/// subgroup is noted additively — as in the draft RFC — in this trait.
|
||||
pub trait Group: Sized + for<'a> Mul<&'a <Self as Group>::Scalar, Output = Self> {
|
||||
pub trait Group: Copy + Sized + for<'a> Mul<&'a <Self as Group>::Scalar, Output = Self> {
|
||||
/// The type of base field scalars
|
||||
type Scalar: Zeroize + Clone;
|
||||
/// The byte length necessary to represent scalars
|
||||
|
||||
@@ -30,13 +30,13 @@ use std::convert::TryFrom;
|
||||
const KEY_LEN: usize = 32;
|
||||
pub(crate) type NonceLen = U32;
|
||||
|
||||
static STR_3DH: &[u8] = b"3DH keys";
|
||||
static STR_3DH: &[u8] = b"3DH";
|
||||
static STR_CLIENT_MAC: &[u8] = b"client mac";
|
||||
static STR_HANDSHAKE_SECRET: &[u8] = b"handshake secret";
|
||||
static STR_SERVER_MAC: &[u8] = b"server mac";
|
||||
static STR_SERVER_ENC: &[u8] = b"handshake enc";
|
||||
static STR_HANDSHAKE_ENC: &[u8] = b"handshake enc";
|
||||
static STR_ENCRYPTION_PAD: &[u8] = b"encryption pad";
|
||||
static STR_SESSION_KEY: &[u8] = b"session secret";
|
||||
static STR_SESSION_SECRET: &[u8] = b"session secret";
|
||||
static STR_OPAQUE: &[u8] = b"OPAQUE ";
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
@@ -55,11 +55,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
rng: &mut R,
|
||||
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> {
|
||||
let client_e_kp = KeyPair::<G>::generate_random(rng);
|
||||
let client_nonce: GenericArray<u8, NonceLen> = {
|
||||
let mut client_nonce_bytes = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut client_nonce_bytes);
|
||||
GenericArray::clone_from_slice(&client_nonce_bytes)
|
||||
};
|
||||
let client_nonce = generate_nonce::<R>(rng);
|
||||
|
||||
let ke1_message = Ke1Message {
|
||||
client_nonce,
|
||||
@@ -89,11 +85,16 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
e_info: Vec<u8>,
|
||||
) -> Result<(Vec<u8>, Self::KE2State, Self::KE2Message), ProtocolError> {
|
||||
let server_e_kp = KeyPair::<G>::generate_random(rng);
|
||||
let server_nonce: GenericArray<u8, NonceLen> = {
|
||||
let mut server_nonce_bytes = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut server_nonce_bytes);
|
||||
GenericArray::clone_from_slice(&server_nonce_bytes)
|
||||
};
|
||||
let server_nonce = generate_nonce::<R>(rng);
|
||||
|
||||
let mut transcript_hasher = D::new()
|
||||
.chain(STR_3DH)
|
||||
.chain(&serialize(&id_u, 2))
|
||||
.chain(&serialized_credential_request[..])
|
||||
.chain(&serialize(&id_s, 2))
|
||||
.chain(&l2_bytes[..])
|
||||
.chain(&server_nonce[..])
|
||||
.chain(&server_e_kp.public().to_arr());
|
||||
|
||||
let (session_key, km2, ke2, km3) = derive_3dh_keys::<D, G>(
|
||||
TripleDHComponents {
|
||||
@@ -104,10 +105,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
pk3: client_s_pk,
|
||||
sk3: server_e_kp.private().clone(),
|
||||
},
|
||||
&ke1_message.client_nonce,
|
||||
&server_nonce,
|
||||
&id_u,
|
||||
&id_s,
|
||||
&transcript_hasher.clone().finalize(),
|
||||
)?;
|
||||
|
||||
// Compute encryption of e_info
|
||||
@@ -121,33 +119,20 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
.map(|(&x1, &x2)| x1 ^ x2)
|
||||
.collect();
|
||||
|
||||
let transcript2: Vec<u8> = [
|
||||
&serialized_credential_request[..],
|
||||
&l2_bytes[..],
|
||||
&server_nonce[..],
|
||||
&server_e_kp.public().to_arr(),
|
||||
&serialize(&ciphertext, 2),
|
||||
]
|
||||
.concat();
|
||||
|
||||
let mut hasher = D::new();
|
||||
hasher.update(&transcript2);
|
||||
let hashed_transcript_without_mac = hasher.finalize_reset();
|
||||
transcript_hasher.update(&serialize(&ciphertext, 2));
|
||||
|
||||
let mut mac_hasher =
|
||||
Hmac::<D>::new_varkey(&km2).map_err(|_| InternalPakeError::HmacError)?;
|
||||
mac_hasher.update(&hashed_transcript_without_mac);
|
||||
mac_hasher.update(&transcript_hasher.clone().finalize());
|
||||
let mac = mac_hasher.finalize().into_bytes();
|
||||
|
||||
hasher.update(&transcript2);
|
||||
hasher.update(&mac);
|
||||
let hashed_transcript = hasher.finalize();
|
||||
transcript_hasher.update(&mac);
|
||||
|
||||
Ok((
|
||||
ke1_message.info,
|
||||
Ke2State {
|
||||
km3,
|
||||
hashed_transcript,
|
||||
hashed_transcript: transcript_hasher.finalize(),
|
||||
session_key,
|
||||
},
|
||||
Ke2Message {
|
||||
@@ -170,6 +155,14 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
id_u: Vec<u8>,
|
||||
id_s: Vec<u8>,
|
||||
) -> Result<(Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError> {
|
||||
let mut transcript_hasher = D::new()
|
||||
.chain(STR_3DH)
|
||||
.chain(&serialize(&id_u, 2))
|
||||
.chain(&serialized_credential_request)
|
||||
.chain(&serialize(&id_s, 2))
|
||||
.chain(&l2_component[..])
|
||||
.chain(&ke2_message.to_bytes_without_info_or_mac());
|
||||
|
||||
let (session_key, km2, ke2, km3) = derive_3dh_keys::<D, G>(
|
||||
TripleDHComponents {
|
||||
pk1: ke2_message.server_e_pk.clone(),
|
||||
@@ -179,26 +172,14 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
pk3: ke2_message.server_e_pk.clone(),
|
||||
sk3: client_s_sk,
|
||||
},
|
||||
&ke1_state.client_nonce,
|
||||
&ke2_message.server_nonce,
|
||||
&id_u,
|
||||
&id_s,
|
||||
&transcript_hasher.clone().finalize(),
|
||||
)?;
|
||||
|
||||
let transcript: Vec<u8> = [
|
||||
&serialized_credential_request,
|
||||
&l2_component[..],
|
||||
&ke2_message.to_bytes_without_mac(),
|
||||
]
|
||||
.concat();
|
||||
|
||||
let mut hasher = D::new();
|
||||
hasher.update(&transcript);
|
||||
let hashed_transcript_without_mac = hasher.finalize_reset();
|
||||
transcript_hasher.update(&serialize(&ke2_message.e_info[..], 2));
|
||||
|
||||
let mut server_mac =
|
||||
Hmac::<D>::new_varkey(&km2).map_err(|_| InternalPakeError::HmacError)?;
|
||||
server_mac.update(&hashed_transcript_without_mac);
|
||||
server_mac.update(&transcript_hasher.clone().finalize());
|
||||
|
||||
if ke2_message.mac != server_mac.finalize().into_bytes() {
|
||||
return Err(ProtocolError::VerificationError(
|
||||
@@ -206,13 +187,11 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
));
|
||||
}
|
||||
|
||||
hasher.update(transcript);
|
||||
hasher.update(ke2_message.mac.to_vec());
|
||||
let hashed_transcript = hasher.finalize();
|
||||
transcript_hasher.update(ke2_message.mac.to_vec());
|
||||
|
||||
let mut client_mac =
|
||||
Hmac::<D>::new_varkey(&km3).map_err(|_| InternalPakeError::HmacError)?;
|
||||
client_mac.update(&hashed_transcript);
|
||||
client_mac.update(&transcript_hasher.finalize());
|
||||
|
||||
// Compute decryption of e_info
|
||||
let h = Hkdf::<D>::from_prk(&ke2).map_err(|_| InternalPakeError::HkdfError)?;
|
||||
@@ -370,18 +349,18 @@ impl<HashLen: ArrayLength<u8>> TryFrom<&[u8]> for Ke2State<HashLen> {
|
||||
|
||||
impl<HashLen: ArrayLength<u8>> ToBytes for Ke2Message<HashLen> {
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
[&self.to_bytes_without_mac(), &self.mac[..]].concat()
|
||||
[
|
||||
&self.to_bytes_without_info_or_mac(),
|
||||
&serialize(&self.e_info, 2),
|
||||
&self.mac[..],
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
}
|
||||
|
||||
impl<HashLen: ArrayLength<u8>> Ke2Message<HashLen> {
|
||||
fn to_bytes_without_mac(&self) -> Vec<u8> {
|
||||
[
|
||||
&self.server_nonce[..],
|
||||
&self.server_e_pk.to_arr(),
|
||||
&serialize(&self.e_info, 2),
|
||||
]
|
||||
.concat()
|
||||
fn to_bytes_without_info_or_mac(&self) -> Vec<u8> {
|
||||
[&self.server_nonce[..], &self.server_e_pk.to_arr()].concat()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,10 +436,7 @@ impl<HashLen: ArrayLength<u8>> TryFrom<&[u8]> for Ke3Message<HashLen> {
|
||||
// with some auxiliary metadata, to produce the session key and two MAC keys
|
||||
fn derive_3dh_keys<D: Hash, G: Group>(
|
||||
dh: TripleDHComponents,
|
||||
client_nonce: &GenericArray<u8, NonceLen>,
|
||||
server_nonce: &GenericArray<u8, NonceLen>,
|
||||
id_u: &[u8],
|
||||
id_s: &[u8],
|
||||
hashed_derivation_transcript: &[u8],
|
||||
) -> Result<TripleDHDerivationResult<D>, ProtocolError> {
|
||||
let ikm: Vec<u8> = [
|
||||
&KeyPair::<G>::diffie_hellman(dh.pk1, dh.sk1)?[..],
|
||||
@@ -469,18 +445,17 @@ fn derive_3dh_keys<D: Hash, G: Group>(
|
||||
]
|
||||
.concat();
|
||||
|
||||
let info: Vec<u8> = [
|
||||
STR_3DH,
|
||||
&serialize(&client_nonce, 2),
|
||||
&serialize(&server_nonce, 2),
|
||||
&serialize(id_u, 2),
|
||||
&serialize(id_s, 2),
|
||||
]
|
||||
.concat();
|
||||
|
||||
let extracted_ikm = Hkdf::<D>::new(None, &ikm);
|
||||
let handshake_secret = derive_secrets::<D>(&extracted_ikm, &STR_HANDSHAKE_SECRET, &info)?;
|
||||
let session_key = derive_secrets::<D>(&extracted_ikm, &STR_SESSION_KEY, &info)?;
|
||||
let handshake_secret = derive_secrets::<D>(
|
||||
&extracted_ikm,
|
||||
&STR_HANDSHAKE_SECRET,
|
||||
&hashed_derivation_transcript,
|
||||
)?;
|
||||
let session_key = derive_secrets::<D>(
|
||||
&extracted_ikm,
|
||||
&STR_SESSION_SECRET,
|
||||
&hashed_derivation_transcript,
|
||||
)?;
|
||||
|
||||
let km2 = hkdf_expand_label::<D>(
|
||||
&handshake_secret,
|
||||
@@ -490,7 +465,7 @@ fn derive_3dh_keys<D: Hash, G: Group>(
|
||||
)?;
|
||||
let ke2 = hkdf_expand_label::<D>(
|
||||
&handshake_secret,
|
||||
&STR_SERVER_ENC,
|
||||
&STR_HANDSHAKE_ENC,
|
||||
b"",
|
||||
<D as Digest>::OutputSize::to_usize(),
|
||||
)?;
|
||||
@@ -545,13 +520,19 @@ fn hkdf_expand_label_extracted<D: Hash>(
|
||||
fn derive_secrets<D: Hash>(
|
||||
hkdf: &Hkdf<D>,
|
||||
label: &[u8],
|
||||
transcript: &[u8],
|
||||
hashed_derivation_transcript: &[u8],
|
||||
) -> Result<Vec<u8>, ProtocolError> {
|
||||
let hashed_transcript = D::digest(transcript);
|
||||
hkdf_expand_label_extracted::<D>(
|
||||
hkdf,
|
||||
label,
|
||||
&hashed_transcript,
|
||||
&hashed_derivation_transcript,
|
||||
<D as Digest>::OutputSize::to_usize(),
|
||||
)
|
||||
}
|
||||
|
||||
// Generate a random nonce up to NonceLen::to_usize() bytes.
|
||||
fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArray<u8, NonceLen> {
|
||||
let mut nonce_bytes = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut nonce_bytes);
|
||||
GenericArray::clone_from_slice(&nonce_bytes)
|
||||
}
|
||||
|
||||
+1
-3
@@ -9,7 +9,6 @@ use crate::errors::InternalPakeError;
|
||||
use crate::group::Group;
|
||||
use generic_array::{typenum::U32, GenericArray};
|
||||
use generic_bytes::{SizedBytes, TryFromSizedBytesError};
|
||||
use generic_bytes_derive::TryFromForSizedBytes;
|
||||
#[cfg(test)]
|
||||
use proptest::prelude::*;
|
||||
#[cfg(test)]
|
||||
@@ -120,8 +119,7 @@ impl<G: Group + Debug> KeyPair<G> {
|
||||
}
|
||||
|
||||
/// A minimalist key type built around a \[u8; 32\]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, TryFromForSizedBytes)]
|
||||
#[ErrorType = "::generic_bytes::TryFromSizedBytesError"]
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct Key(Vec<u8>);
|
||||
|
||||
|
||||
+16
-23
@@ -5,7 +5,7 @@
|
||||
|
||||
//! An implementation of the OPAQUE asymmetric password authentication key exchange protocol
|
||||
//!
|
||||
//! Note: This implementation is in sync with [draft-irtf-cfrg-opaque-02](https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-02.html),
|
||||
//! Note: This implementation is in sync with [draft-irtf-cfrg-opaque-03](https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-03.html),
|
||||
//! but this specification is subject to change, until the final version published by the IETF.
|
||||
//!
|
||||
//! # Overview
|
||||
@@ -169,7 +169,7 @@
|
||||
//! a [ServerRegistration] from the second step.
|
||||
//! The server runs [ServerRegistration::finish] to produce a finalized [ServerRegistration].
|
||||
//! At this point, the client can be considered as successfully registered, and the server can invoke
|
||||
//! [ServerRegistration::to_bytes] to store the password file for use during the login protocol.
|
||||
//! [ServerRegistration::serialize] to store the password file for use during the login protocol.
|
||||
//! ```
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
@@ -268,15 +268,14 @@
|
||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng);
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! use opaque_ke::{ServerLogin, ServerLoginStartParameters};
|
||||
//! use std::convert::TryFrom;
|
||||
//! let password_file = ServerRegistration::<Default>::try_from(&password_file_bytes[..])?;
|
||||
//! let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes[..])?;
|
||||
//! let mut server_rng = OsRng;
|
||||
//! let server_login_start_result = ServerLogin::start(
|
||||
//! &mut server_rng,
|
||||
@@ -317,15 +316,14 @@
|
||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng);
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file =
|
||||
//! # ServerRegistration::<Default>::try_from(
|
||||
//! # ServerRegistration::<Default>::deserialize(
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
@@ -364,15 +362,14 @@
|
||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng);
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file =
|
||||
//! # ServerRegistration::<Default>::try_from(
|
||||
//! # ServerRegistration::<Default>::deserialize(
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
@@ -444,15 +441,14 @@
|
||||
//! // During setup or registration, the server transmits its static public key to the client
|
||||
//! let server_s_pk = server_kp.public(); // obtained from the server
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::default())?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file =
|
||||
//! # ServerRegistration::<Default>::try_from(
|
||||
//! # ServerRegistration::<Default>::deserialize(
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
@@ -522,15 +518,14 @@
|
||||
//! server_registration_start_result.message,
|
||||
//! ClientRegistrationFinishParameters::default()
|
||||
//! )?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file =
|
||||
//! # ServerRegistration::<Default>::try_from(
|
||||
//! # ServerRegistration::<Default>::deserialize(
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
@@ -617,15 +612,14 @@
|
||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng);
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::WithIdentifiers(b"username".to_vec(), b"facebook.com".to_vec()))?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use opaque_ke::{ServerLogin, ServerLoginStartParameters};
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file = ServerRegistration::<Default>::try_from(&password_file_bytes[..])?;
|
||||
//! # let password_file = ServerRegistration::<Default>::deserialize(&password_file_bytes[..])?;
|
||||
//! # let mut server_rng = OsRng;
|
||||
//! let server_login_start_result = ServerLogin::start(
|
||||
//! &mut server_rng,
|
||||
@@ -665,15 +659,14 @@
|
||||
//! # let server_kp = Default::generate_random_keypair(&mut server_rng);
|
||||
//! # let server_registration_start_result = ServerRegistration::<Default>::start(&mut server_rng, client_registration_start_result.message, server_kp.public())?;
|
||||
//! # let client_registration_finish_result = client_registration_start_result.state.finish(&mut client_rng, server_registration_start_result.message, ClientRegistrationFinishParameters::WithIdentifiers(b"username".to_vec(), b"facebook.com".to_vec()))?;
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.to_bytes();
|
||||
//! # let password_file_bytes = server_registration_start_result.state.finish(client_registration_finish_result.message)?.serialize();
|
||||
//! # let client_login_start_result = ClientLogin::<Default>::start(
|
||||
//! # &mut client_rng,
|
||||
//! # b"password",
|
||||
//! # ClientLoginStartParameters::default(),
|
||||
//! # )?;
|
||||
//! # use std::convert::TryFrom;
|
||||
//! # let password_file =
|
||||
//! # ServerRegistration::<Default>::try_from(
|
||||
//! # ServerRegistration::<Default>::deserialize(
|
||||
//! # &password_file_bytes[..],
|
||||
//! # )?;
|
||||
//! # let server_login_start_result =
|
||||
|
||||
+44
-154
@@ -13,45 +13,23 @@ use crate::{
|
||||
PakeError, ProtocolError,
|
||||
},
|
||||
group::Group,
|
||||
hash::Hash,
|
||||
key_exchange::traits::{KeyExchange, ToBytes},
|
||||
keypair::{Key, KeyPair, SizedBytesExt},
|
||||
serialization::{serialize, tokenize},
|
||||
};
|
||||
use generic_array::{typenum::Unsigned, GenericArray};
|
||||
use generic_bytes::SizedBytes;
|
||||
use std::convert::TryFrom;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
// Messages
|
||||
// =========
|
||||
|
||||
/// The message sent by the client to the server, to initiate registration
|
||||
pub struct RegistrationRequest<Grp> {
|
||||
pub struct RegistrationRequest<CS: CipherSuite> {
|
||||
/// blinded password information
|
||||
pub(crate) alpha: Grp,
|
||||
pub(crate) alpha: CS::Group,
|
||||
}
|
||||
|
||||
impl<Grp: Group> TryFrom<&[u8]> for RegistrationRequest<Grp> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(first_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
let elem_len = Grp::ElemLen::to_usize();
|
||||
let checked_slice = check_slice_size(first_message_bytes, elem_len, "first_message_bytes")?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(&checked_slice[checked_slice.len() - elem_len..]);
|
||||
let alpha = Grp::from_element_slice(arr)?;
|
||||
Ok(Self { alpha })
|
||||
}
|
||||
}
|
||||
|
||||
impl<Grp: Group> RegistrationRequest<Grp> {
|
||||
/// Byte representation for the registration request
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
self.alpha.to_arr().to_vec()
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> RegistrationRequest<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
self.alpha.to_arr().to_vec()
|
||||
@@ -59,130 +37,77 @@ impl<Grp: Group> RegistrationRequest<Grp> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let checked_slice =
|
||||
check_slice_size(&input, Grp::ElemLen::to_usize(), "first_message_bytes")?;
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let checked_slice = check_slice_size(&input, elem_len, "first_message_bytes")?;
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(checked_slice);
|
||||
let alpha = Grp::from_element_slice(arr)?;
|
||||
let alpha = CS::Group::from_element_slice(arr)?;
|
||||
Ok(Self { alpha })
|
||||
}
|
||||
}
|
||||
|
||||
/// The answer sent by the server to the user, upon reception of the
|
||||
/// registration attempt
|
||||
pub struct RegistrationResponse<Grp> {
|
||||
pub struct RegistrationResponse<CS: CipherSuite> {
|
||||
/// The server's oprf output
|
||||
pub(crate) beta: Grp,
|
||||
pub(crate) beta: CS::Group,
|
||||
/// Server's static public key
|
||||
pub(crate) server_s_pk: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<Grp> TryFrom<&[u8]> for RegistrationResponse<Grp>
|
||||
where
|
||||
Grp: Group,
|
||||
{
|
||||
type Error = ProtocolError;
|
||||
|
||||
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
let elem_len = Grp::ElemLen::to_usize();
|
||||
let checked_slice = check_slice_size_atleast(bytes, elem_len, "second_message_bytes")?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(&checked_slice[..elem_len]);
|
||||
let beta = Grp::from_element_slice(arr)?;
|
||||
|
||||
// FIXME check public key bytes
|
||||
let server_s_pk = checked_slice[elem_len..].to_vec();
|
||||
|
||||
Ok(Self { beta, server_s_pk })
|
||||
}
|
||||
}
|
||||
|
||||
impl<Grp> RegistrationResponse<Grp>
|
||||
where
|
||||
Grp: Group,
|
||||
{
|
||||
/// Byte representation for the registration response message. This does not
|
||||
/// include the envelope credentials format
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
[&self.beta.to_arr().to_vec()[..], &self.server_s_pk[..]].concat()
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> RegistrationResponse<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut registration_response: Vec<u8> = Vec::new();
|
||||
registration_response.extend_from_slice(&self.beta.to_arr());
|
||||
registration_response.extend_from_slice(&serialize(&self.server_s_pk, 2));
|
||||
registration_response
|
||||
[self.beta.to_arr().to_vec(), self.server_s_pk.clone()].concat()
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let key_len = <Key as SizedBytes>::Len::to_usize();
|
||||
let checked_slice =
|
||||
check_slice_size_atleast(&input, Grp::ElemLen::to_usize(), "second_message_bytes")?;
|
||||
check_slice_size(&input, elem_len + key_len, "registration_response_bytes")?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
let arr = GenericArray::from_slice(&checked_slice[..Grp::ElemLen::to_usize()]);
|
||||
let beta = Grp::from_element_slice(arr)?;
|
||||
let arr = GenericArray::from_slice(&checked_slice[..elem_len]);
|
||||
let beta = CS::Group::from_element_slice(arr)?;
|
||||
|
||||
let (server_s_pk, remainder) = tokenize(&checked_slice[Grp::ElemLen::to_usize()..], 2)?;
|
||||
if !remainder.is_empty() {
|
||||
return Err(PakeError::SerializationError.into());
|
||||
}
|
||||
|
||||
Ok(Self { server_s_pk, beta })
|
||||
Ok(Self {
|
||||
server_s_pk: checked_slice[elem_len..].to_vec(),
|
||||
beta,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The final message from the client, containing sealed cryptographic
|
||||
/// identifiers
|
||||
pub struct RegistrationUpload<D: Hash, G: Group> {
|
||||
pub struct RegistrationUpload<CS: CipherSuite> {
|
||||
/// The "envelope" generated by the user, containing sealed
|
||||
/// cryptographic identifiers
|
||||
pub(crate) envelope: Envelope<D>,
|
||||
pub(crate) envelope: Envelope<CS::Hash>,
|
||||
/// The user's public key
|
||||
pub(crate) client_s_pk: Key,
|
||||
pub(crate) _g: PhantomData<G>,
|
||||
}
|
||||
|
||||
impl<D: Hash, G: Group> TryFrom<&[u8]> for RegistrationUpload<D, G> {
|
||||
type Error = ProtocolError;
|
||||
|
||||
fn try_from(third_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
let key_len = <Key as SizedBytes>::Len::to_usize();
|
||||
let envelope_size = key_len + Envelope::<D>::additional_size();
|
||||
let checked_bytes = check_slice_size(
|
||||
third_message_bytes,
|
||||
envelope_size + key_len,
|
||||
"third_message",
|
||||
)?;
|
||||
let unchecked_client_s_pk = Key::from_bytes(&checked_bytes[envelope_size..])?;
|
||||
let client_s_pk = KeyPair::<G>::check_public_key(unchecked_client_s_pk)?;
|
||||
|
||||
Ok(Self {
|
||||
envelope: Envelope::<D>::from_bytes(&checked_bytes[..envelope_size])?,
|
||||
client_s_pk,
|
||||
_g: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Hash, G: Group> RegistrationUpload<D, G> {
|
||||
impl<CS: CipherSuite> RegistrationUpload<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut message: Vec<u8> = Vec::new();
|
||||
message.extend_from_slice(&serialize(&self.client_s_pk.to_arr(), 2));
|
||||
message.extend_from_slice(&self.envelope.serialize());
|
||||
message
|
||||
[
|
||||
self.client_s_pk.to_arr().to_vec(),
|
||||
self.envelope.serialize(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let (client_s_pk, remainder) = tokenize(&input, 2)?;
|
||||
let (envelope, remainder) = Envelope::<D>::deserialize(&remainder)?;
|
||||
let key_len = <Key as SizedBytes>::Len::to_usize();
|
||||
|
||||
let checked_slice = check_slice_size_atleast(&input, key_len, "registration_upload_bytes")?;
|
||||
|
||||
let (envelope, remainder) = Envelope::<CS::Hash>::deserialize(&checked_slice[key_len..])?;
|
||||
|
||||
if !remainder.is_empty() {
|
||||
return Err(PakeError::SerializationError.into());
|
||||
@@ -190,8 +115,9 @@ impl<D: Hash, G: Group> RegistrationUpload<D, G> {
|
||||
|
||||
Ok(Self {
|
||||
envelope,
|
||||
client_s_pk: KeyPair::<G>::check_public_key(Key::from_bytes(&client_s_pk)?)?,
|
||||
_g: PhantomData,
|
||||
client_s_pk: KeyPair::<CS::Group>::check_public_key(Key::from_bytes(
|
||||
&checked_slice[..key_len],
|
||||
)?)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -203,19 +129,7 @@ pub struct CredentialRequest<CS: CipherSuite> {
|
||||
pub(crate) ke1_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1Message,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialRequest<CS> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(first_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
Self::deserialize(first_message_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> CredentialRequest<CS> {
|
||||
/// byte representation for the login request
|
||||
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||
[&self.alpha.to_arr()[..], &self.ke1_message.to_bytes()].concat()
|
||||
}
|
||||
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut credential_request: Vec<u8> = Vec::new();
|
||||
@@ -273,7 +187,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
) -> Vec<u8> {
|
||||
[
|
||||
&beta.to_arr(),
|
||||
&serialize(&server_s_pk.to_arr().to_vec(), 2)[..],
|
||||
&server_s_pk.to_arr()[..],
|
||||
&envelope.to_bytes(),
|
||||
]
|
||||
.concat()
|
||||
@@ -281,16 +195,10 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
Self::try_from(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialResponse<CS> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(second_message_bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
let elem_len = <CS::Group as Group>::ElemLen::to_usize();
|
||||
let key_len = <Key as SizedBytes>::Len::to_usize();
|
||||
let checked_slice =
|
||||
check_slice_size_atleast(second_message_bytes, elem_len, "login_second_message_bytes")?;
|
||||
check_slice_size_atleast(input, elem_len + key_len, "login_second_message_bytes")?;
|
||||
|
||||
// Check that the message is actually containing an element of the
|
||||
// correct subgroup
|
||||
@@ -298,16 +206,11 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialResponse<CS> {
|
||||
let arr = GenericArray::from_slice(beta_bytes);
|
||||
let beta = CS::Group::from_element_slice(arr)?;
|
||||
|
||||
let (serialized_server_s_pk, remainder) = tokenize(&checked_slice[elem_len..], 2)?;
|
||||
let sized_server_s_pk = check_slice_size(
|
||||
&serialized_server_s_pk[..],
|
||||
<Key as SizedBytes>::Len::to_usize(),
|
||||
"server_s_pk in credential_response",
|
||||
)?;
|
||||
let unchecked_server_s_pk = Key::from_bytes(sized_server_s_pk)?;
|
||||
let unchecked_server_s_pk = Key::from_bytes(&checked_slice[elem_len..elem_len + key_len])?;
|
||||
let server_s_pk = KeyPair::<CS::Group>::check_public_key(unchecked_server_s_pk)?;
|
||||
|
||||
let (envelope, remainder) = Envelope::<CS::Hash>::deserialize(&remainder)?;
|
||||
let (envelope, remainder) =
|
||||
Envelope::<CS::Hash>::deserialize(&checked_slice[elem_len + key_len..])?;
|
||||
|
||||
let ke2_message_size = CS::KeyExchange::ke2_message_size();
|
||||
let checked_remainder =
|
||||
@@ -332,16 +235,6 @@ pub struct CredentialFinalization<CS: CipherSuite> {
|
||||
pub(crate) ke3_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for CredentialFinalization<CS> {
|
||||
type Error = ProtocolError;
|
||||
|
||||
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
let ke3_message =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message::try_from(bytes)?;
|
||||
Ok(Self { ke3_message })
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> CredentialFinalization<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
@@ -350,11 +243,8 @@ impl<CS: CipherSuite> CredentialFinalization<CS> {
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
Self::try_from(input)
|
||||
}
|
||||
|
||||
/// byte representation for the login finalization
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
self.ke3_message.to_bytes()
|
||||
let ke3_message =
|
||||
<CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE3Message::try_from(input)?;
|
||||
Ok(Self { ke3_message })
|
||||
}
|
||||
}
|
||||
|
||||
+70
-98
@@ -27,8 +27,6 @@ use rand::{CryptoRng, RngCore};
|
||||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
static STR_OPAQUE_VERSION: &[u8] = b"OPAQUE";
|
||||
|
||||
// Registration
|
||||
// ============
|
||||
|
||||
@@ -38,9 +36,19 @@ pub struct ClientRegistration<CS: CipherSuite> {
|
||||
pub(crate) token: oprf::Token<CS::Group>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for ClientRegistration<CS> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
|
||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let output: Vec<u8> = [
|
||||
&CS::Group::scalar_as_bytes(&self.token.blind)[..],
|
||||
&self.token.data,
|
||||
]
|
||||
.concat();
|
||||
output
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let min_expected_len = <CS::Group as Group>::ScalarLen::to_usize();
|
||||
let checked_slice = (if input.len() <= min_expected_len {
|
||||
Err(InternalPakeError::SizeError {
|
||||
@@ -67,18 +75,6 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ClientRegistration<CS> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// byte representation for the client's registration state
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let output: Vec<u8> = [
|
||||
&CS::Group::scalar_as_bytes(&self.token.blind)[..],
|
||||
&self.token.data,
|
||||
]
|
||||
.concat();
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
/// Optional parameters for client registration finish
|
||||
pub enum ClientRegistrationFinishParameters {
|
||||
/// Specifying the identifiers idU and idS (corresponding to custom identifier mode)
|
||||
@@ -96,7 +92,7 @@ impl Default for ClientRegistrationFinishParameters {
|
||||
/// Contains the fields that are returned by a client registration start
|
||||
pub struct ClientRegistrationStartResult<CS: CipherSuite> {
|
||||
/// The registration request message to be sent to the server
|
||||
pub message: RegistrationRequest<CS::Group>,
|
||||
pub message: RegistrationRequest<CS>,
|
||||
/// The client state that must be persisted in order to complete registration
|
||||
pub state: ClientRegistration<CS>,
|
||||
}
|
||||
@@ -132,19 +128,18 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
let (token, alpha) = oprf::blind::<R, CS::Group, CS::Hash>(&password, blinding_factor_rng)?;
|
||||
|
||||
Ok(ClientRegistrationStartResult {
|
||||
message: RegistrationRequest::<CS::Group> { alpha },
|
||||
message: RegistrationRequest::<CS> { alpha },
|
||||
state: Self { token },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the fields that are returned by a client registration finish
|
||||
pub struct ClientRegistrationFinishResult<D: Hash, G: Group> {
|
||||
pub struct ClientRegistrationFinishResult<CS: CipherSuite> {
|
||||
/// The registration upload message to be sent to the server
|
||||
pub message: RegistrationUpload<D, G>,
|
||||
pub message: RegistrationUpload<CS>,
|
||||
/// The export key output by client registration
|
||||
pub export_key: GenericArray<u8, <D as Digest>::OutputSize>,
|
||||
_g: PhantomData<G>,
|
||||
pub export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
@@ -182,9 +177,9 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
pub fn finish<R: CryptoRng + RngCore>(
|
||||
self,
|
||||
rng: &mut R,
|
||||
r2: RegistrationResponse<CS::Group>,
|
||||
r2: RegistrationResponse<CS>,
|
||||
params: ClientRegistrationFinishParameters,
|
||||
) -> Result<ClientRegistrationFinishResult<CS::Hash, CS::Group>, ProtocolError> {
|
||||
) -> Result<ClientRegistrationFinishResult<CS>, ProtocolError> {
|
||||
let optional_ids = match params {
|
||||
ClientRegistrationFinishParameters::WithIdentifiers(id_u, id_s) => Some((id_u, id_s)),
|
||||
ClientRegistrationFinishParameters::Default => None,
|
||||
@@ -206,10 +201,8 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
message: RegistrationUpload {
|
||||
envelope,
|
||||
client_s_pk: client_static_keypair.public().clone(),
|
||||
_g: PhantomData,
|
||||
},
|
||||
export_key,
|
||||
_g: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -245,7 +238,7 @@ impl<CS: CipherSuite> Drop for ClientLogin<CS> {
|
||||
/// Contains the fields that are returned by a server registration start
|
||||
pub struct ServerRegistrationStartResult<CS: CipherSuite> {
|
||||
/// The registration resposne message to send to the client
|
||||
pub message: RegistrationResponse<CS::Group>,
|
||||
pub message: RegistrationResponse<CS>,
|
||||
/// The state that the server must keep in order to complete registration
|
||||
pub state: ServerRegistration<CS>,
|
||||
}
|
||||
@@ -257,12 +250,21 @@ pub struct ServerRegistration<CS: CipherSuite> {
|
||||
pub(crate) oprf_key: <CS::Group as Group>::Scalar,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for ServerRegistration<CS> {
|
||||
type Error = ProtocolError;
|
||||
impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut output: Vec<u8> = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec();
|
||||
self.client_s_pk
|
||||
.iter()
|
||||
.for_each(|v| output.extend_from_slice(&v.to_arr()));
|
||||
self.envelope
|
||||
.iter()
|
||||
.for_each(|v| output.extend_from_slice(&v.to_bytes()));
|
||||
output
|
||||
}
|
||||
|
||||
/// The format of a serialized ServerRegistration object:
|
||||
/// oprf_key | client_s_pk | envelope
|
||||
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let scalar_len = <CS::Group as Group>::ScalarLen::to_usize();
|
||||
if input.len() == scalar_len {
|
||||
return Ok(Self {
|
||||
@@ -292,20 +294,6 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ServerRegistration<CS> {
|
||||
oprf_key,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
/// byte representation for the server's registration state
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut output: Vec<u8> = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec();
|
||||
self.client_s_pk
|
||||
.iter()
|
||||
.for_each(|v| output.extend_from_slice(&v.to_arr()));
|
||||
self.envelope
|
||||
.iter()
|
||||
.for_each(|v| output.extend_from_slice(&v.to_bytes()));
|
||||
output
|
||||
}
|
||||
|
||||
/// From the client's "blinded" password, returns a response to be
|
||||
/// sent back to the client, as well as a ServerRegistration
|
||||
@@ -336,7 +324,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
/// ```
|
||||
pub fn start<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
message: RegistrationRequest<CS::Group>,
|
||||
message: RegistrationRequest<CS>,
|
||||
server_s_pk: &Key,
|
||||
) -> Result<ServerRegistrationStartResult<CS>, ProtocolError> {
|
||||
// RFC: generate oprf_key (salt) and v_u = g^oprf_key
|
||||
@@ -388,10 +376,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
|
||||
/// let client_record = server_registration_start_result.state.finish(client_registration_finish_result.message)?;
|
||||
/// # Ok::<(), ProtocolError>(())
|
||||
/// ```
|
||||
pub fn finish(
|
||||
self,
|
||||
message: RegistrationUpload<CS::Hash, CS::Group>,
|
||||
) -> Result<Self, ProtocolError> {
|
||||
pub fn finish(self, message: RegistrationUpload<CS>) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
envelope: Some(message.envelope),
|
||||
client_s_pk: Some(message.client_s_pk),
|
||||
@@ -411,9 +396,21 @@ pub struct ClientLogin<CS: CipherSuite> {
|
||||
serialized_credential_request: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
|
||||
impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let output: Vec<u8> = [
|
||||
&CS::Group::scalar_as_bytes(&self.token.blind)[..],
|
||||
&serialize(&self.serialized_credential_request, 2),
|
||||
&serialize(&self.ke1_state.to_bytes(), 2),
|
||||
&self.token.data,
|
||||
]
|
||||
.concat();
|
||||
output
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let scalar_len = <CS::Group as Group>::ScalarLen::to_usize();
|
||||
let checked_slice = (if input.len() <= scalar_len {
|
||||
Err(InternalPakeError::SizeError {
|
||||
@@ -445,20 +442,6 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// byte representation for the client's login state
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let output: Vec<u8> = [
|
||||
&CS::Group::scalar_as_bytes(&self.token.blind)[..],
|
||||
&serialize(&self.serialized_credential_request, 2),
|
||||
&serialize(&self.ke1_state.to_bytes(), 2),
|
||||
&self.token.data,
|
||||
]
|
||||
.concat();
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
/// Optional parameters for client login start
|
||||
pub enum ClientLoginStartParameters {
|
||||
/// Specifying a plaintext info field that will be sent to the server
|
||||
@@ -599,7 +582,6 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
ClientLoginFinishParameters::WithIdentifiers(id_u, id_s) => Some((id_u, id_s)),
|
||||
};
|
||||
|
||||
let l2_beta_bytes = &l2.beta.to_arr()[..];
|
||||
let server_s_pk_bytes = l2.server_s_pk.to_arr().to_vec();
|
||||
|
||||
let password_derived_key =
|
||||
@@ -619,20 +601,16 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
KeyPair::<CS::Group>::public_from_private(&client_s_sk)
|
||||
.to_arr()
|
||||
.to_vec(),
|
||||
server_s_pk_bytes.clone(),
|
||||
server_s_pk_bytes,
|
||||
),
|
||||
Some((id_u, id_s)) => (id_u, id_s),
|
||||
};
|
||||
|
||||
let l2_bytes: Vec<u8> = [
|
||||
l2_beta_bytes,
|
||||
&serialize(&server_s_pk_bytes, 2),
|
||||
&l2.envelope.to_bytes(),
|
||||
]
|
||||
.concat();
|
||||
let credential_response_component =
|
||||
CredentialResponse::<CS>::serialize_without_ke(&l2.beta, &l2.server_s_pk, &l2.envelope);
|
||||
|
||||
let (confidential_info, session_key, ke3_message) = CS::KeyExchange::generate_ke3(
|
||||
l2_bytes,
|
||||
credential_response_component,
|
||||
l2.ke2_message,
|
||||
&self.ke1_state,
|
||||
&self.serialized_credential_request,
|
||||
@@ -658,18 +636,6 @@ pub struct ServerLogin<CS: CipherSuite> {
|
||||
_cs: PhantomData<CS>,
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> TryFrom<&[u8]> for ServerLogin<CS> {
|
||||
type Error = ProtocolError;
|
||||
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
_cs: PhantomData,
|
||||
ke2_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2State::try_from(
|
||||
bytes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Optional parameters for server login start
|
||||
pub enum ServerLoginStartParameters {
|
||||
/// Specifying a confidential info field that will be sent to the client
|
||||
@@ -705,11 +671,21 @@ pub struct ServerLoginFinishResult {
|
||||
}
|
||||
|
||||
impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
/// byte representation for the server's login state
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
self.ke2_state.to_bytes()
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
pub fn deserialize(bytes: &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
_cs: PhantomData,
|
||||
ke2_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2State::try_from(
|
||||
bytes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// From the client's "blinded"" password, returns a challenge to be
|
||||
/// sent back to the client, as well as a ServerLogin
|
||||
///
|
||||
@@ -779,7 +755,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
Some((id_u, id_s)) => (id_u, id_s),
|
||||
};
|
||||
|
||||
let l1_bytes = &l1.to_bytes();
|
||||
let l1_bytes = &l1.serialize();
|
||||
let beta = oprf::evaluate(l1.alpha, &password_file.oprf_key);
|
||||
let server_s_pk = KeyPair::<CS::Group>::public_from_private(&server_s_sk);
|
||||
|
||||
@@ -874,10 +850,6 @@ fn get_password_derived_key<G: GroupWithMapToCurve, SH: SlowHash<D>, D: Hash>(
|
||||
token: &oprf::Token<G>,
|
||||
beta: G,
|
||||
) -> Result<Vec<u8>, InternalPakeError> {
|
||||
let oprf_output = oprf::finalize::<G, D>(
|
||||
&token.data,
|
||||
&oprf::unblind::<G>(token, beta),
|
||||
STR_OPAQUE_VERSION,
|
||||
);
|
||||
let oprf_output = oprf::finalize::<G, D>(&token.data, &token.blind, beta);
|
||||
SH::hash(oprf_output)
|
||||
}
|
||||
|
||||
+18
-22
@@ -50,21 +50,23 @@ pub(crate) fn evaluate<G: Group>(point: G, oprf_key: &G::Scalar) -> G {
|
||||
|
||||
/// Computes the third step for the multiplicative blinding version of DH-OPRF, in which
|
||||
/// the client unblinds the server's message.
|
||||
pub(crate) fn unblind<G: Group>(token: &Token<G>, point: G) -> Vec<u8> {
|
||||
let unblinded = point * &G::scalar_invert(&token.blind);
|
||||
unblinded.to_arr().to_vec()
|
||||
pub(crate) fn finalize<G: GroupWithMapToCurve, H: Hash>(
|
||||
input: &[u8],
|
||||
blind: &G::Scalar,
|
||||
evaluated_element: G,
|
||||
) -> GenericArray<u8, <H as Digest>::OutputSize> {
|
||||
let unblinded_element = evaluated_element * &G::scalar_invert(blind);
|
||||
finalize_after_unblind::<G, H>(input, unblinded_element)
|
||||
}
|
||||
|
||||
pub(crate) fn finalize<G: GroupWithMapToCurve, H: Hash>(
|
||||
token_data: &[u8],
|
||||
issued_token: &[u8],
|
||||
info: &[u8],
|
||||
fn finalize_after_unblind<G: GroupWithMapToCurve, H: Hash>(
|
||||
input: &[u8],
|
||||
unblinded_element: G,
|
||||
) -> GenericArray<u8, <H as Digest>::OutputSize> {
|
||||
let finalize_dst = [STR_VOPRF_FINALIZE, &G::get_context_string(MODE_BASE)].concat();
|
||||
let hash_input = [
|
||||
serialize(token_data, 2),
|
||||
serialize(issued_token, 2),
|
||||
serialize(info, 2),
|
||||
serialize(input, 2),
|
||||
serialize(&unblinded_element.to_arr().to_vec(), 2),
|
||||
serialize(&finalize_dst, 2),
|
||||
]
|
||||
.concat();
|
||||
@@ -95,15 +97,11 @@ pub fn evaluate_shim<G: Group>(point: G, oprf_key: &G::Scalar) -> G {
|
||||
#[cfg(feature = "bench")]
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn unblind_and_finalize_shim<G: GroupWithMapToCurve, H: Hash>(
|
||||
pub fn finalize_shim<G: GroupWithMapToCurve, H: Hash>(
|
||||
token: &Token<G>,
|
||||
point: G,
|
||||
) -> Result<GenericArray<u8, <H as Digest>::OutputSize>, InternalPakeError> {
|
||||
Ok(finalize::<G, H>(
|
||||
&token.data,
|
||||
&unblind::<G>(token, point),
|
||||
b"",
|
||||
))
|
||||
Ok(finalize::<G, H>(&token.data, &token.blind, point))
|
||||
}
|
||||
|
||||
///////////
|
||||
@@ -127,7 +125,7 @@ mod tests {
|
||||
RistrettoPoint::from_scalar_slice(GenericArray::from_slice(&oprf_key[..])).unwrap();
|
||||
let res = point * scalar;
|
||||
|
||||
finalize::<RistrettoPoint, sha2::Sha512>(&input, &res.to_arr().to_vec(), b"")
|
||||
finalize_after_unblind::<RistrettoPoint, sha2::Sha512>(&input, res)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -141,8 +139,7 @@ mod tests {
|
||||
];
|
||||
let oprf_key = RistrettoPoint::from_scalar_slice(&oprf_key_bytes)?;
|
||||
let beta = evaluate::<RistrettoPoint>(alpha, &oprf_key);
|
||||
let res =
|
||||
finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &unblind(&token, beta), b"");
|
||||
let res = finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, beta);
|
||||
let res2 = prf(&input[..], &oprf_key.as_bytes());
|
||||
assert_eq!(res, res2);
|
||||
Ok(())
|
||||
@@ -154,12 +151,11 @@ mod tests {
|
||||
let mut input = vec![0u8; 64];
|
||||
rng.fill_bytes(&mut input);
|
||||
let (token, alpha) = blind::<_, RistrettoPoint, sha2::Sha512>(&input, &mut rng).unwrap();
|
||||
let res =
|
||||
finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &unblind(&token, alpha), b"");
|
||||
let res = finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, alpha);
|
||||
|
||||
let dst = [STR_VOPRF, &RistrettoPoint::get_context_string(MODE_BASE)].concat();
|
||||
let point = RistrettoPoint::map_to_curve::<Sha512>(&input, &dst).unwrap();
|
||||
let res2 = finalize::<RistrettoPoint, sha2::Sha512>(&input, &point.to_arr().to_vec(), b"");
|
||||
let res2 = finalize_after_unblind::<RistrettoPoint, sha2::Sha512>(&input, point);
|
||||
|
||||
assert_eq!(res, res2);
|
||||
}
|
||||
|
||||
+36
-43
@@ -58,8 +58,8 @@ fn client_registration_roundtrip() {
|
||||
|
||||
// serialization order: scalar, password
|
||||
let bytes: Vec<u8> = [&sc.as_bytes()[..], &pw[..]].concat();
|
||||
let reg = ClientRegistration::<Default>::try_from(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.to_bytes();
|
||||
let reg = ClientRegistration::<Default>::deserialize(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.serialize();
|
||||
assert_eq!(reg_bytes, bytes);
|
||||
}
|
||||
|
||||
@@ -71,17 +71,18 @@ fn server_registration_roundtrip() {
|
||||
let oprf_key = <RistrettoPoint as Group>::random_scalar(&mut rng);
|
||||
let mut oprf_bytes: Vec<u8> = vec![];
|
||||
oprf_bytes.extend_from_slice(oprf_key.as_bytes());
|
||||
let reg = ServerRegistration::<Default>::try_from(&oprf_bytes[..]).unwrap();
|
||||
let reg_bytes = reg.to_bytes();
|
||||
let reg = ServerRegistration::<Default>::deserialize(&oprf_bytes[..]).unwrap();
|
||||
let reg_bytes = reg.serialize();
|
||||
assert_eq!(reg_bytes, oprf_bytes);
|
||||
// If we do have envelope and client pk, the server registration contains
|
||||
// the whole kit
|
||||
|
||||
let mut ciphertext = [0u8; 32];
|
||||
rng.fill_bytes(&mut ciphertext);
|
||||
|
||||
// Construct a mock envelope
|
||||
let mut mock_envelope_bytes = Vec::new();
|
||||
mock_envelope_bytes.extend_from_slice(&[1; 1]); // mode = 1
|
||||
mock_envelope_bytes.extend_from_slice(&vec![0; NonceLen::to_usize()]); // empty nonce
|
||||
mock_envelope_bytes.extend_from_slice(&[0, 0]); // empty ciphertext
|
||||
mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key
|
||||
mock_envelope_bytes.extend_from_slice(&[0; MAC_SIZE]); // length-MAC_SIZE hmac
|
||||
|
||||
let mock_client_kp = Default::generate_random_keypair(&mut rng);
|
||||
@@ -90,46 +91,43 @@ fn server_registration_roundtrip() {
|
||||
bytes.extend_from_slice(oprf_key.as_bytes());
|
||||
bytes.extend_from_slice(&mock_client_kp.public().to_arr());
|
||||
bytes.extend_from_slice(&mock_envelope_bytes);
|
||||
let reg = ServerRegistration::<Default>::try_from(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.to_bytes();
|
||||
let reg = ServerRegistration::<Default>::deserialize(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.serialize();
|
||||
assert_eq!(reg_bytes, bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn register_first_message_roundtrip() {
|
||||
fn registration_request_roundtrip() {
|
||||
let pt = random_ristretto_point();
|
||||
let pt_bytes = pt.to_arr().to_vec();
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(pt_bytes.as_slice());
|
||||
|
||||
let r1 = RegistrationRequest::<RistrettoPoint>::deserialize(input.as_slice()).unwrap();
|
||||
let r1 = RegistrationRequest::<Default>::deserialize(input.as_slice()).unwrap();
|
||||
let r1_bytes = r1.serialize();
|
||||
assert_eq!(input, r1_bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn register_second_message_roundtrip() {
|
||||
fn registration_response_roundtrip() {
|
||||
let pt = random_ristretto_point();
|
||||
let beta_bytes = pt.to_arr();
|
||||
let mut rng = OsRng;
|
||||
let skp = Default::generate_random_keypair(&mut rng);
|
||||
let pubkey_bytes = skp.public().to_arr();
|
||||
|
||||
let pubkey_length: usize = pubkey_bytes.len();
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(beta_bytes.as_slice());
|
||||
input.extend_from_slice(&pubkey_length.to_be_bytes()[std::mem::size_of::<usize>() - 2..]);
|
||||
input.extend_from_slice(&pubkey_bytes.as_slice());
|
||||
|
||||
let r2 = RegistrationResponse::<RistrettoPoint>::deserialize(input.as_slice()).unwrap();
|
||||
let r2 = RegistrationResponse::<Default>::deserialize(input.as_slice()).unwrap();
|
||||
let r2_bytes = r2.serialize();
|
||||
assert_eq!(input, r2_bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn register_third_message_roundtrip() {
|
||||
fn registration_upload_roundtrip() {
|
||||
let mut rng = OsRng;
|
||||
let skp = Default::generate_random_keypair(&mut rng);
|
||||
let pubkey_bytes = skp.public().to_arr();
|
||||
@@ -150,20 +148,17 @@ fn register_third_message_roundtrip() {
|
||||
.unwrap();
|
||||
let envelope_bytes = envelope.serialize();
|
||||
|
||||
let pubkey_length: usize = pubkey_bytes.len();
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(&pubkey_length.to_be_bytes()[std::mem::size_of::<usize>() - 2..]);
|
||||
input.extend_from_slice(&pubkey_bytes[..]);
|
||||
input.extend_from_slice(&envelope_bytes);
|
||||
|
||||
let r3 = RegistrationUpload::<sha2::Sha512, RistrettoPoint>::deserialize(&input[..]).unwrap();
|
||||
let r3 = RegistrationUpload::<Default>::deserialize(&input[..]).unwrap();
|
||||
let r3_bytes = r3.serialize();
|
||||
assert_eq!(input, r3_bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn login_first_message_roundtrip() {
|
||||
fn credential_request_roundtrip() {
|
||||
let mut rng = OsRng;
|
||||
let alpha = random_ristretto_point();
|
||||
let alpha_bytes = alpha.to_arr().to_vec();
|
||||
@@ -192,14 +187,13 @@ fn login_first_message_roundtrip() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn login_second_message_roundtrip() {
|
||||
fn credential_response_roundtrip() {
|
||||
let pt = random_ristretto_point();
|
||||
let pt_bytes = pt.to_arr().to_vec();
|
||||
|
||||
let mut rng = OsRng;
|
||||
let skp = Default::generate_random_keypair(&mut rng);
|
||||
let pubkey_bytes = skp.public().to_arr();
|
||||
let pubkey_length: usize = pubkey_bytes.len();
|
||||
|
||||
let mut key = [0u8; 32];
|
||||
rng.fill_bytes(&mut key);
|
||||
@@ -235,7 +229,6 @@ fn login_second_message_roundtrip() {
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(pt_bytes.as_slice());
|
||||
input.extend_from_slice(&pubkey_length.to_be_bytes()[std::mem::size_of::<usize>() - 2..]);
|
||||
input.extend_from_slice(&pubkey_bytes.as_slice());
|
||||
input.extend_from_slice(&envelope.serialize());
|
||||
input.extend_from_slice(&ke2m[..]);
|
||||
@@ -279,8 +272,8 @@ fn client_login_roundtrip() {
|
||||
&pw[..],
|
||||
]
|
||||
.concat();
|
||||
let reg = ClientLogin::<Default>::try_from(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.to_bytes();
|
||||
let reg = ClientLogin::<Default>::deserialize(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.serialize();
|
||||
assert_eq!(reg_bytes, bytes);
|
||||
}
|
||||
|
||||
@@ -358,53 +351,53 @@ fn test_i2osp_os2ip(bytes in vec(any::<u8>(), 0..std::mem::size_of::<usize>()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_register_first_message(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegistrationRequest::<RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
fn test_nocrash_registration_request(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegistrationRequest::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_register_second_message(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegistrationResponse::<RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
fn test_nocrash_registration_response(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegistrationResponse::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_register_third_message(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegistrationUpload::<sha2::Sha512, RistrettoPoint>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
fn test_nocrash_registration_upload(bytes in vec(any::<u8>(), 0..200)) {
|
||||
RegistrationUpload::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_login_first_message(bytes in vec(any::<u8>(), 0..500)) {
|
||||
CredentialRequest::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
fn test_nocrash_credential_request(bytes in vec(any::<u8>(), 0..500)) {
|
||||
CredentialRequest::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_login_second_message(bytes in vec(any::<u8>(), 0..500)) {
|
||||
CredentialResponse::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
fn test_nocrash_credential_response(bytes in vec(any::<u8>(), 0..500)) {
|
||||
CredentialResponse::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_login_third_message(bytes in vec(any::<u8>(), 0..500)) {
|
||||
CredentialFinalization::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
fn test_nocrash_credential_finalization(bytes in vec(any::<u8>(), 0..500)) {
|
||||
CredentialFinalization::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_client_registration(bytes in vec(any::<u8>(), 0..700)) {
|
||||
ClientRegistration::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
ClientRegistration::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_server_registration(bytes in vec(any::<u8>(), 0..700)) {
|
||||
ServerRegistration::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
ServerRegistration::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_client_login(bytes in vec(any::<u8>(), 0..700)) {
|
||||
ClientLogin::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
ClientLogin::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_server_login(bytes in vec(any::<u8>(), 0..700)) {
|
||||
ServerLogin::<Default>::try_from(&bytes[..]).map_or(true, |_| true);
|
||||
ServerLogin::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-1
@@ -30,13 +30,21 @@ impl<D: Hash> SlowHash<D> for NoOpHash {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "slow-hash")]
|
||||
const DEFAULT_SCRYPT_LOG_N: u8 = 15u8;
|
||||
#[cfg(feature = "slow-hash")]
|
||||
const DEFAULT_SCRYPT_R: u32 = 8u32;
|
||||
#[cfg(feature = "slow-hash")]
|
||||
const DEFAULT_SCRYPT_P: u32 = 1u32;
|
||||
|
||||
#[cfg(feature = "slow-hash")]
|
||||
impl<D: Hash> SlowHash<D> for scrypt::ScryptParams {
|
||||
fn hash(
|
||||
input: GenericArray<u8, <D as Digest>::OutputSize>,
|
||||
) -> Result<Vec<u8>, InternalPakeError> {
|
||||
let params =
|
||||
scrypt::ScryptParams::new(15, 8, 1).map_err(|_| InternalPakeError::SlowHashError)?;
|
||||
scrypt::ScryptParams::new(DEFAULT_SCRYPT_LOG_N, DEFAULT_SCRYPT_R, DEFAULT_SCRYPT_P)
|
||||
.map_err(|_| InternalPakeError::SlowHashError)?;
|
||||
let mut output = vec![0u8; <D as Digest>::OutputSize::to_usize()];
|
||||
scrypt::scrypt(&input, &[], ¶ms, &mut output)
|
||||
.map_err(|_| InternalPakeError::SlowHashError)?;
|
||||
|
||||
+63
-65
@@ -8,7 +8,7 @@ use crate::{
|
||||
errors::*,
|
||||
group::Group,
|
||||
key_exchange::tripledh::{NonceLen, TripleDH},
|
||||
keypair::Key,
|
||||
keypair::{Key, SizedBytesExt},
|
||||
opaque::*,
|
||||
slow_hash::NoOpHash,
|
||||
tests::mock_rng::CycleRng,
|
||||
@@ -19,7 +19,6 @@ use generic_array::typenum::Unsigned;
|
||||
use generic_bytes::SizedBytes;
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use serde_json::Value;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
// Tests
|
||||
// =====
|
||||
@@ -68,37 +67,37 @@ pub struct TestVectorParameters {
|
||||
|
||||
static TEST_VECTOR: &str = r#"
|
||||
{
|
||||
"client_s_pk": "2c3247e1d7fcf2bef09a0c6e771c44fe922f36deb5726998c89f7816323bc373",
|
||||
"client_s_sk": "d7dd5397912dc1dce64a26b8d24bee59b7929b15a6b9769ad6357913a13e7f09",
|
||||
"client_e_pk": "3431e8f57ce0c1ae9da2b4f37a2f877a64b244a86bc1384ba70a9c39985b3729",
|
||||
"client_e_sk": "8410c0520fd2a37775e54000d9abb5a84825d37649827d8f2721dd655cd64c0c",
|
||||
"server_s_pk": "6a55f77ffb17741d5dfd404ef7079ef276cb2114a76f507c0ae7172847da647a",
|
||||
"server_s_sk": "f4433f94dea3f4bf877ab760566efa36340e34d516dc4462b2ad5b9600157a06",
|
||||
"server_e_pk": "32d56c7e3b882b9ac1a4e38d60456c4942ec6b6aceed91d069ead967a825df74",
|
||||
"server_e_sk": "256f9cdddb2c4bed42866e37d5dff019b4a9584b7486e5683d52b56842d82b0d",
|
||||
"client_s_pk": "6e0a6082dd29936c44b47ecb8a5fe72e4b321a0ac314b0080ca4c48afdabd215",
|
||||
"client_s_sk": "3000848b34d9073885d427e766b7093cc13bdce992ef31cd00ba2c77ff074504",
|
||||
"client_e_pk": "5260ad6eb47ac1db44babcce9327327d50e1a0133c0425acca3efcf41b119718",
|
||||
"client_e_sk": "1526e0bed9af28830da956589d65768ed2a20d9689e82c90b89e4e33904e4009",
|
||||
"server_s_pk": "c21a38653eb19437669bfa066a446b6eea7c1f253ac7adf4798d6c68e171b273",
|
||||
"server_s_sk": "2a38b385e9fb7e0a89aa0f005c729b0c4e22eeedea8c105cf136d9c5c334880f",
|
||||
"server_e_pk": "125f4a2dd9353c8c37a08527a323908835d3fbc374260d32e829d5c3fa81f325",
|
||||
"server_e_sk": "7ef6ada36f3983c0f24705a29d3a453e3e17c28d347f226b24c0aa5ab12a700d",
|
||||
"id_u": "696455",
|
||||
"id_s": "696453",
|
||||
"password": "70617373776f7264",
|
||||
"blinding_factor": "c0937fddc5b7a8cbb76301cbe588268d52a9efe6a205af21a0a12b1fadf3a008",
|
||||
"oprf_key": "f386e8710c12c870a0ec74f09364811142050a5266ca53d36c11e369343a5e09",
|
||||
"envelope_nonce": "2338be69855ad2a280ab5ed67fb04cd96691841241dbb4873ca776adc60d1c93",
|
||||
"client_nonce": "09f2721189a82d90e891d346aa9be462e003cc6b6824a55352da7df685eca5bf",
|
||||
"server_nonce": "5c11e9abe0d5d677dd1a66cd1c8e9baa1f1a44c7554ffe61978b100e657f79f4",
|
||||
"blinding_factor": "a32862d66eb57246321fb6b229e83786745c3afdf8957ebe38b01c17571ba105",
|
||||
"oprf_key": "0851f5ec43e0b702bfcb9d8ec208085b51c0fc5200234901407c176327aa0b02",
|
||||
"envelope_nonce": "78b006042d011bdca5d0058a978d2103a6d546de311a2e8cd025fbc67303a468",
|
||||
"client_nonce": "43497a6f86ba31a6a7f399271fb3b4b4f82c4af086bc431ebaeab7d768ff8a64",
|
||||
"server_nonce": "680cd27da18bc56d4317e7db61de1726a70ebe4e49aee38a3bdb6787cf85466e",
|
||||
"info1": "696e666f31",
|
||||
"einfo2": "65696e666f32",
|
||||
"registration_request": "58e629f68bd59f1d5fcee531a5afeedb4e07d2c6aed98d15cab686d063f2f46e",
|
||||
"registration_response": "a2227384ed34860b7d879d617f7daa802b6a878eaa5eab33669400f30ad0431d00206a55f77ffb17741d5dfd404ef7079ef276cb2114a76f507c0ae7172847da647a",
|
||||
"registration_upload": "00202c3247e1d7fcf2bef09a0c6e771c44fe922f36deb5726998c89f7816323bc373022338be69855ad2a280ab5ed67fb04cd96691841241dbb4873ca776adc60d1c930022576b449b09abeb68d5f6c56082b0c2f560c636bff4f0af3b44b6377045201b545598d319af3122041f06e3ab86371bff6c0727557c77d20efeb9a0b9f24573e3646735eeebed45e741d11d0120741af27b04c2716eb6bdfe950daff937cfcae8569e",
|
||||
"credential_request": "58e629f68bd59f1d5fcee531a5afeedb4e07d2c6aed98d15cab686d063f2f46e09f2721189a82d90e891d346aa9be462e003cc6b6824a55352da7df685eca5bf0005696e666f313431e8f57ce0c1ae9da2b4f37a2f877a64b244a86bc1384ba70a9c39985b3729",
|
||||
"credential_response": "a2227384ed34860b7d879d617f7daa802b6a878eaa5eab33669400f30ad0431d00206a55f77ffb17741d5dfd404ef7079ef276cb2114a76f507c0ae7172847da647a022338be69855ad2a280ab5ed67fb04cd96691841241dbb4873ca776adc60d1c930022576b449b09abeb68d5f6c56082b0c2f560c636bff4f0af3b44b6377045201b545598d319af3122041f06e3ab86371bff6c0727557c77d20efeb9a0b9f24573e3646735eeebed45e741d11d0120741af27b04c2716eb6bdfe950daff937cfcae8569e5c11e9abe0d5d677dd1a66cd1c8e9baa1f1a44c7554ffe61978b100e657f79f432d56c7e3b882b9ac1a4e38d60456c4942ec6b6aceed91d069ead967a825df740006a0c5112e94c86671fd294468658b8a78375f89fca9fb7c3ee1f63871360d5237e57da81719849a8dbccb974742333a1aed034d63d0bdba0beacfe30196912d561e99c1e79ccf",
|
||||
"credential_finalization": "b1fad859f343f1a15df14bd7782db9ab6ee4493225a470152e53b3b7601dc954bc80d7b7dadfe70f743b1ab1552a054e7a9d192399ea42073a1d1c5839aabfc2",
|
||||
"client_registration_state": "c0937fddc5b7a8cbb76301cbe588268d52a9efe6a205af21a0a12b1fadf3a00870617373776f7264",
|
||||
"client_login_state": "c0937fddc5b7a8cbb76301cbe588268d52a9efe6a205af21a0a12b1fadf3a008006758e629f68bd59f1d5fcee531a5afeedb4e07d2c6aed98d15cab686d063f2f46e09f2721189a82d90e891d346aa9be462e003cc6b6824a55352da7df685eca5bf0005696e666f313431e8f57ce0c1ae9da2b4f37a2f877a64b244a86bc1384ba70a9c39985b372900408410c0520fd2a37775e54000d9abb5a84825d37649827d8f2721dd655cd64c0c09f2721189a82d90e891d346aa9be462e003cc6b6824a55352da7df685eca5bf70617373776f7264",
|
||||
"server_registration_state": "f386e8710c12c870a0ec74f09364811142050a5266ca53d36c11e369343a5e09",
|
||||
"server_login_state": "761333eea593c396021c3930fb36cf97aad7c7ea00f1ff983e4df9ca002885017161427303fddb4508c9136a67612e01b673ed88b1de49ed6628d0a77e43c590595f53bf0b0766c165b876173c509efc982868d3860df5dad3f0753477ec9bdd103b71dab9540537f2b10964da82032a6339da6d663a409f4e8e5dea03e3653bb6202f265ed814df39f446486197e1c6091ec6b74200f18df5eef59813ff7f245d69b34e8843be496630921601ab784b1f3ccbfe2ff014ea132199c5c76deda7",
|
||||
"password_file": "f386e8710c12c870a0ec74f09364811142050a5266ca53d36c11e369343a5e092c3247e1d7fcf2bef09a0c6e771c44fe922f36deb5726998c89f7816323bc373022338be69855ad2a280ab5ed67fb04cd96691841241dbb4873ca776adc60d1c930022576b449b09abeb68d5f6c56082b0c2f560c636bff4f0af3b44b6377045201b545598d319af3122041f06e3ab86371bff6c0727557c77d20efeb9a0b9f24573e3646735eeebed45e741d11d0120741af27b04c2716eb6bdfe950daff937cfcae8569e",
|
||||
"export_key": "96b95891f06c7f02ab9c508f30e1a82ddea25e2f4fc4ffdafeb199ee65e24e418b2648a201e889eaf84301a1a8d0c3b7fea0ec8d4611686e6daee12430f60c05",
|
||||
"session_key": "b6202f265ed814df39f446486197e1c6091ec6b74200f18df5eef59813ff7f245d69b34e8843be496630921601ab784b1f3ccbfe2ff014ea132199c5c76deda7"
|
||||
"registration_request": "14ba86e53018ce5507d2bfb2d98ad3f60e302d826bff3410a5ec669c8e1ef17d",
|
||||
"registration_response": "aee5c937a85acfbdbd71faf1c5519bfe9e44b0b7489dcc663df9f1ca5b520b6ac21a38653eb19437669bfa066a446b6eea7c1f253ac7adf4798d6c68e171b273",
|
||||
"registration_upload": "6e0a6082dd29936c44b47ecb8a5fe72e4b321a0ac314b0080ca4c48afdabd2150278b006042d011bdca5d0058a978d2103a6d546de311a2e8cd025fbc67303a4687618b32fe2ec2a5c2b6efecec1e6e535106de80af68733673daf0b644965966fa3f279e532d7ecef363f8d55ff6df4c473cfb1049a73f632972bfcc6744185d13a671dd6678d49fb1629a6fbfbe266937378fd9e772c2dd72692d1a35c020010",
|
||||
"credential_request": "14ba86e53018ce5507d2bfb2d98ad3f60e302d826bff3410a5ec669c8e1ef17d43497a6f86ba31a6a7f399271fb3b4b4f82c4af086bc431ebaeab7d768ff8a640005696e666f315260ad6eb47ac1db44babcce9327327d50e1a0133c0425acca3efcf41b119718",
|
||||
"credential_response": "aee5c937a85acfbdbd71faf1c5519bfe9e44b0b7489dcc663df9f1ca5b520b6ac21a38653eb19437669bfa066a446b6eea7c1f253ac7adf4798d6c68e171b2730278b006042d011bdca5d0058a978d2103a6d546de311a2e8cd025fbc67303a4687618b32fe2ec2a5c2b6efecec1e6e535106de80af68733673daf0b644965966fa3f279e532d7ecef363f8d55ff6df4c473cfb1049a73f632972bfcc6744185d13a671dd6678d49fb1629a6fbfbe266937378fd9e772c2dd72692d1a35c020010680cd27da18bc56d4317e7db61de1726a70ebe4e49aee38a3bdb6787cf85466e125f4a2dd9353c8c37a08527a323908835d3fbc374260d32e829d5c3fa81f32500068a4c321f3c375613862ba83f7e5abb8f1d26dbd8035d39f192eb1324c2214457098054a2cbdf5d4ab2894eaf152af8c4be61d701c5a1ab1ec3e1cee5810898140b81771db0be",
|
||||
"credential_finalization": "330aa8ac01bbc9d9642fe1c286187379efe12da14aceab86b22449d21f242d89adabc0295751b4e007beabc413ae9cbf9979e324749953705fd85b87c9c1b1a2",
|
||||
"client_registration_state": "a32862d66eb57246321fb6b229e83786745c3afdf8957ebe38b01c17571ba10570617373776f7264",
|
||||
"client_login_state": "a32862d66eb57246321fb6b229e83786745c3afdf8957ebe38b01c17571ba105006714ba86e53018ce5507d2bfb2d98ad3f60e302d826bff3410a5ec669c8e1ef17d43497a6f86ba31a6a7f399271fb3b4b4f82c4af086bc431ebaeab7d768ff8a640005696e666f315260ad6eb47ac1db44babcce9327327d50e1a0133c0425acca3efcf41b11971800401526e0bed9af28830da956589d65768ed2a20d9689e82c90b89e4e33904e400943497a6f86ba31a6a7f399271fb3b4b4f82c4af086bc431ebaeab7d768ff8a6470617373776f7264",
|
||||
"server_registration_state": "0851f5ec43e0b702bfcb9d8ec208085b51c0fc5200234901407c176327aa0b02",
|
||||
"server_login_state": "89cd93dce8f59cf7b187736c50cbc3ca2e0bbbad0a0be1ddee180a2d95db60695b384be2dd673434ef94bcdbb1b457f63f41cd79ed2422c021c34ca1433b70576920ebb950ad1c40c8c015ec6832e12427e755ba21d005f0b6d5d66d2368ab5ec6f32151fced5a3aa25472c425912242de3638ef57f28b0dd02a956064e5bb9b8fcd73add52d233a454d6b20125e9506a95aae8772ebbfac4d70efe1fb10078fd40f93d84aa7db53853ca74436c917c427cd5c2e408860937e6f7ab80816ca47",
|
||||
"password_file": "0851f5ec43e0b702bfcb9d8ec208085b51c0fc5200234901407c176327aa0b026e0a6082dd29936c44b47ecb8a5fe72e4b321a0ac314b0080ca4c48afdabd2150278b006042d011bdca5d0058a978d2103a6d546de311a2e8cd025fbc67303a4687618b32fe2ec2a5c2b6efecec1e6e535106de80af68733673daf0b644965966fa3f279e532d7ecef363f8d55ff6df4c473cfb1049a73f632972bfcc6744185d13a671dd6678d49fb1629a6fbfbe266937378fd9e772c2dd72692d1a35c020010",
|
||||
"export_key": "8197f91f0d4de1ab126d8dfd06abd0d5df420ce40a135ef376e4ffe515930f413632390e7dc3dcfd19afff62b9113e10eb6c359fc327df6e9ad4d0f06c242322",
|
||||
"session_key": "8fcd73add52d233a454d6b20125e9506a95aae8772ebbfac4d70efe1fb10078fd40f93d84aa7db53853ca74436c917c427cd5c2e408860937e6f7ab80816ca47"
|
||||
}
|
||||
"#;
|
||||
|
||||
@@ -300,7 +299,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
.message
|
||||
.serialize()
|
||||
.to_vec();
|
||||
let client_registration_state = client_registration_start_result.state.to_bytes().to_vec();
|
||||
let client_registration_state = client_registration_start_result.state.serialize().to_vec();
|
||||
|
||||
let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec());
|
||||
let server_registration_start_result = ServerRegistration::<CS>::start(
|
||||
@@ -315,7 +314,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
.to_vec();
|
||||
let oprf_key_bytes =
|
||||
CS::Group::scalar_as_bytes(&server_registration_start_result.state.oprf_key).clone();
|
||||
let server_registration_state = server_registration_start_result.state.to_bytes().to_vec();
|
||||
let server_registration_state = server_registration_start_result.state.serialize().to_vec();
|
||||
|
||||
let mut client_s_sk_and_nonce: Vec<u8> = Vec::new();
|
||||
client_s_sk_and_nonce.extend_from_slice(&client_s_kp.private().to_arr());
|
||||
@@ -339,7 +338,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
.state
|
||||
.finish(client_registration_finish_result.message)
|
||||
.unwrap();
|
||||
let password_file_bytes = password_file.to_bytes();
|
||||
let password_file_bytes = password_file.serialize();
|
||||
|
||||
let mut client_login_start: Vec<u8> = Vec::new();
|
||||
client_login_start.extend_from_slice(&blinding_factor_bytes);
|
||||
@@ -354,7 +353,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
)
|
||||
.unwrap();
|
||||
let credential_request_bytes = client_login_start_result.message.serialize().to_vec();
|
||||
let client_login_state = client_login_start_result.state.to_bytes().to_vec();
|
||||
let client_login_state = client_login_start_result.state.serialize().to_vec();
|
||||
|
||||
let mut server_e_sk_and_nonce_rng = CycleRng::new(
|
||||
[
|
||||
@@ -376,7 +375,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
)
|
||||
.unwrap();
|
||||
let credential_response_bytes = server_login_start_result.message.serialize().to_vec();
|
||||
let server_login_state = server_login_start_result.state.to_bytes().to_vec();
|
||||
let server_login_state = server_login_start_result.state.serialize().to_vec();
|
||||
|
||||
let client_login_finish_result = client_login_start_result
|
||||
.state
|
||||
@@ -385,7 +384,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
ClientLoginFinishParameters::WithIdentifiers(id_u.to_vec(), id_s.to_vec()),
|
||||
)
|
||||
.unwrap();
|
||||
let credential_finalization_bytes = client_login_finish_result.message.to_bytes().to_vec();
|
||||
let credential_finalization_bytes = client_login_finish_result.message.serialize();
|
||||
|
||||
TestVectorParameters {
|
||||
client_s_pk: client_s_kp.public().to_arr().to_vec(),
|
||||
@@ -440,7 +439,7 @@ fn test_registration_request() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.client_registration_state),
|
||||
hex::encode(client_registration_start_result.state.to_bytes())
|
||||
hex::encode(client_registration_start_result.state.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -453,7 +452,7 @@ fn test_registration_response() -> Result<(), ProtocolError> {
|
||||
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
|
||||
&mut oprf_key_rng,
|
||||
RegistrationRequest::deserialize(¶meters.registration_request[..])?,
|
||||
&Key::try_from(¶meters.server_s_pk[..])?,
|
||||
&Key::from_bytes(¶meters.server_s_pk[..])?,
|
||||
)?;
|
||||
assert_eq!(
|
||||
hex::encode(parameters.registration_response),
|
||||
@@ -461,7 +460,7 @@ fn test_registration_response() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.server_registration_state),
|
||||
hex::encode(server_registration_start_result.state.to_bytes())
|
||||
hex::encode(server_registration_start_result.state.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -473,7 +472,7 @@ fn test_registration_upload() -> Result<(), ProtocolError> {
|
||||
let client_s_sk_and_nonce: Vec<u8> =
|
||||
[parameters.client_s_sk, parameters.envelope_nonce].concat();
|
||||
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
|
||||
let result = ClientRegistration::<RistrettoSha5123dhNoSlowHash>::try_from(
|
||||
let result = ClientRegistration::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.client_registration_state[..],
|
||||
)?
|
||||
.finish(
|
||||
@@ -498,7 +497,7 @@ fn test_registration_upload() -> Result<(), ProtocolError> {
|
||||
fn test_password_file() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let server_registration = ServerRegistration::<RistrettoSha5123dhNoSlowHash>::try_from(
|
||||
let server_registration = ServerRegistration::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.server_registration_state[..],
|
||||
)?;
|
||||
let password_file = server_registration.finish(RegistrationUpload::deserialize(
|
||||
@@ -507,7 +506,7 @@ fn test_password_file() -> Result<(), ProtocolError> {
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.password_file),
|
||||
hex::encode(password_file.to_bytes())
|
||||
hex::encode(password_file.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -534,7 +533,7 @@ fn test_credential_request() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.client_login_state),
|
||||
hex::encode(client_login_start_result.state.to_bytes())
|
||||
hex::encode(client_login_start_result.state.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -547,8 +546,8 @@ fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
CycleRng::new([parameters.server_e_sk, parameters.server_nonce].concat());
|
||||
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
|
||||
&mut server_e_sk_and_nonce_rng,
|
||||
ServerRegistration::try_from(¶meters.password_file[..])?,
|
||||
&Key::try_from(¶meters.server_s_sk[..])?,
|
||||
ServerRegistration::deserialize(¶meters.password_file[..])?,
|
||||
&Key::from_bytes(¶meters.server_s_sk[..])?,
|
||||
CredentialRequest::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.credential_request[..],
|
||||
)?,
|
||||
@@ -568,7 +567,7 @@ fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.server_login_state),
|
||||
hex::encode(server_login_start_result.state.to_bytes())
|
||||
hex::encode(server_login_start_result.state.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -577,14 +576,15 @@ fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
fn test_credential_finalization() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_login_finish_result =
|
||||
ClientLogin::<RistrettoSha5123dhNoSlowHash>::try_from(¶meters.client_login_state[..])?
|
||||
.finish(
|
||||
CredentialResponse::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.credential_response[..],
|
||||
)?,
|
||||
ClientLoginFinishParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
|
||||
)?;
|
||||
let client_login_finish_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.client_login_state[..],
|
||||
)?
|
||||
.finish(
|
||||
CredentialResponse::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.credential_response[..],
|
||||
)?,
|
||||
ClientLoginFinishParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.einfo2),
|
||||
@@ -600,7 +600,7 @@ fn test_credential_finalization() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.credential_finalization),
|
||||
hex::encode(client_login_finish_result.message.to_bytes())
|
||||
hex::encode(client_login_finish_result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.export_key),
|
||||
@@ -614,11 +614,12 @@ fn test_credential_finalization() -> Result<(), ProtocolError> {
|
||||
fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let server_login_result =
|
||||
ServerLogin::<RistrettoSha5123dhNoSlowHash>::try_from(¶meters.server_login_state[..])?
|
||||
.finish(CredentialFinalization::try_from(
|
||||
¶meters.credential_finalization[..],
|
||||
)?)?;
|
||||
let server_login_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
¶meters.server_login_state[..],
|
||||
)?
|
||||
.finish(CredentialFinalization::deserialize(
|
||||
¶meters.credential_finalization[..],
|
||||
)?)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.session_key),
|
||||
@@ -687,13 +688,10 @@ fn test_complete_flow(
|
||||
hex::encode(client_login_finish_result.export_key)
|
||||
);
|
||||
} else {
|
||||
let res = matches!(
|
||||
client_login_result,
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::InvalidLoginError
|
||||
))
|
||||
);
|
||||
assert!(res);
|
||||
assert!(match client_login_result {
|
||||
Err(ProtocolError::VerificationError(PakeError::InvalidLoginError)) => true,
|
||||
_ => false,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+201
-192
@@ -4,12 +4,17 @@
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
use crate::{
|
||||
ciphersuite::CipherSuite, errors::*, key_exchange::tripledh::TripleDH, keypair::Key, opaque::*,
|
||||
slow_hash::NoOpHash, tests::mock_rng::CycleRng, *,
|
||||
ciphersuite::CipherSuite,
|
||||
errors::*,
|
||||
key_exchange::tripledh::TripleDH,
|
||||
keypair::{Key, SizedBytesExt},
|
||||
opaque::*,
|
||||
slow_hash::NoOpHash,
|
||||
tests::mock_rng::CycleRng,
|
||||
*,
|
||||
};
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use serde_json::Value;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
// Tests
|
||||
// =====
|
||||
@@ -60,198 +65,202 @@ pub struct TestVectorParameters {
|
||||
pub session_key: Vec<u8>,
|
||||
}
|
||||
|
||||
// Pulled from "OPAQUE-3DH Test Vector 1" and "OPAQUE-3DH Test Vector 6"
|
||||
// of https://datatracker.ietf.org/doc/draft-irtf-cfrg-opaque/
|
||||
static TEST_VECTORS: &[&str] = &[
|
||||
r#"
|
||||
Group: ristretto255
|
||||
EnvelopeMode: 01
|
||||
OPRF: 0001
|
||||
SlowHash: Identity
|
||||
Hash: SHA512
|
||||
server_nonce: a4997137a8fa0d4baf7052a499bf877057f9404e03c889d641a0d7c
|
||||
807b6a518
|
||||
oprf_key: 5ed895206bfc53316d307b23e46ecc6623afb3086da74189a416012be03
|
||||
7e50b
|
||||
SlowHash: Identity
|
||||
EnvelopeMode: 01
|
||||
Group: ristretto255
|
||||
Nh: 64
|
||||
Npk: 32
|
||||
Nsk: 32
|
||||
password: 436f7272656374486f72736542617474657279537461706c65
|
||||
blind_login: ed8366feb6b1d05d1f46acb727061e43aadfafe9c10e5a64e7518d63
|
||||
e3263503
|
||||
server_private_keyshare: 31587dff30b8001d9d43584decc22e358fa7f9d6e606
|
||||
29fb1223081c3bae7103
|
||||
client_nonce: 75a1ad27ab77578bc08b44c4318f09b31d53145c9ba3b42abf0ea08
|
||||
a781277a6
|
||||
server_info: 6772656574696e677320616c696365
|
||||
envelope_nonce: cc7abb200199d5071c94efa49fb62435d3e70d03cf9573a95da54
|
||||
20d3eebcd2b
|
||||
client_private_key: 8bcb0b70dac18de24eef12e737d6b28724d3e37774e0b092f
|
||||
9f70b255defaf04
|
||||
client_public_key: 360e716c676cfe4d9968d1a352ed3faf17603863e0a7aa1905
|
||||
df6ea129343b09
|
||||
server_private_key: f3a0829898a89239dce29ccc98ec8b449a34b255ba1e6f944
|
||||
829d18e0d589b0f
|
||||
server_public_key: 66e130c6eb5b41f851b235b03a0eafeaa883f64147bc62cb74
|
||||
9c22c762389c3c
|
||||
client_info: 68656c6c6f20626f62
|
||||
client_private_keyshare: fbbf4ad24119f08a35bf999f8ae0c779ed7b3e266bf3
|
||||
3f793f6bf9ebf4578005
|
||||
envelope_nonce: 6c6bb9021b9833c788dd25994d3ce7f3811338744fd6dc556e037
|
||||
585783444c0
|
||||
server_keyshare: 82be40ef93bf7c6edd43d4ed9f52fa19827649b819de39c52a22
|
||||
43e985b75d62
|
||||
blind_registration: c604c785ada70d77a5256ae21767de8c3304115237d262134
|
||||
f5e46e512cf8e03
|
||||
client_public_key: b2d1b10f3741a8efef3139f4d2889f2b11f776b79b9aa2c3ef
|
||||
caba4f1c4ae861
|
||||
client_private_key: f0f56cfb488649fe28691dd9aa5dc9ff4c0e6028075baa3c5
|
||||
615398a2cb12304
|
||||
client_keyshare: 484e47e31b3132f4ee512e41805a1690891111a7b885bc526198
|
||||
22c14cabf360
|
||||
server_public_key: 5442a6f57333a332b4c6f07308f6fa846bde3ed27425820cdc
|
||||
eeeb935924a903
|
||||
server_private_key: d63d709e3a739a128929a9f289ff263fdcbc457f2f47f7c43
|
||||
ccafbbfee72290c
|
||||
auth_key: 22198da4ad73b1d35cd8bb875e64ce1a9fc2edeb073d760e114d1d7a2f8
|
||||
6d47411caf1787907e2ff96cd3190b14d101101d74cff234259d9f19a18f2cfe29d0b
|
||||
server_mac_key: 9de28e2f7107afe266570934c033dd6a403fb2b09a9f1a1357a81
|
||||
9fb072d25e6651626638d77bd7f0adf4b2b715d0a0bee2ac531fd0f7da699aba6e9ed
|
||||
717466
|
||||
envelope: 016c6bb9021b9833c788dd25994d3ce7f3811338744fd6dc556e0375857
|
||||
83444c00022e9b28440a1dc99cca7513e8eb754d427caf8515642b45a92c73838c043
|
||||
fc316deeb83deface81589bc8e5c2c767b5ab79218834fbf4fa4f87cf23775aa54633
|
||||
ed75665cd88f451e044cac1b282d890269476d1ac18ff9a4c0cb832e1143ffa7d447a
|
||||
prk: 732303f65e76c39f30876aec31af1f5bcd8861626c922baa2e842209c7d5bf2e
|
||||
024912db2d6cac00b1260c437d34ec588a664a55fc7a0a40251915d2b15d8ec9
|
||||
client_mac_key: 1536168d48218d08dcbed3438e897d98eff566894240d8d136be0
|
||||
4ba46b2c788883fd165ce7614c52a6a9c926bf55d249e6c29bc4a23d5a1775ad294a7
|
||||
858922
|
||||
pseudorandom_pad: e99274b5cd27d14aeeaf16e7aa8d7e7a03071d58229c5dc96d0
|
||||
46ed57a761ddccdbc
|
||||
handshake_encrypt_key: c646def7a8ca75282ac1a0ad15630834cba2772837d7a3
|
||||
a26d00b36923e55b3f5d065679c715e4c799654f261c865f1a55bc94cabc29a6e2e72
|
||||
296dfc494a984
|
||||
handshake_secret: cc887e128c28064106d4101ac3de633e9096e170f2c4a9913d3
|
||||
50f306274b1665a5b251f761672c12db4c403a615c22cee96adb3539fa62662a17f2e
|
||||
18cd5fed
|
||||
registration_response: 1867301bcc67bdf8e640b7d6edcbe2a65488446417b50d
|
||||
30cdba66ccb379e57200205442a6f57333a332b4c6f07308f6fa846bde3ed27425820
|
||||
cdceeeb935924a903
|
||||
export_key: 6ca2c344763e5bc9e3d2bbfe3d982b826b709da597e28e85f9594ec54
|
||||
2a20c697d55de277ccce1d1af7c48ab7fea1467ac1e3a99c71dcf6326a909d280bd2f
|
||||
6f
|
||||
registration_upload: 0020b2d1b10f3741a8efef3139f4d2889f2b11f776b79b9a
|
||||
a2c3efcaba4f1c4ae861016c6bb9021b9833c788dd25994d3ce7f3811338744fd6dc5
|
||||
56e037585783444c00022e9b28440a1dc99cca7513e8eb754d427caf8515642b45a92
|
||||
c73838c043fc316deeb83deface81589bc8e5c2c767b5ab79218834fbf4fa4f87cf23
|
||||
775aa54633ed75665cd88f451e044cac1b282d890269476d1ac18ff9a4c0cb832e114
|
||||
3ffa7d447a
|
||||
registration_request: 241b621c417c0705b5ea7a8b7cdd5039fd61e6b63effe2a
|
||||
44418164c4d49003e
|
||||
session_key: ee9f1ef224d498858f6c9b3a121016a38bad7816055c452b1c7edf3d
|
||||
d439c42a4cc78cbd672e985a20910df14f8f1af4ce5793303ffe6954ff5f1a264e3fd
|
||||
515
|
||||
KE3: e771daf28bc5e8068dead67c3db19f9ad03ee919e52f6c7a6e79cf1085bd7448
|
||||
1e76512c77f37762578eb2faff8fe98e4185ca2d01957216c556d33a6fba3028
|
||||
KE2: e83812f06568d57b8cdfdcc90fe91454e21bd25dd2a1c32dd1599a2e4a4b6c35
|
||||
00205442a6f57333a332b4c6f07308f6fa846bde3ed27425820cdceeeb935924a9030
|
||||
16c6bb9021b9833c788dd25994d3ce7f3811338744fd6dc556e037585783444c00022
|
||||
e9b28440a1dc99cca7513e8eb754d427caf8515642b45a92c73838c043fc316deeb83
|
||||
deface81589bc8e5c2c767b5ab79218834fbf4fa4f87cf23775aa54633ed75665cd88
|
||||
f451e044cac1b282d890269476d1ac18ff9a4c0cb832e1143ffa7d447aa4997137a8f
|
||||
a0d4baf7052a499bf877057f9404e03c889d641a0d7c807b6a51882be40ef93bf7c6e
|
||||
dd43d4ed9f52fa19827649b819de39c52a2243e985b75d62000f13aed85ae30aee2f8
|
||||
9ac5e1c5dd53609b890267ef2d765bb56000bc704c2ba4e4256107befee6655cdb084
|
||||
64e6c75d8b251642e0d721b3fce38f245568b50e7f6c98825d54cc1a26d6eafadcc1d
|
||||
344
|
||||
KE1: b68e0e356f8490fa9c3bed952e16cc02db21eda686b3c484f3d9d912caa41f76
|
||||
75a1ad27ab77578bc08b44c4318f09b31d53145c9ba3b42abf0ea08a781277a600096
|
||||
8656c6c6f20626f62484e47e31b3132f4ee512e41805a1690891111a7b885bc526198
|
||||
22c14cabf360
|
||||
server_info: 6772656574696e677320616c696365
|
||||
server_nonce: 98b8081059f60ffed9336f026fd8e124737205ac73f5348ae5bebdb
|
||||
49456c70f
|
||||
client_nonce: 58dc21475ff730342f807bf031c7ae47a11f0d4dfaa63a7feb15d7e
|
||||
36427ca44
|
||||
server_keyshare: 5214e3ddc73db786480b79fa2da787f2080b82cbe922c2a9592b
|
||||
44597d9a702e
|
||||
client_keyshare: a4084c7296b1a3d5a5e4a24358750489575acfd8fcfa6e787492
|
||||
b98265a5e651
|
||||
server_private_keyshare: c4d002aa4cfcf281657cf36fe562bc60d9133e0e72a7
|
||||
4432f685b2b6a4b42a0c
|
||||
client_private_keyshare: de2e98f422bf7b99be19f7da7cac62f1599d35a225ec
|
||||
6340149a0aaff3102003
|
||||
blind_registration: 7e5bcbf82a46109ee0d24e9bcab41fc830a6ce8b82fc1e921
|
||||
3a043b743b95800
|
||||
blind_login: c4d5a15f0d5ffc354e340454ec779f575e4573a3886ab5e57e4da298
|
||||
4bdd5306
|
||||
oprf_key: 080d0a4d352de92672ab709b1ae1888cb48dfabc2d6ca5b914b335512fe
|
||||
70508
|
||||
auth_key: 7bb7f2b831ee30d3e5cc4012c8f721a4d8f9dd494932d53776e043df9bd
|
||||
2aa284025b8b006fd8449536446ff50698f46c73fccb53f20d80898f185307d1d39e5
|
||||
prk: b0aefddbb21d1b97bc40c07b172e0bf172ec740de4f6274f69d46350a447e9b1
|
||||
b3fb1e4cefc7d8e393ff58a5c45c74d0615ee0eecde116f3d4e744142eb2ee89
|
||||
pseudorandom_pad: 36a828b3b57bf242c4c47ccd9cb84e5b3cefaffe09629c6b94d
|
||||
eba0ccec5fa39
|
||||
envelope: 01cc7abb200199d5071c94efa49fb62435d3e70d03cf9573a95da5420d3
|
||||
eebcd2bbd6323c36fba7fa08a2b6e2aab6efcdc183c4c897d822cf96d29b129932a55
|
||||
3d469ffa9999fcbd37a1e8b6c1e579bcf83fed355c9ff413e6158d72d16f3ccd8699e
|
||||
906027842694b6293b6303bbb7f324e0fccb4ae0f01edb60ee1d32992696e
|
||||
handshake_secret: 2b041dcf12ac9b75dded88f891c25d76746ce9e2c1a43118ac4
|
||||
aa5721cdc1bc2f0691e6c012a1ea9eb95ab4899b3e7058d37fe9546c46b0511877e40
|
||||
f55aac6c
|
||||
handshake_encrypt_key: ceef10f15d869a4cea8174fa98d0d96c7aaf8602d006fe
|
||||
0c5274a40173db76cac820138c5890bb63fb974d1e3e925850cc2464e2c10f0a9a776
|
||||
9a45e80889b1e
|
||||
server_mac_key: f8fd7fdc349b5ae1339515e05912c89a795f561a117cdc84d8d8b
|
||||
5f05b05751abfb87fa01c799c5d367244d1e32eab67ff926833c6025c556acffa4af1
|
||||
f3871a
|
||||
client_mac_key: 92a30cc82c374c06895aa07e81f0cf5f25309a24b595faefcd225
|
||||
1f9219b47e47d17da4fe8b572dedefa350ed365f87b217973e90d0b647a2ccf1d796a
|
||||
8970f6
|
||||
registration_request: ec9027daa5e9a901d641286a7ded51364142936ac7636e1
|
||||
42e3f4368b4bd8124
|
||||
registration_response: 8867d7c8c2c576a6322d49d46078ea32f479aed917c70a
|
||||
636d3ada4397ea1c0e66e130c6eb5b41f851b235b03a0eafeaa883f64147bc62cb749
|
||||
c22c762389c3c
|
||||
registration_upload: 360e716c676cfe4d9968d1a352ed3faf17603863e0a7aa19
|
||||
05df6ea129343b0901cc7abb200199d5071c94efa49fb62435d3e70d03cf9573a95da
|
||||
5420d3eebcd2bbd6323c36fba7fa08a2b6e2aab6efcdc183c4c897d822cf96d29b129
|
||||
932a553d469ffa9999fcbd37a1e8b6c1e579bcf83fed355c9ff413e6158d72d16f3cc
|
||||
d8699e906027842694b6293b6303bbb7f324e0fccb4ae0f01edb60ee1d32992696e
|
||||
KE1: e06a32011e1b1704eb686b263e5d132fff4e9f6429cd93b98db107485006792c
|
||||
58dc21475ff730342f807bf031c7ae47a11f0d4dfaa63a7feb15d7e36427ca4400096
|
||||
8656c6c6f20626f62a4084c7296b1a3d5a5e4a24358750489575acfd8fcfa6e787492
|
||||
b98265a5e651
|
||||
KE2: 66f6b5fa1a4eb6bd7a0c93ed2639a31cba0d02e2df744003641d5a30a4a12364
|
||||
66e130c6eb5b41f851b235b03a0eafeaa883f64147bc62cb749c22c762389c3c01cc7
|
||||
abb200199d5071c94efa49fb62435d3e70d03cf9573a95da5420d3eebcd2bbd6323c3
|
||||
6fba7fa08a2b6e2aab6efcdc183c4c897d822cf96d29b129932a553d469ffa9999fcb
|
||||
d37a1e8b6c1e579bcf83fed355c9ff413e6158d72d16f3ccd8699e906027842694b62
|
||||
93b6303bbb7f324e0fccb4ae0f01edb60ee1d32992696e98b8081059f60ffed9336f0
|
||||
26fd8e124737205ac73f5348ae5bebdb49456c70f5214e3ddc73db786480b79fa2da7
|
||||
87f2080b82cbe922c2a9592b44597d9a702e000f72f38a0945819089c44c86820c51d
|
||||
89cc35f77df03d330101bbed3b2f69066112f32529bdda0998657350fc9f8da4cde73
|
||||
408ad931f4c2ea6237ccae4696483388b174f50cf96d439139b0f8680c3b
|
||||
KE3: 9f0e4f73455ca9fe06bb52ad02670b09be5a03db11a73be4422f19963be082b0
|
||||
eb55871022e8d1d87adc3ab50de7c738058eb659866d091648f2fed12e23fd53
|
||||
export_key: 66c0b72aa829f13a166fb1a1168f1e26023921f0eed1126def4f81ba0
|
||||
4924ad6012e42b63656ec199ba27670d1e7f23dc0a927714edc140134dde5a5d2063d
|
||||
fc
|
||||
session_key: 951c2bb1b876725fa7d3829db791dddd406a688507b47e24101bd0cc
|
||||
5d071760b6fba59e8758a6ea6d7e5f51a715b49a47c50fee9a7c8a0451243c3ee837f
|
||||
d30
|
||||
"#,
|
||||
r#"
|
||||
Group: ristretto255
|
||||
EnvelopeMode: 02
|
||||
OPRF: 0001
|
||||
SlowHash: Identity
|
||||
Hash: SHA512
|
||||
server_nonce: 0f3a6da8b667bc7a383c987586bee749c5f2787691baca68757e78b
|
||||
6128b0a0f
|
||||
oprf_key: 89c61a42c8191a5ca41f2fe959843d333bcf43173b7de4c5c119e0e0d8b
|
||||
0e707
|
||||
SlowHash: Identity
|
||||
EnvelopeMode: 02
|
||||
Group: ristretto255
|
||||
Nh: 64
|
||||
Npk: 32
|
||||
Nsk: 32
|
||||
client_identity: 20fa92f2e4b7ea5b5e677ac4930ff3b93b0043481ab70bc613b2
|
||||
e16a6dde6b05
|
||||
server_identity: eae9dfa6b8348d34418c32d385e1eac99efbce1af320901f7c8e
|
||||
de8d6d272c65
|
||||
password: 436f7272656374486f72736542617474657279537461706c65
|
||||
blind_login: e6d0f1d89ad552e383d6c6f4e8598cc3037d6e274d22da3089e7afbd
|
||||
4171ea02
|
||||
server_private_keyshare: 70c944dcb7f4dddde168ecb48dd9488c62b6fc7e9bb4
|
||||
2a16d291afca9dd25b07
|
||||
client_nonce: 480917b09c6720680b4a7a0ba9f54b69d870f640a4a7994b47ad07d
|
||||
1a95c984f
|
||||
server_info: 6772656574696e677320616c696365
|
||||
server_identity: 5442a6f57333a332b4c6f07308f6fa846bde3ed27425820cdcee
|
||||
eb935924a903
|
||||
envelope_nonce: f41e8b3c5a999aa946f9b562a150e5c5e36748a31a79feb241809
|
||||
0438877888c
|
||||
client_private_key: dc70a99bbabf1ebe98b192e93cedceb9c0164e95b891bd8bc
|
||||
81721b83d66b00b
|
||||
client_public_key: 20fa92f2e4b7ea5b5e677ac4930ff3b93b0043481ab70bc613
|
||||
b2e16a6dde6b05
|
||||
server_private_key: 709687a36c94592ab76579f42ce1be6961f0700496e71df80
|
||||
6ebd5320554720d
|
||||
server_public_key: eae9dfa6b8348d34418c32d385e1eac99efbce1af320901f7c
|
||||
8ede8d6d272c65
|
||||
client_info: 68656c6c6f20626f62
|
||||
client_private_keyshare: a4ba6cb7e16ab76eccdb4c0b9261eedd426d7863f00b
|
||||
fc4a0e09476d3121e70c
|
||||
envelope_nonce: e38fb444afe3df13ae05e6876d10eca7661196375518eb66d7dee
|
||||
b8cfb42d13f
|
||||
server_public_key: 5442a6f57333a332b4c6f07308f6fa846bde3ed27425820cdc
|
||||
eeeb935924a903
|
||||
client_identity: b2d1b10f3741a8efef3139f4d2889f2b11f776b79b9aa2c3efca
|
||||
ba4f1c4ae861
|
||||
blind_registration: 019cbd1d7420292528f8cdd62f339fdabb602f04a95dac9db
|
||||
cec831b8c681a09
|
||||
client_public_key: b2d1b10f3741a8efef3139f4d2889f2b11f776b79b9aa2c3ef
|
||||
caba4f1c4ae861
|
||||
client_private_key: f0f56cfb488649fe28691dd9aa5dc9ff4c0e6028075baa3c5
|
||||
615398a2cb12304
|
||||
client_keyshare: 4ae7d50bb80cc8f5034d36c1c27edc30caca0983677a941bc0ac
|
||||
e5e10b18300a
|
||||
server_keyshare: a2e9e0809b270a1d5c8208f3498a3188538265e6a9e6b274cb38
|
||||
c4c5d9b1792d
|
||||
server_private_key: d63d709e3a739a128929a9f289ff263fdcbc457f2f47f7c43
|
||||
ccafbbfee72290c
|
||||
auth_key: 4c7c0ae950ad7e9c518266f953d4a01bd2232695f92fb028aa6c124996e
|
||||
31a205f621305fd4997edf8a5fce04a51252ba8430227c134b81d7093a58e01c70752
|
||||
server_mac_key: 974bde939ef1d30ba29f9ec2addcaff1eeb105a1f534e04113f9f
|
||||
0b5c3b9a0797e3fa5f7006e63dfb2b0ce74d002bd1161767c361507bfb1fa0fed5063
|
||||
1cdcb7
|
||||
envelope: 02e38fb444afe3df13ae05e6876d10eca7661196375518eb66d7deeb8cf
|
||||
b42d13f00227ed4654d4452340f26c6304dceeeb1fddb142fcd91b3b26ecd566d7688
|
||||
095f9478a721e5a592be9dd3bda76ed97421819aca4a30752813223d33bc7ea443be9
|
||||
76754605116278c7fffda4de142674ed154f540bd3285080637eb4b929e1378336b11
|
||||
prk: e3bb74ca5f88a95571578e921489e1b6119b438e4efce6e955ae9b6453f24aa4
|
||||
e3a34fa22bc5f470cfc134ca0784a9cd7df64be46ff3b325fc19f4009979bf2e
|
||||
client_mac_key: 1c55ecba64d98dc2db8f45faa72b8fdd63cad8677b8665cc575cf
|
||||
8ad36ef38ec63c9dfc5552007573215983f55d8f5cfa1651da8417e3f27094dde5254
|
||||
7f5b89
|
||||
pseudorandom_pad: 7ef495b828a97c896f381824d3371ba012eb63c3f19bb535676
|
||||
a3b63b18373255ba3
|
||||
handshake_encrypt_key: 0852fb826109073be6e7c065b6e2d1f872c16f9977c177
|
||||
cd2f945b26bb933fe6252f226f40483f7aa52f545f801d1e4430f30f80fd42070494e
|
||||
a77fdcecd6595
|
||||
handshake_secret: bfd3bfbe451520880975d0e568cbd3b5155b23c02de504fccb9
|
||||
dd5a8195266cd94d49d040530b3d6b0a585d542eb24da708a2b6f6dc34dee4652d0c1
|
||||
c62c4e59
|
||||
registration_response: 088ac01ebf5700f0c96bc2988509343cb7e2dd6f0df820
|
||||
d0fb807faa11a26f5600205442a6f57333a332b4c6f07308f6fa846bde3ed27425820
|
||||
cdceeeb935924a903
|
||||
export_key: 0effa605dc47ba4fe565c423b782b8b6697b26ee2ede7059b0e17510d
|
||||
f8b11554ce053409671480a56ffbe77b91edc95205c213caeaf9dcb0841790ff834a0
|
||||
09
|
||||
registration_upload: 0020b2d1b10f3741a8efef3139f4d2889f2b11f776b79b9a
|
||||
a2c3efcaba4f1c4ae86102e38fb444afe3df13ae05e6876d10eca7661196375518eb6
|
||||
6d7deeb8cfb42d13f00227ed4654d4452340f26c6304dceeeb1fddb142fcd91b3b26e
|
||||
cd566d7688095f9478a721e5a592be9dd3bda76ed97421819aca4a30752813223d33b
|
||||
c7ea443be976754605116278c7fffda4de142674ed154f540bd3285080637eb4b929e
|
||||
1378336b11
|
||||
registration_request: c8d2e9ba503bf3f8821226653314427edb1ec8a3ecc94a5
|
||||
dfbbe33d59d07b645
|
||||
session_key: 8dc21ff264f2774de95955d35544ba314e92d07f4a3b32c89ead5e70
|
||||
c83ac4c0221deadd34ed11d43fc4d3651aec612d696c63979c96bf1ddd1ee44da5d0c
|
||||
d68
|
||||
KE3: c178e45ed9b314653685cdbf5f7730e3e40f8652ceb9b10f47d1c784fdd75dd1
|
||||
07c4ae3f7683de5a692359178c8f13f41a043fc1dcfc14b1fb7cb411514efc6c
|
||||
KE2: 5079b16709b195b3b63257b419efb752bd0603170160fa72b828ce9ff9209c0c
|
||||
00205442a6f57333a332b4c6f07308f6fa846bde3ed27425820cdceeeb935924a9030
|
||||
2e38fb444afe3df13ae05e6876d10eca7661196375518eb66d7deeb8cfb42d13f0022
|
||||
7ed4654d4452340f26c6304dceeeb1fddb142fcd91b3b26ecd566d7688095f9478a72
|
||||
1e5a592be9dd3bda76ed97421819aca4a30752813223d33bc7ea443be976754605116
|
||||
278c7fffda4de142674ed154f540bd3285080637eb4b929e1378336b110f3a6da8b66
|
||||
7bc7a383c987586bee749c5f2787691baca68757e78b6128b0a0fa2e9e0809b270a1d
|
||||
5c8208f3498a3188538265e6a9e6b274cb38c4c5d9b1792d000f5a1a0b34573bf728b
|
||||
14f53485f3bf62fd91154dc9ca01b21945b2204f96adc87bd80e8283ecf3522b6d893
|
||||
7527f2e9b9782a94fedab0fa304590d1d4f03d72fb1664fca1523a3be95f6c3a97d0a
|
||||
2ed
|
||||
KE1: 7024ca0d5423176294fbb9ca968d8ce3fc879a231f1ceef69e672c89e02ded59
|
||||
480917b09c6720680b4a7a0ba9f54b69d870f640a4a7994b47ad07d1a95c984f00096
|
||||
8656c6c6f20626f624ae7d50bb80cc8f5034d36c1c27edc30caca0983677a941bc0ac
|
||||
e5e10b18300a
|
||||
server_info: 6772656574696e677320616c696365
|
||||
server_nonce: ef49d83cef5f1411ea30abb82b08bd85423aadb86e2c19df5930b3c
|
||||
8498b9f97
|
||||
client_nonce: 4ab1227db632bc079f79c0f5279df2dfa75cfbd4434ab40dcf844d6
|
||||
77165cd3b
|
||||
server_keyshare: 96a9587e233e67f2397f10fec6355b68102534f1f1b115b4ddf7
|
||||
485840efcd7c
|
||||
client_keyshare: 54f35db3a52fb0cf2a97918a6987993231d227e28711eaef19a3
|
||||
e5033632611a
|
||||
server_private_keyshare: 6650d64df70618a878504ce73dcca27b1af125c67e48
|
||||
1e7bd49d0b24709b200f
|
||||
client_private_keyshare: ebb01c59f99bc955df622548e247f7ef180732909ff3
|
||||
c5f87ff8c7867b8be704
|
||||
blind_registration: 308f1d3fa1fea402f3c90b04601274050a3c6f467387c2f48
|
||||
878823949b0e109
|
||||
blind_login: 141e21373228a44b09d4c00da9a6bbaf9a5e54a1687c07f327833643
|
||||
4245510b
|
||||
oprf_key: b7126967aa0cb69c311b71343843ea041bae30e2bde41b548b8fbd8bced
|
||||
97604
|
||||
auth_key: 9f761a5a56a74269b382403aeba47c1d24b9e200e1839efcb616fb280da
|
||||
1b6ba7bd71d6455dd3cd979c545608cfbfc1c4e9ba677e1d40848054a00696c4b2589
|
||||
prk: 30bc3f37a757890ac17ce46043f3c5ed30c96fb8743205e77e84dc167d98e114
|
||||
6093150ff7b4d002f793bfe717e88d174ed2669abdd9e96af473a7ac82973b0a
|
||||
pseudorandom_pad: b909f990c94b9c5949a2b8d0874d602f846b7981b331fd79978
|
||||
b530cc46c8670
|
||||
envelope: 02f41e8b3c5a999aa946f9b562a150e5c5e36748a31a79feb2418090438
|
||||
877888c6579500b73f482e7d1132a39bba0ae96447d37140ba040f25f9c72b4f90a36
|
||||
7bdb425fa1dd4c49e17780f33b821e1e019668fe7f45520e26996ac8cb08e3d2566cc
|
||||
439c83030464effecb8350e7b1ca31087d87f6a45ed3910c185a24a89d282
|
||||
handshake_secret: ff89f264f8c3974238f4c8d736af7b0a55f2e4edc487cbf3e5c
|
||||
7b4bbf21acd7c1d28354c2c8555fba57c4d4b1fbb4b772bfdf909881f67dd517cc9f4
|
||||
f6ebaeac
|
||||
handshake_encrypt_key: 3071b181f639062cf70b74d0ffe5ec8fa695da13cd2f00
|
||||
e74b8b7ef348ae7a5df9c3a32c9f7aeaad5a28379712cf849b9707e221dce124abfad
|
||||
d0225a8e8e045
|
||||
server_mac_key: 7c37b344d189cbbeff80bbb4b78e2703d1a80dc28239923094287
|
||||
62f7ce2a93b11f6e85dd45c02809afe8583d4aad6377e72788773af92eef33c690692
|
||||
20ae76
|
||||
client_mac_key: 2c4aff12ba7aa911a51f9e5b7a7c01439d854c97e4b8ec842a9db
|
||||
d78345760328fd5a72424e49e25ec8fe1b6d9d42f774516f400948bd5a105d995d000
|
||||
2fc83b
|
||||
registration_request: 3c8b89966e261a5aaf7aeb6dcdd94c87ce311bf197221b8
|
||||
7ef44632d58f18a05
|
||||
registration_response: caf9243d7ef3e267815632bf79c85a27a23f218a438815
|
||||
2a523f6a310949807beae9dfa6b8348d34418c32d385e1eac99efbce1af320901f7c8
|
||||
ede8d6d272c65
|
||||
registration_upload: 20fa92f2e4b7ea5b5e677ac4930ff3b93b0043481ab70bc6
|
||||
13b2e16a6dde6b0502f41e8b3c5a999aa946f9b562a150e5c5e36748a31a79feb2418
|
||||
090438877888c6579500b73f482e7d1132a39bba0ae96447d37140ba040f25f9c72b4
|
||||
f90a367bdb425fa1dd4c49e17780f33b821e1e019668fe7f45520e26996ac8cb08e3d
|
||||
2566cc439c83030464effecb8350e7b1ca31087d87f6a45ed3910c185a24a89d282
|
||||
KE1: 8261a1efd78bea73faf256a23c200d729259886530fa43b875c1ca124b09bc7e
|
||||
4ab1227db632bc079f79c0f5279df2dfa75cfbd4434ab40dcf844d677165cd3b00096
|
||||
8656c6c6f20626f6254f35db3a52fb0cf2a97918a6987993231d227e28711eaef19a3
|
||||
e5033632611a
|
||||
KE2: fa1f33a43a03123ebe35345ef93aa23b57ea8bfbee7022b05a179d60768ba02e
|
||||
eae9dfa6b8348d34418c32d385e1eac99efbce1af320901f7c8ede8d6d272c6502f41
|
||||
e8b3c5a999aa946f9b562a150e5c5e36748a31a79feb2418090438877888c6579500b
|
||||
73f482e7d1132a39bba0ae96447d37140ba040f25f9c72b4f90a367bdb425fa1dd4c4
|
||||
9e17780f33b821e1e019668fe7f45520e26996ac8cb08e3d2566cc439c83030464eff
|
||||
ecb8350e7b1ca31087d87f6a45ed3910c185a24a89d282ef49d83cef5f1411ea30abb
|
||||
82b08bd85423aadb86e2c19df5930b3c8498b9f9796a9587e233e67f2397f10fec635
|
||||
5b68102534f1f1b115b4ddf7485840efcd7c000f7ebe71d4ab326006a3aeca802435d
|
||||
c995a38ac6662221f974cb920992d82b8ef8d147c77e29b628a82b5ccb01ea2f7bb60
|
||||
af94cd1860e1bd974a11a1c9bd827789f663c4758eb71058c244138de0c2
|
||||
KE3: d81f93397cdba85a43993d4d9afbdc67f147adfa2b223213b19692cb820eef48
|
||||
5073eda4c8236b2f47702404ad60d9a875d189626fc7b7cc861825385470ae54
|
||||
export_key: 03192555940b5b42e64e6200bf55cc701f1bace3d402a2f8d83977843
|
||||
51a1e3fa1f07a471b783b208acb1d92be47903b6fa3a0df9f4d4b7956ee4f431e2950
|
||||
f6
|
||||
session_key: 58a7fa98bf3b7b52da21406abfb11d98734354edd47d7b32462c0513
|
||||
f0617c89824ea6031d4147a86fc9f6c6837ce640c12fb937d764f296d1a9421ad1b2a
|
||||
5d5
|
||||
"#,
|
||||
];
|
||||
|
||||
@@ -347,14 +356,14 @@ fn get_password_file_bytes(parameters: &TestVectorParameters) -> Result<Vec<u8>,
|
||||
ServerRegistration::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut oprf_key_rng,
|
||||
RegistrationRequest::deserialize(¶meters.registration_request[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_public_key[..]).unwrap(),
|
||||
&Key::from_bytes(¶meters.server_public_key[..]).unwrap(),
|
||||
)?;
|
||||
|
||||
let password_file = server_registration_start_result
|
||||
.state
|
||||
.finish(RegistrationUpload::deserialize(¶meters.registration_upload[..]).unwrap())?;
|
||||
|
||||
Ok(password_file.to_bytes())
|
||||
Ok(password_file.serialize())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -382,7 +391,7 @@ fn test_registration_response() -> Result<(), ProtocolError> {
|
||||
ServerRegistration::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut oprf_key_rng,
|
||||
RegistrationRequest::deserialize(¶meters.registration_request[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_public_key[..]).unwrap(),
|
||||
&Key::from_bytes(¶meters.server_public_key[..]).unwrap(),
|
||||
)?;
|
||||
assert_eq!(
|
||||
hex::encode(parameters.registration_response),
|
||||
@@ -463,8 +472,8 @@ fn test_ke2() -> Result<(), ProtocolError> {
|
||||
CycleRng::new([parameters.server_private_keyshare, parameters.server_nonce].concat());
|
||||
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut server_private_keyshare_and_nonce_rng,
|
||||
ServerRegistration::try_from(&password_file_bytes[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_private_key[..]).unwrap(),
|
||||
ServerRegistration::deserialize(&password_file_bytes[..]).unwrap(),
|
||||
&Key::from_bytes(¶meters.server_private_key[..]).unwrap(),
|
||||
CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(¶meters.KE1[..])
|
||||
.unwrap(),
|
||||
if parameters.envelope_mode == EnvelopeMode::CustomIdentifier {
|
||||
@@ -527,7 +536,7 @@ fn test_ke3() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.KE3),
|
||||
hex::encode(client_login_finish_result.message.to_bytes())
|
||||
hex::encode(client_login_finish_result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.export_key),
|
||||
@@ -546,8 +555,8 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
CycleRng::new([parameters.server_private_keyshare, parameters.server_nonce].concat());
|
||||
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut server_private_keyshare_and_nonce_rng,
|
||||
ServerRegistration::try_from(&password_file_bytes[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_private_key[..]).unwrap(),
|
||||
ServerRegistration::deserialize(&password_file_bytes[..]).unwrap(),
|
||||
&Key::from_bytes(¶meters.server_private_key[..]).unwrap(),
|
||||
CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(¶meters.KE1[..])
|
||||
.unwrap(),
|
||||
if parameters.envelope_mode == EnvelopeMode::CustomIdentifier {
|
||||
@@ -563,7 +572,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
|
||||
let server_login_result = server_login_start_result
|
||||
.state
|
||||
.finish(CredentialFinalization::try_from(¶meters.KE3[..])?)?;
|
||||
.finish(CredentialFinalization::deserialize(¶meters.KE3[..])?)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.session_key),
|
||||
|
||||
@@ -16,8 +16,6 @@ struct VOPRFTestVectorParameters {
|
||||
blind: Vec<u8>,
|
||||
blinded_element: Vec<u8>,
|
||||
evaluation_element: Vec<u8>,
|
||||
unblinded_element: Vec<u8>,
|
||||
info: Vec<u8>,
|
||||
output: Vec<u8>,
|
||||
}
|
||||
|
||||
@@ -26,26 +24,22 @@ struct VOPRFTestVectorParameters {
|
||||
static OPRF_RISTRETTO255_SHA512: &'static [&str] = &[
|
||||
r#"
|
||||
{
|
||||
"sksm": "c604c785ada70d77a5256ae21767de8c3304115237d262134f5e46e512cf8e03",
|
||||
"sksm": "758cbac0e1eb4265d80f6e6489d9a74d788f7ddeda67d7fb3c08b08f44bda30a",
|
||||
"input": "00",
|
||||
"blind": "5ed895206bfc53316d307b23e46ecc6623afb3086da74189a416012be037e50b",
|
||||
"blinded_element": "5cccd309ec729aebe398c53e19c0ab09c24a29f01036960bdad109852e7bdb44",
|
||||
"evaluation_element": "86bd5eeabf29a87cb4a5c7207cb3ade5297e65f9b74c979bd3551891f4b21515",
|
||||
"unblinded_element": "3c7f2d901c0d4f245503a186086fbdf5d8b4408432b25c5163e8b5a19c258348",
|
||||
"info": "4f505246207465737420766563746f7273",
|
||||
"output": "0bb570873cc0402ca38f1a2c395301f2a3627616e305f2bc54bb08c3f6ea9871eb71074e52e36b90778ba7c3e3429ef7170245c9e01647f3827fdef84d3ba930"
|
||||
"blind": "c604c785ada70d77a5256ae21767de8c3304115237d262134f5e46e512cf8e03",
|
||||
"blinded_element": "3c7f2d901c0d4f245503a186086fbdf5d8b4408432b25c5163e8b5a19c258348",
|
||||
"evaluation_element": "fc6c2b854553bf1ed6674072ed0bde1a9911e02b4bd64aa02cfb428f30251e77",
|
||||
"output": "d8ed12382086c74564ae19b7a2b5ed9bdc52656d1fc151faaae51aaba86291e8df0b2143a92f24d44d5efd0892e2e26721d27d88745343493634a66d3a925e3a"
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
{
|
||||
"sksm": "c604c785ada70d77a5256ae21767de8c3304115237d262134f5e46e512cf8e03",
|
||||
"sksm": "758cbac0e1eb4265d80f6e6489d9a74d788f7ddeda67d7fb3c08b08f44bda30a",
|
||||
"input": "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a",
|
||||
"blind": "ed8366feb6b1d05d1f46acb727061e43aadfafe9c10e5a64e7518d63e3263503",
|
||||
"blinded_element": "227d63ca69e93bd062193c1e97fff3d5ebf628f646009d77c4e22ba6429be154",
|
||||
"evaluation_element": "063b91a12e7cbb98dfeb75d8a7eeb83aacf9fd6df7e0b4197466fb77a27fa631",
|
||||
"unblinded_element": "804ec6774764ed50a0bbad0a5f477aa04df7323acab8f98ca6e468b7790bca4c",
|
||||
"info": "4f505246207465737420766563746f7273",
|
||||
"output": "af7cc264dbc96a6b898ba0fa33bfa9e1407bf1dcfbf8772204d470d4458b8f047806679dbfa251f656b906edf9fa638e268adf979bd0e2380a092047d61f9db9"
|
||||
"blind": "5ed895206bfc53316d307b23e46ecc6623afb3086da74189a416012be037e50b",
|
||||
"blinded_element": "28a5e797b710f76d20a52507145fbf320a574ec2c8ab0e33e65dd2c277d0ee56",
|
||||
"evaluation_element": "345e140b707257ae83d4911f7ead3177891e7a62c54097732802c4c7a98ab25a",
|
||||
"output": "4d5f4221b5ebfd4d1a9dd54830e1ed0bce5a8f30a792723a6fddfe6cfe9f86bb1d95a3725818aeb725eb0b1b52e01ee9a72f47042372ef66c307770054d674fc"
|
||||
}
|
||||
"#,
|
||||
];
|
||||
@@ -63,8 +57,6 @@ fn populate_test_vectors(values: &Value) -> VOPRFTestVectorParameters {
|
||||
blind: decode(&values, "blind").unwrap(),
|
||||
blinded_element: decode(&values, "blinded_element").unwrap(),
|
||||
evaluation_element: decode(&values, "evaluation_element").unwrap(),
|
||||
unblinded_element: decode(&values, "unblinded_element").unwrap(),
|
||||
info: decode(&values, "info").unwrap(),
|
||||
output: decode(&values, "output").unwrap(),
|
||||
}
|
||||
}
|
||||
@@ -112,34 +104,7 @@ fn test_evaluate() -> Result<(), PakeError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Tests sksm, evaluation_element -> evaluation_element
|
||||
#[test]
|
||||
fn test_unblind() -> Result<(), PakeError> {
|
||||
for tv in OPRF_RISTRETTO255_SHA512 {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(tv).unwrap());
|
||||
|
||||
let token = oprf::Token {
|
||||
data: parameters.input,
|
||||
blind: RistrettoPoint::from_scalar_slice(GenericArray::from_slice(
|
||||
¶meters.blind[..],
|
||||
))
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
let unblinded_element = oprf::unblind::<RistrettoPoint>(
|
||||
&token,
|
||||
RistrettoPoint::from_element_slice(GenericArray::from_slice(
|
||||
¶meters.evaluation_element,
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(¶meters.unblinded_element, &unblinded_element);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Tests input, unblinded_element, info -> output
|
||||
// Tests input, blind, evaluation_element -> output
|
||||
#[test]
|
||||
fn test_finalize() -> Result<(), PakeError> {
|
||||
for tv in OPRF_RISTRETTO255_SHA512 {
|
||||
@@ -147,8 +112,10 @@ fn test_finalize() -> Result<(), PakeError> {
|
||||
|
||||
let output = oprf::finalize::<RistrettoPoint, Sha512>(
|
||||
¶meters.input,
|
||||
¶meters.unblinded_element,
|
||||
¶meters.info,
|
||||
&RistrettoPoint::from_scalar_slice(GenericArray::from_slice(¶meters.blind))?,
|
||||
RistrettoPoint::from_element_slice(GenericArray::from_slice(
|
||||
¶meters.evaluation_element,
|
||||
))?,
|
||||
);
|
||||
|
||||
assert_eq!(¶meters.output, &output.to_vec());
|
||||
|
||||
Reference in New Issue
Block a user