Adding p256 support and no_std CI (#2)
This commit is contained in:
@@ -15,6 +15,7 @@ jobs:
|
|||||||
backend_feature:
|
backend_feature:
|
||||||
- u64_backend
|
- u64_backend
|
||||||
- u32_backend
|
- u32_backend
|
||||||
|
- p256,u64_backend
|
||||||
toolchain:
|
toolchain:
|
||||||
- stable
|
- stable
|
||||||
- 1.51.0
|
- 1.51.0
|
||||||
@@ -43,6 +44,28 @@ jobs:
|
|||||||
command: test
|
command: test
|
||||||
args: --no-default-features --features std --features ${{ matrix.backend_feature }}
|
args: --no-default-features --features std --features ${{ matrix.backend_feature }}
|
||||||
|
|
||||||
|
build-no-std:
|
||||||
|
name: Build with no-std on ${{ matrix.target }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target:
|
||||||
|
# for wasm
|
||||||
|
- wasm32-unknown-unknown
|
||||||
|
# for any no_std target
|
||||||
|
- thumbv6m-none-eabi
|
||||||
|
backend_feature:
|
||||||
|
- u64_backend
|
||||||
|
- u32_backend
|
||||||
|
- p256,u64_backend
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: hecrj/setup-rust-action@v1
|
||||||
|
- run: rustup target add ${{ matrix.target }}
|
||||||
|
- run: cargo build --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.backend_feature }}
|
||||||
|
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
name: cargo clippy
|
name: cargo clippy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
+13
-1
@@ -3,15 +3,18 @@ name = "voprf"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
description = "An implementation of a verifiable oblivious pseudorandom function (VOPRF)"
|
description = "An implementation of a verifiable oblivious pseudorandom function (VOPRF)"
|
||||||
authors = ["Kevin Lewi <[email protected]>"]
|
authors = ["Kevin Lewi <[email protected]>"]
|
||||||
|
categories = ["no-std"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["u64_backend"]
|
default = ["u64_backend"]
|
||||||
|
p256 = ["num-bigint", "num-integer", "num-traits", "once_cell", "p256_"]
|
||||||
|
std = ["curve25519-dalek/std", "getrandom", "rand/std", "rand/std_rng", "num-bigint/std", "num-integer/std", "num-traits/std"]
|
||||||
u64_backend = ["curve25519-dalek/u64_backend"]
|
u64_backend = ["curve25519-dalek/u64_backend"]
|
||||||
u32_backend = ["curve25519-dalek/u32_backend"]
|
u32_backend = ["curve25519-dalek/u32_backend"]
|
||||||
std = ["curve25519-dalek/std", "getrandom", "rand/std", "rand/std_rng"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
constant_time_eq = "0.1"
|
constant_time_eq = "0.1"
|
||||||
@@ -22,10 +25,18 @@ generic-array = "0.14"
|
|||||||
getrandom = { version = "0.2", optional = true }
|
getrandom = { version = "0.2", optional = true }
|
||||||
hkdf = "0.11"
|
hkdf = "0.11"
|
||||||
hmac = "0.11"
|
hmac = "0.11"
|
||||||
|
num-bigint = { version = "0.4", default-features = false, optional = true }
|
||||||
|
num-integer = { version = "0.1", default-features = false, optional = true }
|
||||||
|
num-traits = { version = "0.2", default-features = false, optional = true }
|
||||||
|
once_cell = { version = "1", default-features = false, optional = true }
|
||||||
|
p256_ = { package = "p256", version = "0.9", default-features = false, features = ["arithmetic", "zeroize"], optional = true }
|
||||||
rand = { version = "0.8", default-features = false }
|
rand = { version = "0.8", default-features = false }
|
||||||
subtle = { version = "2.3", default-features = false }
|
subtle = { version = "2.3", default-features = false }
|
||||||
zeroize = { version = "1", features = ["zeroize_derive"] }
|
zeroize = { version = "1", features = ["zeroize_derive"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
getrandom = { version = "0.2", features = ["js"], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
@@ -37,3 +48,4 @@ serde_json = "1"
|
|||||||
sha2 = "0.9"
|
sha2 = "0.9"
|
||||||
proptest = "1"
|
proptest = "1"
|
||||||
rustyline = "8"
|
rustyline = "8"
|
||||||
|
voprf = { path = "", default-features = false, features = ["std"] }
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ mod expand;
|
|||||||
#[cfg(feature = "p256")]
|
#[cfg(feature = "p256")]
|
||||||
pub(crate) mod p256;
|
pub(crate) mod p256;
|
||||||
mod ristretto;
|
mod ristretto;
|
||||||
mod x25519;
|
|
||||||
|
|
||||||
use crate::errors::InternalError;
|
use crate::errors::InternalError;
|
||||||
use crate::hash::Hash;
|
use crate::hash::Hash;
|
||||||
|
|||||||
+3
-3
@@ -9,7 +9,7 @@
|
|||||||
)]
|
)]
|
||||||
|
|
||||||
use super::Group;
|
use super::Group;
|
||||||
use crate::errors::{InternalError, ProtocolError};
|
use crate::errors::InternalError;
|
||||||
use crate::hash::Hash;
|
use crate::hash::Hash;
|
||||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
@@ -35,7 +35,7 @@ impl Group for ProjectivePoint {
|
|||||||
|
|
||||||
// Implements the `hash_to_curve()` function from
|
// Implements the `hash_to_curve()` function from
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
|
||||||
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, ProtocolError> {
|
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalError> {
|
||||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
|
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
|
||||||
// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1`
|
// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1`
|
||||||
const P: Lazy<BigInt> = Lazy::new(|| {
|
const P: Lazy<BigInt> = Lazy::new(|| {
|
||||||
@@ -83,7 +83,7 @@ impl Group for ProjectivePoint {
|
|||||||
|
|
||||||
// Implements the `HashToScalar()` function from
|
// Implements the `HashToScalar()` function from
|
||||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.3
|
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.3
|
||||||
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, ProtocolError> {
|
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, InternalError> {
|
||||||
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0]
|
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0]
|
||||||
// P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369`
|
// P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369`
|
||||||
const N: once_cell::unsync::Lazy<BigInt> = once_cell::unsync::Lazy::new(|| {
|
const N: once_cell::unsync::Lazy<BigInt> = once_cell::unsync::Lazy::new(|| {
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
//
|
|
||||||
// This source code is licensed under the MIT license found in the
|
|
||||||
// LICENSE file in the root directory of this source tree.
|
|
||||||
|
|
||||||
use super::Group;
|
|
||||||
use crate::errors::InternalError;
|
|
||||||
use crate::hash::Hash;
|
|
||||||
use curve25519_dalek::{constants::X25519_BASEPOINT, montgomery::MontgomeryPoint, scalar::Scalar};
|
|
||||||
use generic_array::{typenum::U32, GenericArray};
|
|
||||||
use rand::{CryptoRng, RngCore};
|
|
||||||
|
|
||||||
/// The implementation of such a subgroup for Ristretto
|
|
||||||
impl Group for MontgomeryPoint {
|
|
||||||
const SUITE_ID: usize = 0xFFFF;
|
|
||||||
|
|
||||||
fn map_to_curve<H: Hash>(_msg: &[u8], _dst: &[u8]) -> Result<Self, InternalError> {
|
|
||||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_to_scalar<H: Hash>(_input: &[u8], _dst: &[u8]) -> Result<Self::Scalar, InternalError> {
|
|
||||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
|
||||||
}
|
|
||||||
|
|
||||||
type Scalar = Scalar;
|
|
||||||
type ScalarLen = U32;
|
|
||||||
fn from_scalar_slice(
|
|
||||||
scalar_bits: &GenericArray<u8, Self::ScalarLen>,
|
|
||||||
) -> Result<Self::Scalar, InternalError> {
|
|
||||||
Ok(Scalar::from_bytes_mod_order(*scalar_bits.as_ref()))
|
|
||||||
}
|
|
||||||
fn random_nonzero_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
|
|
||||||
loop {
|
|
||||||
let scalar = {
|
|
||||||
#[cfg(not(test))]
|
|
||||||
{
|
|
||||||
let mut scalar_bytes = [0u8; 64];
|
|
||||||
rng.fill_bytes(&mut scalar_bytes);
|
|
||||||
Scalar::from_bytes_mod_order_wide(&scalar_bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests need an exact conversion from bytes to scalar, sampling only 32 bytes from rng
|
|
||||||
#[cfg(test)]
|
|
||||||
{
|
|
||||||
let mut scalar_bytes = [0u8; 32];
|
|
||||||
rng.fill_bytes(&mut scalar_bytes);
|
|
||||||
Scalar::from_bytes_mod_order(scalar_bytes)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if scalar != Scalar::zero() {
|
|
||||||
break scalar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn scalar_as_bytes(scalar: Self::Scalar) -> GenericArray<u8, Self::ScalarLen> {
|
|
||||||
scalar.to_bytes().into()
|
|
||||||
}
|
|
||||||
fn scalar_invert(_scalar: &Self::Scalar) -> Self::Scalar {
|
|
||||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
|
||||||
}
|
|
||||||
|
|
||||||
// The byte length necessary to represent group elements
|
|
||||||
type ElemLen = U32;
|
|
||||||
fn from_element_slice(
|
|
||||||
element_bits: &GenericArray<u8, Self::ElemLen>,
|
|
||||||
) -> Result<Self, InternalError> {
|
|
||||||
Ok(Self(*element_bits.as_ref()))
|
|
||||||
}
|
|
||||||
// serialization of a group element
|
|
||||||
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
|
|
||||||
self.to_bytes().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn base_point() -> Self {
|
|
||||||
X25519_BASEPOINT
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mult_by_slice(&self, scalar: &GenericArray<u8, Self::ScalarLen>) -> Self {
|
|
||||||
self * Scalar::from_bits(*scalar.as_ref())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns if the group element is equal to the identity (1)
|
|
||||||
fn is_identity(&self) -> bool {
|
|
||||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ct_equal(&self, _other: &Self) -> bool {
|
|
||||||
unreachable!("this algorithm should only be used as the `KeGroup`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -89,26 +89,29 @@ fn populate_test_vectors(values: &Value) -> VOPRFTestVectorParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Ristretto255Sha512;
|
|
||||||
impl CipherSuite for Ristretto255Sha512 {
|
|
||||||
type Group = RistrettoPoint;
|
|
||||||
type Hash = Sha512;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tests() -> Result<(), InternalError> {
|
fn tests() -> Result<(), InternalError> {
|
||||||
|
struct Ristretto255Sha512;
|
||||||
|
impl CipherSuite for Ristretto255Sha512 {
|
||||||
|
type Group = RistrettoPoint;
|
||||||
|
type Hash = Sha512;
|
||||||
|
}
|
||||||
|
|
||||||
test_blind::<Ristretto255Sha512>(OPRF_RISTRETTO255_SHA512)?;
|
test_blind::<Ristretto255Sha512>(OPRF_RISTRETTO255_SHA512)?;
|
||||||
test_evaluate::<Ristretto255Sha512>(OPRF_RISTRETTO255_SHA512)?;
|
test_evaluate::<Ristretto255Sha512>(OPRF_RISTRETTO255_SHA512)?;
|
||||||
test_finalize::<Ristretto255Sha512>(OPRF_RISTRETTO255_SHA512)?;
|
test_finalize::<Ristretto255Sha512>(OPRF_RISTRETTO255_SHA512)?;
|
||||||
|
|
||||||
#[cfg(feature = "p256")]
|
#[cfg(feature = "p256")]
|
||||||
{
|
{
|
||||||
use p256_::ProjectivePoint;
|
struct P256Sha256;
|
||||||
use sha2::Sha256;
|
impl CipherSuite for P256Sha256 {
|
||||||
|
type Group = p256_::ProjectivePoint;
|
||||||
|
type Hash = sha2::Sha256;
|
||||||
|
}
|
||||||
|
|
||||||
test_blind::<ProjectivePoint, Sha256>(OPRF_P256_SHA256)?;
|
test_blind::<P256Sha256>(OPRF_P256_SHA256)?;
|
||||||
test_evaluate::<ProjectivePoint>(OPRF_P256_SHA256)?;
|
test_evaluate::<P256Sha256>(OPRF_P256_SHA256)?;
|
||||||
test_finalize::<ProjectivePoint, Sha256>(OPRF_P256_SHA256)?;
|
test_finalize::<P256Sha256>(OPRF_P256_SHA256)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user