Compare commits
19
Commits
v0.5.0-pre.2
...
v0.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0531f0812 | ||
|
|
c93884aca3 | ||
|
|
40769f7eca | ||
|
|
1b67086028 | ||
|
|
68cc7d3709 | ||
|
|
59e3fedb21 | ||
|
|
8da56845b8 | ||
|
|
c0162ec8d9 | ||
|
|
ee91c9776c | ||
|
|
0fdfdfdaee | ||
|
|
eafa134c94 | ||
|
|
209b957ae4 | ||
|
|
f79ebf9844 | ||
|
|
20a35da7ba | ||
|
|
4bd2cf466e | ||
|
|
829c6add0f | ||
|
|
8b895cc631 | ||
|
|
83eb78b232 | ||
|
|
5badeff8d2 |
+5
-4
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
+12
-12
@@ -4,7 +4,7 @@ on:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [opened, repoened, synchronize]
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
cargo-audit:
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cache cargo-audit
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/.crates.toml
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
run: cargo install cargo-audit
|
||||
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run cargo audit
|
||||
run: cargo audit -D warnings
|
||||
@@ -43,11 +43,11 @@ jobs:
|
||||
- --features serde
|
||||
toolchain:
|
||||
- stable
|
||||
- 1.60.0
|
||||
- 1.65.0
|
||||
name: test
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install ${{ matrix.toolchain }} toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
@@ -99,8 +99,8 @@ jobs:
|
||||
- --features danger
|
||||
- --features serde
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
- run: rustup target add ${{ matrix.target }}
|
||||
- run: cargo build --verbose --target=${{ matrix.target }} --no-default-features ${{ matrix.frontend_feature }} ${{ matrix.backend_feature }}
|
||||
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install stable toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install nightly toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
@@ -161,7 +161,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/.crates.toml
|
||||
@@ -170,10 +170,10 @@ jobs:
|
||||
key: taplo
|
||||
|
||||
- name: Install Taplo
|
||||
run: cargo install taplo-cli
|
||||
run: cargo install taplo-cli --locked
|
||||
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run Taplo
|
||||
run: taplo fmt --check
|
||||
|
||||
@@ -10,9 +10,10 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
rust: [stable]
|
||||
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
rust-version: ${{ matrix.rust }}
|
||||
- uses: actions/checkout@master
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.0 (March 6, 2024)
|
||||
* Just a version bump from v0.5.0-pre.7
|
||||
|
||||
## 0.5.0-pre.7 (January 11, 2024)
|
||||
* Updated to be in sync with RFC 9497
|
||||
|
||||
## 0.5.0-pre.6 (July 24, 2023)
|
||||
* Updated curve25519-dalek dependency to 4
|
||||
|
||||
## 0.5.0-pre.5 (June 27, 2023)
|
||||
* Updated curve25519-dalek dependency to 4.0.0-rc.3
|
||||
|
||||
## 0.5.0-pre.4 (May 20, 2023)
|
||||
* Updated curve25519-dalek dependency to 4.0.0-rc.2
|
||||
|
||||
## 0.5.0-pre.3 (March 4, 2023)
|
||||
* Updated to be in sync with draft-irtf-cfrg-voprf-19
|
||||
* Increased MSRV to 1.65
|
||||
* Updated p256 dependency to v0.13
|
||||
* Added p384 tests
|
||||
|
||||
## 0.5.0-pre.2 (February 3, 2023)
|
||||
* Increased MSRV to 1.60
|
||||
* Updated p256 dependency to v0.12
|
||||
|
||||
+2
-1
@@ -27,4 +27,5 @@ outlined on that page and do not file a public issue.
|
||||
|
||||
## License
|
||||
By contributing to voprf, you agree that your contributions will be
|
||||
licensed under the LICENSE file in the root directory of this source tree.
|
||||
licensed under both the LICENSE-MIT and LICENSE-APACHE files in the root
|
||||
directory of this source tree.
|
||||
|
||||
+14
-6
@@ -7,9 +7,9 @@ keywords = ["oprf"]
|
||||
license = "MIT"
|
||||
name = "voprf"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/novifinancial/voprf/"
|
||||
rust-version = "1.60"
|
||||
version = "0.5.0-pre.2"
|
||||
repository = "https://github.com/facebook/voprf/"
|
||||
rust-version = "1.65"
|
||||
version = "0.5.0"
|
||||
|
||||
[features]
|
||||
alloc = []
|
||||
@@ -21,14 +21,14 @@ serde = ["generic-array/serde", "dep:serde"]
|
||||
std = ["alloc"]
|
||||
|
||||
[dependencies]
|
||||
curve25519-dalek = { version = "=4.0.0-rc.1", default-features = false, features = [
|
||||
curve25519-dalek = { version = "4", default-features = false, features = [
|
||||
"rand_core",
|
||||
"zeroize",
|
||||
], optional = true }
|
||||
derive-where = { version = "1", features = ["zeroize-on-drop"] }
|
||||
digest = "0.10"
|
||||
displaydoc = { version = "0.2", default-features = false }
|
||||
elliptic-curve = { version = "0.12", features = [
|
||||
elliptic-curve = { version = "0.13", features = [
|
||||
"hash2curve",
|
||||
"sec1",
|
||||
"voprf",
|
||||
@@ -45,7 +45,15 @@ zeroize = { version = "1.5", default-features = false }
|
||||
[dev-dependencies]
|
||||
generic-array = { version = "0.14", features = ["more_lengths"] }
|
||||
hex = "0.4"
|
||||
p256 = { version = "0.12", default-features = false, features = [
|
||||
p256 = { version = "0.13", default-features = false, features = [
|
||||
"hash2curve",
|
||||
"voprf",
|
||||
] }
|
||||
p384 = { version = "0.13", default-features = false, features = [
|
||||
"hash2curve",
|
||||
"voprf",
|
||||
] }
|
||||
p521 = { version = "0.13.3", default-features = false, features = [
|
||||
"hash2curve",
|
||||
"voprf",
|
||||
] }
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall
|
||||
be dual licensed as above, without any additional terms or conditions.
|
||||
@@ -3,7 +3,7 @@ An implementation of a (verifiable) oblivious pseudorandom function (VOPRF)
|
||||
|
||||
A VOPRF is a verifiable oblivious pseudorandom function, a protocol between a client and a server. The regular (non-verifiable) OPRF is also supported in this implementation.
|
||||
|
||||
This implementation is based on the [Internet Draft for VOPRF](https://github.com/cfrg/draft-irtf-cfrg-voprf).
|
||||
This implementation is based on [RFC 9497](https://www.rfc-editor.org/rfc/rfc9497).
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
@@ -16,12 +16,12 @@ Installation
|
||||
Add the following line to the dependencies of your `Cargo.toml`:
|
||||
|
||||
```
|
||||
voprf = "0.5.0-pre.2"
|
||||
voprf = "0.5"
|
||||
```
|
||||
|
||||
### Minimum Supported Rust Version
|
||||
|
||||
Rust **1.60** or higher.
|
||||
Rust **1.65** or higher.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
@@ -32,4 +32,6 @@ To learn more about contributing to this project, [see this document](./CONTRIBU
|
||||
License
|
||||
-------
|
||||
|
||||
This project is [licensed](./LICENSE) under either Apache 2.0 or MIT, at your option.
|
||||
This project is dual-licensed under either the [MIT license](./LICENSE-MIT)
|
||||
or the [Apache License, Version 2.0](./LICENSE-APACHE).
|
||||
You may select, at your option, one of the above-listed licenses.
|
||||
|
||||
+11
-10
@@ -1,14 +1,15 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Defines the CipherSuite trait to specify the underlying primitives for VOPRF
|
||||
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{Digest, OutputSizeUser};
|
||||
use digest::{FixedOutput, HashMarker, OutputSizeUser};
|
||||
use elliptic_curve::VoprfParameters;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U256};
|
||||
|
||||
@@ -21,8 +22,8 @@ where
|
||||
IsLess<U256> + IsLessOrEqual<<Self::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
/// The ciphersuite identifier as dictated by
|
||||
/// <https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/>
|
||||
const ID: u16;
|
||||
/// <https://www.rfc-editor.org/rfc/rfc9497>
|
||||
const ID: &'static str;
|
||||
|
||||
/// A finite cyclic group along with a point representation that allows some
|
||||
/// customization on how to hash an input to a curve point. See [`Group`].
|
||||
@@ -30,17 +31,17 @@ where
|
||||
|
||||
/// The main hash function to use (for HKDF computations and hashing
|
||||
/// transcripts).
|
||||
type Hash: BlockSizeUser + Digest;
|
||||
type Hash: BlockSizeUser + Default + FixedOutput + HashMarker;
|
||||
}
|
||||
|
||||
impl<T: VoprfParameters> CipherSuite for T
|
||||
where
|
||||
T: Group,
|
||||
T::Hash: BlockSizeUser + Digest,
|
||||
T::Hash: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
<T::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<T::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
const ID: u16 = T::ID;
|
||||
const ID: &'static str = T::ID;
|
||||
|
||||
type Group = T;
|
||||
|
||||
|
||||
+80
-31
@@ -1,19 +1,21 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Common functionality between multiple OPRF modes.
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{Digest, Output, OutputSizeUser};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, Unsigned, U11, U2, U256};
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, Unsigned, U2, U256, U9};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
@@ -33,7 +35,7 @@ pub(crate) const STR_DERIVE_KEYPAIR: [u8; 13] = *b"DeriveKeyPair";
|
||||
pub(crate) const STR_COMPOSITE: [u8; 9] = *b"Composite";
|
||||
pub(crate) const STR_CHALLENGE: [u8; 9] = *b"Challenge";
|
||||
pub(crate) const STR_INFO: [u8; 4] = *b"Info";
|
||||
pub(crate) const STR_VOPRF: [u8; 8] = *b"VOPRF10-";
|
||||
pub(crate) const STR_OPRF: [u8; 7] = *b"OPRFV1-";
|
||||
pub(crate) const STR_HASH_TO_SCALAR: [u8; 13] = *b"HashToScalar-";
|
||||
pub(crate) const STR_HASH_TO_GROUP: [u8; 12] = *b"HashToGroup-";
|
||||
|
||||
@@ -153,7 +155,7 @@ where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#section-2.2.1
|
||||
// https://www.rfc-editor.org/rfc/rfc9497#section-2.2.1
|
||||
|
||||
let (m, z) = compute_composites::<CS, _, _>(Some(k), b, cs, ds, mode)?;
|
||||
|
||||
@@ -194,9 +196,9 @@ where
|
||||
&STR_CHALLENGE,
|
||||
];
|
||||
|
||||
let dst = GenericArray::from(STR_HASH_TO_SCALAR).concat(create_context_string::<CS>(mode));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_SCALAR, mode);
|
||||
// This can't fail, the size of the `input` is known.
|
||||
let c_scalar = CS::Group::hash_to_scalar::<CS::Hash>(&h2_input, &dst).unwrap();
|
||||
let c_scalar = CS::Group::hash_to_scalar::<CS::Hash>(&h2_input, &dst.as_dst()).unwrap();
|
||||
let s_scalar = r - &(c_scalar * &k);
|
||||
|
||||
Ok(Proof { c_scalar, s_scalar })
|
||||
@@ -216,7 +218,7 @@ where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#section-2.2.2
|
||||
// https://www.rfc-editor.org/rfc/rfc9497#section-2.2.2
|
||||
let (m, z) = compute_composites::<CS, _, _>(None, b, cs, ds, mode)?;
|
||||
let t2 = (a * &proof.s_scalar) + &(b * &proof.c_scalar);
|
||||
let t3 = (m * &proof.s_scalar) + &(z * &proof.c_scalar);
|
||||
@@ -254,9 +256,9 @@ where
|
||||
&STR_CHALLENGE,
|
||||
];
|
||||
|
||||
let dst = GenericArray::from(STR_HASH_TO_SCALAR).concat(create_context_string::<CS>(mode));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_SCALAR, mode);
|
||||
// This can't fail, the size of the `input` is known.
|
||||
let c = CS::Group::hash_to_scalar::<CS::Hash>(&h2_input, &dst).unwrap();
|
||||
let c = CS::Group::hash_to_scalar::<CS::Hash>(&h2_input, &dst.as_dst()).unwrap();
|
||||
|
||||
match c.ct_eq(&proof.c_scalar).into() {
|
||||
true => Ok(()),
|
||||
@@ -285,7 +287,7 @@ where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#section-2.2.1
|
||||
// https://www.rfc-editor.org/rfc/rfc9497#section-2.2.1
|
||||
|
||||
let elem_len = <CS::Group as Group>::ElemLen::U16.to_be_bytes();
|
||||
|
||||
@@ -296,7 +298,7 @@ where
|
||||
let len = u16::try_from(c_slice.len()).map_err(|_| Error::Batch)?;
|
||||
|
||||
// seedDST = "Seed-" || contextString
|
||||
let seed_dst = GenericArray::from(STR_SEED).concat(create_context_string::<CS>(mode));
|
||||
let seed_dst = Dst::new::<CS, _, _>(STR_SEED, mode);
|
||||
|
||||
// h1Input = I2OSP(len(Bm), 2) || Bm ||
|
||||
// I2OSP(len(seedDST), 2) || seedDST
|
||||
@@ -304,8 +306,8 @@ where
|
||||
let seed = CS::Hash::new()
|
||||
.chain_update(elem_len)
|
||||
.chain_update(CS::Group::serialize_elem(b))
|
||||
.chain_update(i2osp_2_array(&seed_dst))
|
||||
.chain_update(seed_dst)
|
||||
.chain_update(seed_dst.i2osp_2())
|
||||
.chain_update_multi(&seed_dst.as_dst())
|
||||
.finalize();
|
||||
let seed_len = i2osp_2_array(&seed);
|
||||
|
||||
@@ -332,9 +334,9 @@ where
|
||||
&STR_COMPOSITE,
|
||||
];
|
||||
|
||||
let dst = GenericArray::from(STR_HASH_TO_SCALAR).concat(create_context_string::<CS>(mode));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_SCALAR, mode);
|
||||
// This can't fail, the size of the `input` is known.
|
||||
let di = CS::Group::hash_to_scalar::<CS::Hash>(&h2_input, &dst).unwrap();
|
||||
let di = CS::Group::hash_to_scalar::<CS::Hash>(&h2_input, &dst.as_dst()).unwrap();
|
||||
m = c * &di + &m;
|
||||
z = match k_option {
|
||||
Some(_) => z,
|
||||
@@ -365,8 +367,7 @@ where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
let context_string = create_context_string::<CS>(mode);
|
||||
let dst = GenericArray::from(STR_DERIVE_KEYPAIR).concat(context_string);
|
||||
let dst = Dst::new::<CS, _, _>(STR_DERIVE_KEYPAIR, mode);
|
||||
|
||||
let info_len = i2osp_2(info.len()).map_err(|_| Error::DeriveKeyPair)?;
|
||||
|
||||
@@ -376,7 +377,7 @@ where
|
||||
// || contextString)
|
||||
let sk_s = CS::Group::hash_to_scalar::<CS::Hash>(
|
||||
&[seed, &info_len, info, &counter.to_be_bytes()],
|
||||
&dst,
|
||||
&dst.as_dst(),
|
||||
)
|
||||
.map_err(|_| Error::DeriveKeyPair)?;
|
||||
|
||||
@@ -455,8 +456,8 @@ where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(mode));
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst).map_err(|_| Error::Input)
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, mode);
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).map_err(|_| Error::Input)
|
||||
}
|
||||
|
||||
/// Internal function that finalizes the hash input for OPRF, VOPRF & POPRF.
|
||||
@@ -497,16 +498,64 @@ where
|
||||
.finalize())
|
||||
}
|
||||
|
||||
/// Generates the contextString parameter as defined in
|
||||
/// <https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/>
|
||||
pub(crate) fn create_context_string<CS: CipherSuite>(mode: Mode) -> GenericArray<u8, U11>
|
||||
pub(crate) struct Dst<L: ArrayLength<u8>> {
|
||||
dst_1: GenericArray<u8, L>,
|
||||
dst_2: &'static str,
|
||||
}
|
||||
|
||||
impl<L: ArrayLength<u8>> Dst<L> {
|
||||
pub(crate) fn new<CS: CipherSuite, T, TL: ArrayLength<u8>>(par_1: T, mode: Mode) -> Self
|
||||
where
|
||||
T: Into<GenericArray<u8, TL>>,
|
||||
TL: Add<U9, Output = L>,
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
let par_1 = par_1.into();
|
||||
// Generates the contextString parameter as defined in
|
||||
// <https://www.rfc-editor.org/rfc/rfc9497#section-3.1>
|
||||
let par_2 = GenericArray::from(STR_OPRF)
|
||||
.concat([mode.to_u8()].into())
|
||||
.concat([b'-'].into());
|
||||
|
||||
let dst_1 = par_1.concat(par_2);
|
||||
let dst_2 = CS::ID;
|
||||
|
||||
assert!(
|
||||
L::USIZE + dst_2.len() <= u16::MAX.into(),
|
||||
"constructed DST longer then {}",
|
||||
u16::MAX
|
||||
);
|
||||
|
||||
Self { dst_1, dst_2 }
|
||||
}
|
||||
|
||||
pub(crate) fn as_dst(&self) -> [&[u8]; 2] {
|
||||
[&self.dst_1, self.dst_2.as_bytes()]
|
||||
}
|
||||
|
||||
pub(crate) fn i2osp_2(&self) -> [u8; 2] {
|
||||
u16::try_from(L::USIZE + self.dst_2.len())
|
||||
.unwrap()
|
||||
.to_be_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
trait DigestExt {
|
||||
fn chain_update_multi(self, data: &[&[u8]]) -> Self;
|
||||
}
|
||||
|
||||
impl<T> DigestExt for T
|
||||
where
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
T: Digest,
|
||||
{
|
||||
GenericArray::from(STR_VOPRF)
|
||||
.concat([mode.to_u8()].into())
|
||||
.concat(CS::ID.to_be_bytes().into())
|
||||
fn chain_update_multi(mut self, datas: &[&[u8]]) -> Self {
|
||||
for data in datas {
|
||||
self.update(data)
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
+5
-4
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Errors which are produced during an execution of the protocol
|
||||
|
||||
|
||||
+17
-16
@@ -1,17 +1,18 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::Digest;
|
||||
use digest::{FixedOutput, HashMarker};
|
||||
use elliptic_curve::group::cofactor::CofactorGroup;
|
||||
use elliptic_curve::hash2curve::{ExpandMsgXmd, FromOkm, GroupDigest};
|
||||
use elliptic_curve::sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint};
|
||||
use elliptic_curve::{
|
||||
AffinePoint, Field, FieldSize, Group as _, ProjectivePoint, PublicKey, Scalar, SecretKey,
|
||||
AffinePoint, Field, FieldBytesSize, Group as _, ProjectivePoint, PublicKey, Scalar, SecretKey,
|
||||
};
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U256};
|
||||
use generic_array::GenericArray;
|
||||
@@ -24,32 +25,32 @@ impl<C> Group for C
|
||||
where
|
||||
C: GroupDigest,
|
||||
ProjectivePoint<Self>: CofactorGroup + ToEncodedPoint<Self>,
|
||||
FieldSize<Self>: ModulusSize,
|
||||
FieldBytesSize<Self>: ModulusSize,
|
||||
AffinePoint<Self>: FromEncodedPoint<Self> + ToEncodedPoint<Self>,
|
||||
Scalar<Self>: FromOkm,
|
||||
{
|
||||
type Elem = ProjectivePoint<Self>;
|
||||
|
||||
type ElemLen = <FieldSize<Self> as ModulusSize>::CompressedPointSize;
|
||||
type ElemLen = <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize;
|
||||
|
||||
type Scalar = Scalar<Self>;
|
||||
|
||||
type ScalarLen = FieldSize<Self>;
|
||||
type ScalarLen = FieldBytesSize<Self>;
|
||||
|
||||
// Implements the `hash_to_curve()` function from
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[u8]) -> Result<Self::Elem, InternalError>
|
||||
// https://www.rfc-editor.org/rfc/rfc9380.html#section-3
|
||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
||||
where
|
||||
H: Digest + BlockSizeUser,
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>,
|
||||
{
|
||||
Self::hash_from_bytes::<ExpandMsgXmd<H>>(input, dst).map_err(|_| InternalError::Input)
|
||||
}
|
||||
|
||||
// Implements the `HashToScalar()` function
|
||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[u8]) -> Result<Self::Scalar, InternalError>
|
||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
||||
where
|
||||
H: Digest + BlockSizeUser,
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>,
|
||||
{
|
||||
<Self as GroupDigest>::hash_to_scalar::<ExpandMsgXmd<H>>(input, dst)
|
||||
@@ -92,7 +93,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
fn zero_scalar() -> Self::Scalar {
|
||||
Scalar::<Self>::zero()
|
||||
Scalar::<Self>::ZERO
|
||||
}
|
||||
|
||||
fn serialize_scalar(scalar: Self::Scalar) -> GenericArray<u8, Self::ScalarLen> {
|
||||
@@ -100,7 +101,7 @@ where
|
||||
}
|
||||
|
||||
fn deserialize_scalar(scalar_bits: &[u8]) -> Result<Self::Scalar> {
|
||||
SecretKey::<Self>::from_be_bytes(scalar_bits)
|
||||
SecretKey::<Self>::from_slice(scalar_bits)
|
||||
.map(|secret_key| *secret_key.to_nonzero_scalar())
|
||||
.map_err(|_| Error::Deserialization)
|
||||
}
|
||||
|
||||
+11
-10
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Defines the Group trait to specify the underlying prime order group
|
||||
|
||||
@@ -14,7 +15,7 @@ mod ristretto;
|
||||
use core::ops::{Add, Mul, Sub};
|
||||
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::Digest;
|
||||
use digest::{FixedOutput, HashMarker};
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
@@ -26,7 +27,7 @@ use zeroize::Zeroize;
|
||||
use crate::{InternalError, Result};
|
||||
|
||||
/// 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.
|
||||
/// subgroup is noted additively — as in the RFC — in this trait.
|
||||
pub trait Group {
|
||||
/// The type of group elements
|
||||
type Elem: ConstantTimeEq
|
||||
@@ -54,9 +55,9 @@ pub trait Group {
|
||||
/// # Errors
|
||||
/// [`Error::Input`](crate::Error::Input) if the `input` is empty or longer
|
||||
/// then [`u16::MAX`].
|
||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[u8]) -> Result<Self::Elem, InternalError>
|
||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
||||
where
|
||||
H: Digest + BlockSizeUser,
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>;
|
||||
|
||||
/// Hashes a slice of pseudo-random bytes to a scalar
|
||||
@@ -64,9 +65,9 @@ pub trait Group {
|
||||
/// # Errors
|
||||
/// [`Error::Input`](crate::Error::Input) if the `input` is empty or longer
|
||||
/// then [`u16::MAX`].
|
||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[u8]) -> Result<Self::Scalar, InternalError>
|
||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
||||
where
|
||||
H: Digest + BlockSizeUser,
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>;
|
||||
|
||||
/// Get the base point for the group
|
||||
|
||||
+13
-12
@@ -1,16 +1,17 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
|
||||
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use curve25519_dalek::traits::Identity;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::Digest;
|
||||
use digest::{FixedOutput, HashMarker};
|
||||
use elliptic_curve::hash2curve::{ExpandMsg, ExpandMsgXmd, Expander};
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U256, U32, U64};
|
||||
use generic_array::GenericArray;
|
||||
@@ -26,7 +27,7 @@ pub struct Ristretto255;
|
||||
|
||||
#[cfg(feature = "ristretto255-ciphersuite")]
|
||||
impl crate::CipherSuite for Ristretto255 {
|
||||
const ID: u16 = 0x0001;
|
||||
const ID: &'static str = "ristretto255-SHA512";
|
||||
|
||||
type Group = Ristretto255;
|
||||
|
||||
@@ -43,10 +44,10 @@ impl Group for Ristretto255 {
|
||||
type ScalarLen = U32;
|
||||
|
||||
// Implements the `hash_to_ristretto255()` function from
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
|
||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[u8]) -> Result<Self::Elem, InternalError>
|
||||
// https://www.rfc-editor.org/rfc/rfc9380.html#appendix-B
|
||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
||||
where
|
||||
H: Digest + BlockSizeUser,
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>,
|
||||
{
|
||||
let mut uniform_bytes = GenericArray::<_, U64>::default();
|
||||
@@ -58,10 +59,10 @@ impl Group for Ristretto255 {
|
||||
}
|
||||
|
||||
// Implements the `HashToScalar()` function from
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.1
|
||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[u8]) -> Result<Self::Scalar, InternalError>
|
||||
// https://www.rfc-editor.org/rfc/rfc9497#section-4.1
|
||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
||||
where
|
||||
H: Digest + BlockSizeUser,
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>,
|
||||
{
|
||||
let mut uniform_bytes = GenericArray::<_, U64>::default();
|
||||
|
||||
+13
-4
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Includes a series of tests for the group implementations
|
||||
|
||||
@@ -15,6 +16,8 @@ use crate::{Error, Group, Result};
|
||||
#[test]
|
||||
fn test_group_properties() -> Result<()> {
|
||||
use p256::NistP256;
|
||||
use p384::NistP384;
|
||||
use p521::NistP521;
|
||||
|
||||
#[cfg(feature = "ristretto255")]
|
||||
{
|
||||
@@ -27,6 +30,12 @@ fn test_group_properties() -> Result<()> {
|
||||
test_identity_element_error::<NistP256>()?;
|
||||
test_zero_scalar_error::<NistP256>()?;
|
||||
|
||||
test_identity_element_error::<NistP384>()?;
|
||||
test_zero_scalar_error::<NistP384>()?;
|
||||
|
||||
test_identity_element_error::<NistP521>()?;
|
||||
test_zero_scalar_error::<NistP521>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+7
-8
@@ -1,16 +1,15 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! An implementation of a verifiable oblivious pseudorandom function (VOPRF)
|
||||
//!
|
||||
//! Note: This implementation is in sync with
|
||||
//! [draft-irtf-cfrg-voprf-11](https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html),
|
||||
//! but this specification is subject to change, until the final version
|
||||
//! published by the IETF.
|
||||
//! [RFC 9497](https://www.rfc-editor.org/rfc/rfc9497).
|
||||
//!
|
||||
//! # Overview
|
||||
//!
|
||||
@@ -511,7 +510,7 @@
|
||||
//! and [PoprfClient] are used, and that each of the functions accept an
|
||||
//! additional (and optional) info parameter which represents the public input.
|
||||
//! See
|
||||
//! <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-11.html#name-poprf-public-input>
|
||||
//! <https://www.rfc-editor.org/rfc/rfc9497#name-poprf-public-input>
|
||||
//! for more detailed information on how this public input should be used.
|
||||
//!
|
||||
//! # Features
|
||||
|
||||
+26
-11
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Contains the main OPRF API
|
||||
|
||||
@@ -291,11 +292,10 @@ where
|
||||
mod tests {
|
||||
use core::ptr;
|
||||
|
||||
use generic_array::sequence::Concat;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use super::*;
|
||||
use crate::common::{create_context_string, STR_HASH_TO_GROUP};
|
||||
use crate::common::{Dst, STR_HASH_TO_GROUP};
|
||||
use crate::Group;
|
||||
|
||||
fn prf<CS: CipherSuite>(
|
||||
@@ -308,8 +308,8 @@ mod tests {
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(mode));
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst).unwrap();
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, mode);
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).unwrap();
|
||||
|
||||
let res = point * &key;
|
||||
|
||||
@@ -348,9 +348,8 @@ mod tests {
|
||||
.finalize(&input, &EvaluationElement(client_blind_result.message.0))
|
||||
.unwrap();
|
||||
|
||||
let dst =
|
||||
GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(Mode::Oprf));
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[&input], &dst).unwrap();
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, Mode::Oprf);
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[&input], &dst.as_dst()).unwrap();
|
||||
let res2 = finalize_after_unblind::<CS, _, _>(iter::once((input.as_ref(), point)), &[])
|
||||
.next()
|
||||
.unwrap()
|
||||
@@ -427,6 +426,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_functionality() -> Result<()> {
|
||||
use p256::NistP256;
|
||||
use p384::NistP384;
|
||||
use p521::NistP521;
|
||||
|
||||
#[cfg(feature = "ristretto255")]
|
||||
{
|
||||
@@ -447,6 +448,20 @@ mod tests {
|
||||
zeroize_oprf_client::<NistP256>();
|
||||
zeroize_oprf_server::<NistP256>();
|
||||
|
||||
base_retrieval::<NistP384>();
|
||||
base_inversion_unsalted::<NistP384>();
|
||||
server_evaluate::<NistP384>();
|
||||
|
||||
zeroize_oprf_client::<NistP384>();
|
||||
zeroize_oprf_server::<NistP384>();
|
||||
|
||||
base_retrieval::<NistP521>();
|
||||
base_inversion_unsalted::<NistP521>();
|
||||
server_evaluate::<NistP521>();
|
||||
|
||||
zeroize_oprf_client::<NistP521>();
|
||||
zeroize_oprf_server::<NistP521>();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+33
-21
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Contains the main POPRF API
|
||||
|
||||
@@ -14,16 +15,14 @@ use core::iter::{self, Map, Repeat, Zip};
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{Digest, Output, OutputSizeUser};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, Unsigned, U256};
|
||||
use generic_array::GenericArray;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::common::{
|
||||
create_context_string, derive_keypair, deterministic_blind_unchecked, generate_proof,
|
||||
hash_to_group, i2osp_2, server_evaluate_hash_input, verify_proof, BlindedElement,
|
||||
EvaluationElement, Mode, PreparedEvaluationElement, Proof, STR_FINALIZE, STR_HASH_TO_SCALAR,
|
||||
STR_INFO,
|
||||
derive_keypair, deterministic_blind_unchecked, generate_proof, hash_to_group, i2osp_2,
|
||||
server_evaluate_hash_input, verify_proof, BlindedElement, Dst, EvaluationElement, Mode,
|
||||
PreparedEvaluationElement, Proof, STR_FINALIZE, STR_HASH_TO_SCALAR, STR_INFO,
|
||||
};
|
||||
#[cfg(feature = "serde")]
|
||||
use crate::serialization::serde::{Element, Scalar};
|
||||
@@ -616,10 +615,9 @@ where
|
||||
let info_len = i2osp_2(info.len()).map_err(|_| Error::Info)?;
|
||||
let framed_info = [STR_INFO.as_slice(), &info_len, info];
|
||||
|
||||
let dst =
|
||||
GenericArray::from(STR_HASH_TO_SCALAR).concat(create_context_string::<CS>(Mode::Poprf));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_SCALAR, Mode::Poprf);
|
||||
// This can't fail, the size of the `input` is known.
|
||||
let m = CS::Group::hash_to_scalar::<CS::Hash>(&framed_info, &dst).unwrap();
|
||||
let m = CS::Group::hash_to_scalar::<CS::Hash>(&framed_info, &dst.as_dst()).unwrap();
|
||||
|
||||
let t = CS::Group::base_elem() * &m;
|
||||
let tweaked_key = t + &pk;
|
||||
@@ -654,10 +652,9 @@ where
|
||||
let info_len = i2osp_2(info.len()).map_err(|_| Error::Info)?;
|
||||
let framed_info = [STR_INFO.as_slice(), &info_len, info];
|
||||
|
||||
let dst =
|
||||
GenericArray::from(STR_HASH_TO_SCALAR).concat(create_context_string::<CS>(Mode::Poprf));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_SCALAR, Mode::Poprf);
|
||||
// This can't fail, the size of the `input` is known.
|
||||
let m = CS::Group::hash_to_scalar::<CS::Hash>(&framed_info, &dst).unwrap();
|
||||
let m = CS::Group::hash_to_scalar::<CS::Hash>(&framed_info, &dst.as_dst()).unwrap();
|
||||
|
||||
let t = sk + &m;
|
||||
|
||||
@@ -723,7 +720,7 @@ where
|
||||
)?;
|
||||
|
||||
Ok(blinds
|
||||
.zip(messages.into_iter())
|
||||
.zip(messages)
|
||||
.map(|(blind, x)| x.0 * &CS::Group::invert_scalar(blind)))
|
||||
}
|
||||
|
||||
@@ -810,8 +807,8 @@ mod tests {
|
||||
{
|
||||
let t = compute_tweak::<CS>(key, Some(info)).unwrap();
|
||||
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(mode));
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst).unwrap();
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, mode);
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).unwrap();
|
||||
|
||||
// evaluatedElement = G.ScalarInverse(t) * blindedElement
|
||||
let res = point * &CS::Group::invert_scalar(t);
|
||||
@@ -864,10 +861,9 @@ mod tests {
|
||||
.blind_evaluate(&mut rng, &client_blind_result.message, Some(info))
|
||||
.unwrap();
|
||||
let wrong_pk = {
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP)
|
||||
.concat(create_context_string::<CS>(Mode::Oprf));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, Mode::Oprf);
|
||||
// Choose a group element that is unlikely to be the right public key
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[b"msg"], &dst).unwrap()
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[b"msg"], &dst.as_dst()).unwrap()
|
||||
};
|
||||
let client_finalize_result = client_blind_result.state.finalize(
|
||||
input,
|
||||
@@ -970,6 +966,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_functionality() -> Result<()> {
|
||||
use p256::NistP256;
|
||||
use p384::NistP384;
|
||||
use p521::NistP521;
|
||||
|
||||
#[cfg(feature = "ristretto255")]
|
||||
{
|
||||
@@ -990,6 +988,20 @@ mod tests {
|
||||
zeroize_verifiable_client::<NistP256>();
|
||||
zeroize_verifiable_server::<NistP256>();
|
||||
|
||||
verifiable_retrieval::<NistP384>();
|
||||
verifiable_bad_public_key::<NistP384>();
|
||||
verifiable_server_evaluate::<NistP384>();
|
||||
|
||||
zeroize_verifiable_client::<NistP384>();
|
||||
zeroize_verifiable_server::<NistP384>();
|
||||
|
||||
verifiable_retrieval::<NistP521>();
|
||||
verifiable_bad_public_key::<NistP521>();
|
||||
verifiable_server_evaluate::<NistP521>();
|
||||
|
||||
zeroize_verifiable_client::<NistP521>();
|
||||
zeroize_verifiable_server::<NistP521>();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Handles the serialization of each of the components used in the VOPRF
|
||||
//! protocol
|
||||
@@ -306,11 +307,11 @@ fn deserialize_scalar<G: Group>(input: &mut &[u8]) -> Result<G::Scalar> {
|
||||
}
|
||||
|
||||
trait SliceExt {
|
||||
fn take_ext(self: &mut &Self, take: usize) -> Option<&Self>;
|
||||
fn take_ext<'a>(self: &mut &'a Self, take: usize) -> Option<&'a Self>;
|
||||
}
|
||||
|
||||
impl<T> SliceExt for [T] {
|
||||
fn take_ext(self: &mut &Self, take: usize) -> Option<&Self> {
|
||||
fn take_ext<'a>(self: &mut &'a Self, take: usize) -> Option<&'a Self> {
|
||||
if take > self.len() {
|
||||
return None;
|
||||
}
|
||||
@@ -389,6 +390,8 @@ mod test {
|
||||
}
|
||||
|
||||
let _ = $item::<p256::NistP256>::deserialize(&$bytes[..]);
|
||||
let _ = $item::<p384::NistP384>::deserialize(&$bytes[..]);
|
||||
let _ = $item::<p521::NistP521>::deserialize(&$bytes[..]);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+915
-1027
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::cmp::min;
|
||||
|
||||
+5
-4
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
mod cfrg_vectors;
|
||||
mod mock_rng;
|
||||
|
||||
+8
-7
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
@@ -14,7 +15,7 @@ pub(crate) fn rfc_to_json(input: &str) -> String {
|
||||
}
|
||||
|
||||
fn parse_ciphersuites(input: &str) -> String {
|
||||
let re = regex::Regex::new(r"## OPRF\((?P<ciphersuite>.+?)\)").unwrap();
|
||||
let re = regex::Regex::new(r"\nA\.\d\. (?P<ciphersuite>.+?)\n\n").unwrap();
|
||||
let mut ciphersuites = vec![];
|
||||
|
||||
let chunks: Vec<&str> = re.split(input).collect();
|
||||
@@ -33,7 +34,7 @@ fn parse_ciphersuites(input: &str) -> String {
|
||||
}
|
||||
|
||||
fn parse_modes(input: &str) -> String {
|
||||
let re = regex::Regex::new(r"### (?P<mode>.*+) Mode").unwrap();
|
||||
let re = regex::Regex::new(r"A\.\d.\d\. (?P<mode>.*?) Mode").unwrap();
|
||||
let mut modes = vec![];
|
||||
|
||||
let chunks: Vec<&str> = re.split(input).collect();
|
||||
@@ -52,7 +53,7 @@ fn parse_modes(input: &str) -> String {
|
||||
}
|
||||
|
||||
fn parse_vectors(input: &str) -> String {
|
||||
let re = regex::Regex::new(r"Test Vector.*+\n").unwrap();
|
||||
let re = regex::Regex::new(r"A\.\d.\d\.\d\. Test Vector.*+\n").unwrap();
|
||||
let mut vectors = vec![];
|
||||
|
||||
let chunks: Vec<&str> = re.split(input).collect();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
use alloc::string::String;
|
||||
use alloc::vec;
|
||||
@@ -87,6 +88,8 @@ macro_rules! json_to_test_vectors {
|
||||
#[test]
|
||||
fn test_vectors() -> Result<()> {
|
||||
use p256::NistP256;
|
||||
use p384::NistP384;
|
||||
use p521::NistP521;
|
||||
|
||||
let rfc: Value = serde_json::from_str(rfc_to_json(super::cfrg_vectors::VECTORS).as_str())
|
||||
.expect("Could not parse json");
|
||||
@@ -97,7 +100,7 @@ fn test_vectors() -> Result<()> {
|
||||
|
||||
let ristretto_oprf_tvs = json_to_test_vectors!(
|
||||
rfc,
|
||||
String::from("ristretto255, SHA-512"),
|
||||
String::from("ristretto255-SHA512"),
|
||||
String::from("OPRF")
|
||||
);
|
||||
assert_ne!(ristretto_oprf_tvs.len(), 0);
|
||||
@@ -109,7 +112,7 @@ fn test_vectors() -> Result<()> {
|
||||
|
||||
let ristretto_voprf_tvs = json_to_test_vectors!(
|
||||
rfc,
|
||||
String::from("ristretto255, SHA-512"),
|
||||
String::from("ristretto255-SHA512"),
|
||||
String::from("VOPRF")
|
||||
);
|
||||
assert_ne!(ristretto_voprf_tvs.len(), 0);
|
||||
@@ -121,7 +124,7 @@ fn test_vectors() -> Result<()> {
|
||||
|
||||
let ristretto_poprf_tvs = json_to_test_vectors!(
|
||||
rfc,
|
||||
String::from("ristretto255, SHA-512"),
|
||||
String::from("ristretto255-SHA512"),
|
||||
String::from("POPRF")
|
||||
);
|
||||
assert_ne!(ristretto_poprf_tvs.len(), 0);
|
||||
@@ -133,7 +136,7 @@ fn test_vectors() -> Result<()> {
|
||||
}
|
||||
|
||||
let p256_oprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("OPRF"));
|
||||
json_to_test_vectors!(rfc, String::from("P256-SHA256"), String::from("OPRF"));
|
||||
assert_ne!(p256_oprf_tvs.len(), 0);
|
||||
test_oprf_seed_to_key::<NistP256>(&p256_oprf_tvs)?;
|
||||
test_oprf_blind::<NistP256>(&p256_oprf_tvs)?;
|
||||
@@ -142,7 +145,7 @@ fn test_vectors() -> Result<()> {
|
||||
test_oprf_evaluate::<NistP256>(&p256_oprf_tvs)?;
|
||||
|
||||
let p256_voprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("VOPRF"));
|
||||
json_to_test_vectors!(rfc, String::from("P256-SHA256"), String::from("VOPRF"));
|
||||
assert_ne!(p256_voprf_tvs.len(), 0);
|
||||
test_voprf_seed_to_key::<NistP256>(&p256_voprf_tvs)?;
|
||||
test_voprf_blind::<NistP256>(&p256_voprf_tvs)?;
|
||||
@@ -151,7 +154,7 @@ fn test_vectors() -> Result<()> {
|
||||
test_voprf_evaluate::<NistP256>(&p256_voprf_tvs)?;
|
||||
|
||||
let p256_poprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("POPRF"));
|
||||
json_to_test_vectors!(rfc, String::from("P256-SHA256"), String::from("POPRF"));
|
||||
assert_ne!(p256_poprf_tvs.len(), 0);
|
||||
test_poprf_seed_to_key::<NistP256>(&p256_poprf_tvs)?;
|
||||
test_poprf_blind::<NistP256>(&p256_poprf_tvs)?;
|
||||
@@ -159,6 +162,60 @@ fn test_vectors() -> Result<()> {
|
||||
test_poprf_finalize::<NistP256>(&p256_poprf_tvs)?;
|
||||
test_poprf_evaluate::<NistP256>(&p256_poprf_tvs)?;
|
||||
|
||||
let p384_oprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P384-SHA384"), String::from("OPRF"));
|
||||
assert_ne!(p384_oprf_tvs.len(), 0);
|
||||
test_oprf_seed_to_key::<NistP384>(&p384_oprf_tvs)?;
|
||||
test_oprf_blind::<NistP384>(&p384_oprf_tvs)?;
|
||||
test_oprf_blind_evaluate::<NistP384>(&p384_oprf_tvs)?;
|
||||
test_oprf_finalize::<NistP384>(&p384_oprf_tvs)?;
|
||||
test_oprf_evaluate::<NistP384>(&p384_oprf_tvs)?;
|
||||
|
||||
let p384_voprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P384-SHA384"), String::from("VOPRF"));
|
||||
assert_ne!(p384_voprf_tvs.len(), 0);
|
||||
test_voprf_seed_to_key::<NistP384>(&p384_voprf_tvs)?;
|
||||
test_voprf_blind::<NistP384>(&p384_voprf_tvs)?;
|
||||
test_voprf_blind_evaluate::<NistP384>(&p384_voprf_tvs)?;
|
||||
test_voprf_finalize::<NistP384>(&p384_voprf_tvs)?;
|
||||
test_voprf_evaluate::<NistP384>(&p384_voprf_tvs)?;
|
||||
|
||||
let p384_poprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P384-SHA384"), String::from("POPRF"));
|
||||
assert_ne!(p384_poprf_tvs.len(), 0);
|
||||
test_poprf_seed_to_key::<NistP384>(&p384_poprf_tvs)?;
|
||||
test_poprf_blind::<NistP384>(&p384_poprf_tvs)?;
|
||||
test_poprf_blind_evaluate::<NistP384>(&p384_poprf_tvs)?;
|
||||
test_poprf_finalize::<NistP384>(&p384_poprf_tvs)?;
|
||||
test_poprf_evaluate::<NistP384>(&p384_poprf_tvs)?;
|
||||
|
||||
let p521_oprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P521-SHA512"), String::from("OPRF"));
|
||||
assert_ne!(p521_oprf_tvs.len(), 0);
|
||||
test_oprf_seed_to_key::<NistP521>(&p521_oprf_tvs)?;
|
||||
test_oprf_blind::<NistP521>(&p521_oprf_tvs)?;
|
||||
test_oprf_blind_evaluate::<NistP521>(&p521_oprf_tvs)?;
|
||||
test_oprf_finalize::<NistP521>(&p521_oprf_tvs)?;
|
||||
test_oprf_evaluate::<NistP521>(&p521_oprf_tvs)?;
|
||||
|
||||
let p521_voprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P521-SHA512"), String::from("VOPRF"));
|
||||
assert_ne!(p521_voprf_tvs.len(), 0);
|
||||
test_voprf_seed_to_key::<NistP521>(&p521_voprf_tvs)?;
|
||||
test_voprf_blind::<NistP521>(&p521_voprf_tvs)?;
|
||||
test_voprf_blind_evaluate::<NistP521>(&p521_voprf_tvs)?;
|
||||
test_voprf_finalize::<NistP521>(&p521_voprf_tvs)?;
|
||||
test_voprf_evaluate::<NistP521>(&p521_voprf_tvs)?;
|
||||
|
||||
let p521_poprf_tvs =
|
||||
json_to_test_vectors!(rfc, String::from("P521-SHA512"), String::from("POPRF"));
|
||||
assert_ne!(p521_poprf_tvs.len(), 0);
|
||||
test_poprf_seed_to_key::<NistP521>(&p521_poprf_tvs)?;
|
||||
test_poprf_blind::<NistP521>(&p521_poprf_tvs)?;
|
||||
test_poprf_blind_evaluate::<NistP521>(&p521_poprf_tvs)?;
|
||||
test_poprf_finalize::<NistP521>(&p521_poprf_tvs)?;
|
||||
test_poprf_evaluate::<NistP521>(&p521_poprf_tvs)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+33
-15
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// This source code is licensed under both the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
// This source code is dual-licensed under either the MIT license found in the
|
||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
// of this source tree.
|
||||
// of this source tree. You may select, at your option, one of the above-listed
|
||||
// licenses.
|
||||
|
||||
//! Contains the main VOPRF API
|
||||
|
||||
@@ -536,7 +537,7 @@ where
|
||||
)?;
|
||||
|
||||
Ok(blinds
|
||||
.zip(messages.into_iter())
|
||||
.zip(messages)
|
||||
.map(|(blind, x)| x.0 * &CS::Group::invert_scalar(blind)))
|
||||
}
|
||||
|
||||
@@ -587,13 +588,12 @@ mod tests {
|
||||
|
||||
use ::alloc::vec;
|
||||
use ::alloc::vec::Vec;
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::Sum;
|
||||
use generic_array::ArrayLength;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use super::*;
|
||||
use crate::common::{create_context_string, STR_HASH_TO_GROUP};
|
||||
use crate::common::{Dst, STR_HASH_TO_GROUP};
|
||||
use crate::Group;
|
||||
|
||||
fn prf<CS: CipherSuite>(
|
||||
@@ -605,8 +605,8 @@ mod tests {
|
||||
<CS::Hash as OutputSizeUser>::OutputSize:
|
||||
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
|
||||
{
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP).concat(create_context_string::<CS>(mode));
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst).unwrap();
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, mode);
|
||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).unwrap();
|
||||
|
||||
let res = point * &key;
|
||||
|
||||
@@ -718,10 +718,9 @@ mod tests {
|
||||
.unwrap();
|
||||
let messages: Vec<_> = messages.collect();
|
||||
let wrong_pk = {
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP)
|
||||
.concat(create_context_string::<CS>(Mode::Oprf));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, Mode::Oprf);
|
||||
// Choose a group element that is unlikely to be the right public key
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[b"msg"], &dst).unwrap()
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[b"msg"], &dst.as_dst()).unwrap()
|
||||
};
|
||||
let client_finalize_result =
|
||||
VoprfClient::batch_finalize(&inputs, &client_states, &messages, &proof, wrong_pk);
|
||||
@@ -739,10 +738,9 @@ mod tests {
|
||||
let server = VoprfServer::<CS>::new(&mut rng).unwrap();
|
||||
let server_result = server.blind_evaluate(&mut rng, &client_blind_result.message);
|
||||
let wrong_pk = {
|
||||
let dst = GenericArray::from(STR_HASH_TO_GROUP)
|
||||
.concat(create_context_string::<CS>(Mode::Oprf));
|
||||
let dst = Dst::new::<CS, _, _>(STR_HASH_TO_GROUP, Mode::Oprf);
|
||||
// Choose a group element that is unlikely to be the right public key
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[b"msg"], &dst).unwrap()
|
||||
CS::Group::hash_to_curve::<CS::Hash>(&[b"msg"], &dst.as_dst()).unwrap()
|
||||
};
|
||||
let client_finalize_result = client_blind_result.state.finalize(
|
||||
input,
|
||||
@@ -837,6 +835,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_functionality() -> Result<()> {
|
||||
use p256::NistP256;
|
||||
use p384::NistP384;
|
||||
use p521::NistP521;
|
||||
|
||||
#[cfg(feature = "ristretto255")]
|
||||
{
|
||||
@@ -861,6 +861,24 @@ mod tests {
|
||||
zeroize_voprf_client::<NistP256>();
|
||||
zeroize_voprf_server::<NistP256>();
|
||||
|
||||
verifiable_retrieval::<NistP384>();
|
||||
verifiable_batch_retrieval::<NistP384>();
|
||||
verifiable_bad_public_key::<NistP384>();
|
||||
verifiable_batch_bad_public_key::<NistP384>();
|
||||
verifiable_server_evaluate::<NistP384>();
|
||||
|
||||
zeroize_voprf_client::<NistP384>();
|
||||
zeroize_voprf_server::<NistP384>();
|
||||
|
||||
verifiable_retrieval::<NistP521>();
|
||||
verifiable_batch_retrieval::<NistP521>();
|
||||
verifiable_bad_public_key::<NistP521>();
|
||||
verifiable_batch_bad_public_key::<NistP521>();
|
||||
verifiable_server_evaluate::<NistP521>();
|
||||
|
||||
zeroize_voprf_client::<NistP521>();
|
||||
zeroize_voprf_server::<NistP521>();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user