Skip to content

Commit

Permalink
Merge pull request #24 from cryspen/jonas/wasm-demo
Browse files Browse the repository at this point in the history
WASM demo
  • Loading branch information
jschneider-bensch authored Sep 27, 2023
2 parents f620b99 + df13ded commit ad86833
Show file tree
Hide file tree
Showing 18 changed files with 1,324 additions and 80 deletions.
2 changes: 2 additions & 0 deletions hacspec-scrambledb/oprf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ p256.workspace = true
hash-to-curve.workspace = true
elgamal.workspace = true
hacspec_lib.workspace = true
sha256.workspace = true

[dev-dependencies]
serde_json = { version = "1.0.102" }
hex = { version = "0.4.3", features = ["serde"] }
serde = { version = "1.0.180", features = ["derive"] }
log = "0.4.19"
pretty_env_logger = "0.5.0"
rand = "0.8.5"
203 changes: 192 additions & 11 deletions hacspec-scrambledb/oprf/src/coprf/coprf_online.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ use elgamal::Ciphertext;
use hacspec_lib::Randomness;

use super::coprf_setup::{BlindingPublicKey, CoPRFKey};
use crate::{
coprf::coprf_setup::{CoPRFReceiverContext, CoPRFRequesterContext},
p256_sha256, Error,
};
use crate::{coprf::coprf_setup::CoPRFReceiverContext, p256_sha256, Error};
use p256::{NatMod, P256Point};

/// CoPRF Inputs can be arbitrary byte strings.
Expand Down Expand Up @@ -100,23 +97,25 @@ pub fn prepare_blind_convert(
/// collusion-resistance.
pub fn blind_convert(
bpk: BlindingPublicKey,
key_i: CoPRFKey,
key_j: CoPRFKey,
key_from: CoPRFKey,
key_to: CoPRFKey,
blind_input: BlindInput,
randomness: &mut Randomness,
) -> Result<BlindOutput, Error> {
let delta = key_j * key_i.inv();
let delta = key_to * key_from.inv();
let ctx_rerandomized = elgamal::rerandomize(bpk, blind_input, randomness)?;
elgamal::scalar_mul_ciphertext(delta, ctx_rerandomized).map_err(|e| e.into())
}

#[cfg(test)]
mod tests {
use crate::coprf::coprf_setup::{derive_key, CoPRFEvaluatorContext};

use super::*;

// =========== Unblinded Operations ===========

/// The clear evaluation of the PRF based on the PRF by Naor, Pinkas, and Reingold:
/// The cleartext evaluation of the PRF based on the PRF by Naor, Pinkas, and Reingold:
///
/// ```text
/// PRF: K x X -> G
Expand Down Expand Up @@ -154,13 +153,195 @@ mod tests {
/// is performed by first computing a `delta` scalar from both evaluation
/// keys, which when mulitplied with the output to convert will cancel out
/// the original evaluation key and multiply by the target evaluation key.
pub fn convert(key_i: CoPRFKey, key_j: CoPRFKey, y: Output) -> Result<Output, Error> {
let delta = key_j * key_i.inv();
pub fn convert(
key_origin: CoPRFKey,
key_destination: CoPRFKey,
y: Output,
) -> Result<Output, Error> {
let delta = key_destination * key_origin.inv();
let result = p256::p256_point_mul(delta, y)?;

Ok(result)
}

fn generate_randomness() -> Randomness {
use rand::prelude::*;

let mut rng = rand::thread_rng();
let mut randomness = [0u8; 1000000];
rng.fill_bytes(&mut randomness);
let randomness = Randomness::new(randomness.to_vec());

randomness
}

#[test]
fn self_test_eval_convert() {
let mut randomness = generate_randomness();

let test_context = b"Test";
let test_input = b"TestInput";
let evaluator_context = CoPRFEvaluatorContext::new(&mut randomness).unwrap();

let key_origin1 = derive_key(&evaluator_context, b"1").unwrap();
let key_origin2 = derive_key(&evaluator_context, b"2").unwrap();
let key_destination = derive_key(&evaluator_context, b"3").unwrap();

let y_under_origin1 = evaluate(test_context, key_origin1, test_input).unwrap();
let y_under_origin2 = evaluate(test_context, key_origin2, test_input).unwrap();

let y_under_destination = evaluate(test_context, key_destination, test_input).unwrap();
let converted_y_from_1 = convert(key_origin1, key_destination, y_under_origin1).unwrap();
let converted_y_from_2 = convert(key_origin2, key_destination, y_under_origin2).unwrap();

assert_eq!(converted_y_from_1, converted_y_from_2);
assert_eq!(converted_y_from_1, y_under_destination);
}

#[test]
fn test_blind_evaluate() {
let mut randomness = generate_randomness();

let test_context = b"Test";
let test_input = b"TestInput";
let evaluator_context = CoPRFEvaluatorContext::new(&mut randomness).unwrap();
let receiver_context = CoPRFReceiverContext::new(&mut randomness);

let blind_input = blind(
receiver_context.get_bpk(),
test_input,
test_context.to_vec(),
&mut randomness,
)
.unwrap();

let evaluation_key = derive_key(&evaluator_context, b"TestKey").unwrap();
let blind_result = blind_evaluate(
evaluation_key,
receiver_context.get_bpk(),
blind_input,
&mut randomness,
)
.unwrap();

let unblinded_result = finalize(&receiver_context, blind_result).unwrap();

let expected_result = evaluate(test_context, evaluation_key, test_input).unwrap();

assert_eq!(unblinded_result, expected_result);
}

#[test]
fn test_name() {}
fn blind_convergence() {
let mut randomness = generate_randomness();

let test_context = b"Test";
let test_input = b"TestInput";
let evaluator_context = CoPRFEvaluatorContext::new(&mut randomness).unwrap();
let receiver_context = CoPRFReceiverContext::new(&mut randomness);

let key_origin1 = derive_key(&evaluator_context, b"1").unwrap();
let key_origin2 = derive_key(&evaluator_context, b"2").unwrap();
let key_destination = derive_key(&evaluator_context, b"3").unwrap();

let y_under_destination = evaluate(test_context, key_destination, test_input).unwrap();
let y1 = evaluate(test_context, key_origin1, test_input).unwrap();
let y2 = evaluate(test_context, key_origin2, test_input).unwrap();

let blind1 =
prepare_blind_convert(receiver_context.get_bpk(), y1, &mut randomness).unwrap();
let blind2 =
prepare_blind_convert(receiver_context.get_bpk(), y2, &mut randomness).unwrap();

let blind_result_1 = blind_convert(
receiver_context.get_bpk(),
key_origin1,
key_destination,
blind1,
&mut randomness,
)
.unwrap();

let blind_result_2 = blind_convert(
receiver_context.get_bpk(),
key_origin2,
key_destination,
blind2,
&mut randomness,
)
.unwrap();

let res1 = finalize(&receiver_context, blind_result_1).unwrap();
let res2 = finalize(&receiver_context, blind_result_2).unwrap();

assert_eq!(res1, res2);
assert_eq!(res1, y_under_destination);
}
#[test]
fn test_blind_conversion() {
let mut randomness = generate_randomness();

let test_context = b"Test";
let test_input = b"TestInput";
let evaluator_context = CoPRFEvaluatorContext::new(&mut randomness).unwrap();
let receiver_context = CoPRFReceiverContext::new(&mut randomness);

let blind_input = blind(
receiver_context.get_bpk(),
test_input,
test_context.to_vec(),
&mut randomness,
)
.unwrap();

let key_eval = derive_key(&evaluator_context, b"TestKey").unwrap();
let key_destination = derive_key(&evaluator_context, b"DestinationKey").unwrap();

let blind_result = blind_evaluate(
key_eval,
receiver_context.get_bpk(),
blind_input,
&mut randomness,
)
.unwrap();

let expected_result = evaluate(test_context, key_destination, test_input).unwrap();

// converting the blinded result directly
let blind_converted_result = blind_convert(
receiver_context.get_bpk(),
key_eval,
key_destination,
blind_result,
&mut randomness,
)
.unwrap();

let unblinded_converted_result =
finalize(&receiver_context, blind_converted_result).unwrap();
assert_eq!(expected_result, unblinded_converted_result);

// converting after unblinding and re-blinding
let unblinded_intermediate_result = finalize(&receiver_context, blind_result).unwrap();

let prepped_input = prepare_blind_convert(
receiver_context.get_bpk(),
unblinded_intermediate_result,
&mut randomness,
)
.unwrap();

let blind_converted_result = blind_convert(
receiver_context.get_bpk(),
key_eval,
key_destination,
prepped_input,
&mut randomness,
)
.unwrap();

let unblinded_converted_result =
finalize(&receiver_context, blind_converted_result).unwrap();
assert_eq!(expected_result, unblinded_converted_result);
}
}
12 changes: 8 additions & 4 deletions hacspec-scrambledb/oprf/src/coprf/coprf_setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ pub type BlindingPrivateKey = elgamal::DecryptionKey;
/// `Nsk` bytes of entropy is provided to the key derivation
/// algorithm, where `Nsk` is the number of bytes to represent a valid
/// private key, i.e. a P256 scalar in our case.
pub type CoPRFMasterSecret = [u8; 32];
pub type CoPRFMasterSecret = Vec<u8>;
const COPRF_MSK_BYTES: usize = 32;

/// A coPRF evaluation key is identified by a bytestring of arbitrary
/// length.
Expand Down Expand Up @@ -78,8 +79,9 @@ impl CoPRFEvaluatorContext {
/// ### E.1.2. Evaluator Setup
/// The coPRF evaluator holds the master secret as well as any PRF
/// evaluation keys derived from it.
pub fn new(msk: CoPRFMasterSecret) -> Self {
CoPRFEvaluatorContext { msk }
pub fn new(randomness: &mut Randomness) -> Result<Self, Error> {
let msk = randomness.bytes(COPRF_MSK_BYTES)?.to_vec();
Ok(CoPRFEvaluatorContext { msk })
}
}

Expand Down Expand Up @@ -120,5 +122,7 @@ pub fn derive_key(context: &CoPRFEvaluatorContext, key_id: &[u8]) -> Result<CoPR
let mut key_material = context.msk.to_vec();
key_material.extend_from_slice(key_id);

p256::random_scalar(&mut Randomness::new(key_material)).map_err(|e| e.into())
let random_bytes = sha256::hash(&key_material);

p256::random_scalar(&mut Randomness::new(random_bytes.to_vec())).map_err(|e| e.into())
}
7 changes: 7 additions & 0 deletions hacspec-scrambledb/oprf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum Error {
CurveError,
HashToCurveError,
ElgamalError,
RandomnessError,
}

impl From<p256::Error> for Error {
Expand All @@ -27,6 +28,12 @@ impl From<elgamal::Error> for Error {
}
}

impl From<hacspec_lib::Error> for Error {
fn from(_value: hacspec_lib::Error) -> Self {
Self::RandomnessError
}
}

// 3. Protocol
pub mod protocol;

Expand Down
3 changes: 3 additions & 0 deletions hacspec-scrambledb/prp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ edition = "2021"

[dependencies]
hacspec_lib.workspace = true

[dev-dependencies]
rand = "0.8.5"
16 changes: 16 additions & 0 deletions hacspec-scrambledb/prp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,19 @@ pub fn prp(input: Block, key: &ChaChaKey) -> Block {
let state = chacha20_init(key, b"scrambledbiv", 1);
chacha20_encrypt_block(state, 2, &input)
}

#[cfg(test)]
mod tests {
use super::*;
use rand::prelude::*;

#[test]
fn test_inversion() {
let mut key = [0u8; 32];
rand::thread_rng().fill_bytes(&mut key);

let block = [1u8; 64];
assert_ne!(block, prp(block, &key));
assert_eq!(block, prp(prp(block, &key), &key));
}
}
33 changes: 33 additions & 0 deletions hacspec-scrambledb/scrambledb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,42 @@ edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["rlib", "cdylib"]

[dependencies]
oprf.workspace = true
elgamal.workspace = true
prp.workspace = true
p256.workspace = true
hacspec_lib.workspace = true
hash-to-curve.workspace = true

wasm-bindgen = { version = "0.2.87", optional = true }
rand = { version = "0.8.5", optional = true }
getrandom = { version = "0.2.10", features = ["js"], optional = true }
hex = { version = "0.4.3", optional = true }


gloo-utils = { version = "0.1", features = ["serde"] }
serde_json = "1.0.106"

[dependencies.web-sys]
version = "0.3.4"
optional = true
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
'console',
'HtmlTableElement',
'HtmlTableRowElement',
]

[features]
wasm = ["wasm-bindgen", "getrandom", "web-sys", "rand", "hex"]

[dev-dependencies]
scrambledb = { path = ".", features = ["rand"] }
1 change: 1 addition & 0 deletions hacspec-scrambledb/scrambledb/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ impl From<oprf::Error> for Error {
oprf::Error::CurveError => Self::CorruptedData,
oprf::Error::HashToCurveError => Self::CorruptedData,
oprf::Error::ElgamalError => Self::RandomnessError,
oprf::Error::RandomnessError => Self::RandomnessError,
}
}
}
Expand Down
Loading

0 comments on commit ad86833

Please sign in to comment.