Skip to content

Commit

Permalink
Merge pull request #84 from fjarri/verification-shortcuts
Browse files Browse the repository at this point in the history
Add skip_verification() and to_unverified() to kfrags/cfrags
  • Loading branch information
fjarri authored Dec 20, 2021
2 parents 22645d1 + 3fbc0b6 commit 3cf47a1
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 18 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `serde` support for types is now gated under the `serde-support` feature (not enabled by default). ([#82])


### Added

- `KeyFrag::skip_verification()`, `VerifiedKeyFrag::to_unverified()`, `CapsuleFrag::skip_verification()`, `VerifiedCapsuleFrag::to_unverified()`, and
the corresponding methods in Python and WASM bindings. ([#84])


[#82]: https://github.com/nucypher/rust-umbral/pull/82
[#84]: https://github.com/nucypher/rust-umbral/pull/84


## [0.3.3] - 2021-12-10
Expand Down
28 changes: 28 additions & 0 deletions umbral-pre-python/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,15 @@ API reference
Verifies the integrity of the fragment using the signing key and, optionally, the delegating and the receiving keys (if they were included in the signature in :py:func:`generate_kfrags`).

.. py:method:: skip_verification() -> VerifiedKeyFrag:
Explicitly skips verification.
Useful in cases when the verifying keys are impossible to obtain independently.

.. warning::

Make sure you considered the implications of not enforcing verification.

.. py:method:: __bytes__() -> bytes
Serializes the object into a bytestring.
Expand Down Expand Up @@ -218,6 +227,11 @@ API reference
Intended for internal storage;
make sure that the bytes come from a trusted source.

.. py:method:: to_unverified() -> KeyFrag:
Clears the verification status from the keyfrag.
Useful for the cases where it needs to be put in the protocol structure containing :py:class:`KeyFrag` types (since those are the ones that can be serialized/deserialized freely).

.. py:method:: __bytes__() -> bytes
Serializes the object into a bytestring.
Expand All @@ -234,6 +248,15 @@ API reference
Verifies the integrity of the fragment.

.. py:method:: skip_verification() -> VerifiedCapsuleFrag:
Explicitly skips verification.
Useful in cases when the verifying keys are impossible to obtain independently.

.. warning::

Make sure you considered the implications of not enforcing verification.

.. py:method:: __bytes__() -> bytes
Serializes the object into a bytestring.
Expand Down Expand Up @@ -262,6 +285,11 @@ API reference
Intended for internal storage;
make sure that the bytes come from a trusted source.

.. py:method:: to_unverified() -> KeyFrag:
Clears the verification status from the capsule frag.
Useful for the cases where it needs to be put in the protocol structure containing :py:class:`CapsuleFrag` types (since those are the ones that can be serialized/deserialized freely).

.. py:method:: __bytes__() -> bytes
Serializes the object into a bytestring.
Expand Down
24 changes: 24 additions & 0 deletions umbral-pre-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,12 @@ impl KeyFrag {
})
}

pub fn skip_verification(&self) -> VerifiedKeyFrag {
VerifiedKeyFrag {
backend: self.backend.clone().skip_verification(),
}
}

#[staticmethod]
pub fn from_bytes(data: &[u8]) -> PyResult<Self> {
from_bytes(data)
Expand Down Expand Up @@ -538,6 +544,12 @@ impl VerifiedKeyFrag {
umbral_pre::VerifiedKeyFrag::serialized_size()
}

pub fn to_unverified(&self) -> KeyFrag {
KeyFrag {
backend: self.backend.to_unverified(),
}
}

fn __bytes__(&self) -> PyResult<PyObject> {
to_bytes(self)
}
Expand Down Expand Up @@ -626,6 +638,12 @@ impl CapsuleFrag {
})
}

pub fn skip_verification(&self) -> VerifiedCapsuleFrag {
VerifiedCapsuleFrag {
backend: self.backend.clone().skip_verification(),
}
}

#[staticmethod]
pub fn from_bytes(data: &[u8]) -> PyResult<Self> {
from_bytes(data)
Expand Down Expand Up @@ -697,6 +715,12 @@ impl VerifiedCapsuleFrag {
umbral_pre::VerifiedCapsuleFrag::serialized_size()
}

pub fn to_unverified(&self) -> CapsuleFrag {
CapsuleFrag {
backend: self.backend.to_unverified(),
}
}

fn __bytes__(&self) -> PyResult<PyObject> {
to_bytes(self)
}
Expand Down
12 changes: 12 additions & 0 deletions umbral-pre-python/umbral_pre/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ class KeyFrag:
) -> VerifiedKeyFrag:
...

def skip_verification(self) -> VerifiedKeyFrag:
...

@staticmethod
def from_bytes() -> KeyFrag:
...
Expand All @@ -130,6 +133,9 @@ class VerifiedKeyFrag:
def from_verified_bytes(data: bytes) -> VerifiedKeyFrag:
...

def to_unverified(self) -> KeyFrag:
...

@staticmethod
def serialized_size() -> int:
...
Expand Down Expand Up @@ -158,6 +164,9 @@ class CapsuleFrag:
) -> VerifiedCapsuleFrag:
...

def skip_verification(self) -> VerifiedCapsuleFrag:
...

@staticmethod
def from_bytes() -> CapsuleFrag:
...
Expand All @@ -172,6 +181,9 @@ class VerifiedCapsuleFrag:
def from_verified_bytes(data: bytes) -> VerifiedCapsuleFrag:
...

def to_unverified(self) -> CapsuleFrag:
...

@staticmethod
def serialized_size() -> int:
...
Expand Down
20 changes: 20 additions & 0 deletions umbral-pre-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ impl CapsuleFrag {
.map_err(map_js_err)
}

#[wasm_bindgen(js_name = skipVerification)]
pub fn skip_verification(&self) -> VerifiedCapsuleFrag {
VerifiedCapsuleFrag(self.0.clone().skip_verification())
}

#[wasm_bindgen(js_name = toBytes)]
pub fn to_bytes(&self) -> Box<[u8]> {
self.0.to_array().to_vec().into_boxed_slice()
Expand Down Expand Up @@ -303,6 +308,11 @@ impl VerifiedCapsuleFrag {
.map_err(map_js_err)
}

#[wasm_bindgen(js_name = toUnverified)]
pub fn to_unverified(&self) -> CapsuleFrag {
CapsuleFrag(self.0.to_unverified())
}

#[wasm_bindgen(js_name = toBytes)]
pub fn to_bytes(&self) -> Box<[u8]> {
self.0.to_array().to_vec().into_boxed_slice()
Expand Down Expand Up @@ -462,6 +472,11 @@ impl KeyFrag {
.map_err(map_js_err)
}

#[wasm_bindgen(js_name = skipVerification)]
pub fn skip_verification(&self) -> VerifiedKeyFrag {
VerifiedKeyFrag(self.0.clone().skip_verification())
}

#[wasm_bindgen(js_name = toBytes)]
pub fn to_bytes(&self) -> Box<[u8]> {
self.0.to_array().to_vec().into_boxed_slice()
Expand Down Expand Up @@ -497,6 +512,11 @@ impl VerifiedKeyFrag {
.map_err(map_js_err)
}

#[wasm_bindgen(js_name = toUnverified)]
pub fn to_unverified(&self) -> KeyFrag {
KeyFrag(self.0.to_unverified())
}

#[wasm_bindgen(js_name = toBytes)]
pub fn to_bytes(&self) -> Box<[u8]> {
self.0.to_array().to_vec().into_boxed_slice()
Expand Down
5 changes: 2 additions & 3 deletions umbral-pre/bench/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkGroup, Criterion};

#[cfg(feature = "bench-internals")]
use umbral_pre::bench::{
capsule_from_public_key, capsule_open_original, capsule_open_reencrypted, get_cfrag,
unsafe_hash_to_point,
capsule_from_public_key, capsule_open_original, capsule_open_reencrypted, unsafe_hash_to_point,
};

use umbral_pre::{
Expand Down Expand Up @@ -74,7 +73,7 @@ fn bench_capsule_open_reencrypted<'a, M: Measurement>(group: &mut BenchmarkGroup

let cfrags: Vec<_> = vcfrags[0..threshold]
.iter()
.map(|vcfrag| get_cfrag(&vcfrag).clone())
.map(|vcfrag| vcfrag.to_unverified())
.collect();

group.bench_function("Capsule::open_reencrypted", |b| {
Expand Down
7 changes: 1 addition & 6 deletions umbral-pre/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use rand_core::OsRng;

use crate::capsule::{Capsule, KeySeed, OpenReencryptedError};
use crate::capsule_frag::{CapsuleFrag, VerifiedCapsuleFrag};
use crate::capsule_frag::CapsuleFrag;
use crate::keys::{PublicKey, SecretKey};
use crate::secret_box::SecretBox;

Expand All @@ -30,8 +30,3 @@ pub fn capsule_open_reencrypted(
) -> Result<SecretBox<KeySeed>, OpenReencryptedError> {
capsule.open_reencrypted(receiving_sk, delegating_pk, cfrags)
}

/// Extracts the internal [`CapsuleFrag`] from a [`VerifiedCapsuleFrag`].
pub fn get_cfrag(verified_cfrag: &VerifiedCapsuleFrag) -> &CapsuleFrag {
&verified_cfrag.cfrag
}
7 changes: 5 additions & 2 deletions umbral-pre/src/capsule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,10 @@ mod tests {
.map(|kfrag| reencrypt(&capsule, &kfrag))
.collect();

let cfrags: Vec<_> = vcfrags.iter().cloned().map(|vcfrag| vcfrag.cfrag).collect();
let cfrags: Vec<_> = vcfrags
.iter()
.map(|vcfrag| vcfrag.to_unverified())
.collect();

let key_seed_reenc = capsule
.open_reencrypted(&receiving_sk, &delegating_pk, &cfrags)
Expand All @@ -342,7 +345,7 @@ mod tests {
.iter()
.cloned()
.chain(vcfrags2[1..2].iter().cloned())
.map(|vcfrag| vcfrag.cfrag)
.map(|vcfrag| vcfrag.to_unverified())
.collect();

let result = capsule.open_reencrypted(&receiving_sk, &delegating_pk, &mismatched_cfrags);
Expand Down
20 changes: 18 additions & 2 deletions umbral-pre/src/capsule_frag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,14 +297,22 @@ impl CapsuleFrag {
cfrag: self.clone(),
})
}

/// Explicitly skips verification.
/// Useful in cases when the verifying keys are impossible to obtain independently.
///
/// **Warning:** make sure you considered the implications of not enforcing verification.
pub fn skip_verification(self) -> VerifiedCapsuleFrag {
VerifiedCapsuleFrag { cfrag: self }
}
}

/// Verified capsule fragment, good for dencryption.
/// Can be serialized, but cannot be deserialized directly.
/// It can only be obtained from [`CapsuleFrag::verify`].
/// It can only be obtained from [`CapsuleFrag::verify`] or [`CapsuleFrag::skip_verification`].
#[derive(Debug, Clone, PartialEq)]
pub struct VerifiedCapsuleFrag {
pub(crate) cfrag: CapsuleFrag,
cfrag: CapsuleFrag,
}

impl RepresentableAsArray for VerifiedCapsuleFrag {
Expand Down Expand Up @@ -348,6 +356,14 @@ impl VerifiedCapsuleFrag {
pub fn from_verified_bytes(data: impl AsRef<[u8]>) -> Result<Self, DeserializationError> {
CapsuleFrag::from_bytes(data).map(|cfrag| Self { cfrag })
}

/// Clears the verification status from the capsule frag.
/// Useful for the cases where it needs to be put in the protocol structure
/// containing [`CapsuleFrag`] types (since those are the ones
/// that can be serialized/deserialized freely).
pub fn to_unverified(&self) -> CapsuleFrag {
self.cfrag.clone()
}
}

#[cfg(test)]
Expand Down
20 changes: 18 additions & 2 deletions umbral-pre/src/key_frag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,22 @@ impl KeyFrag {
kfrag: self.clone(),
})
}

/// Explicitly skips verification.
/// Useful in cases when the verifying keys are impossible to obtain independently.
///
/// **Warning:** make sure you considered the implications of not enforcing verification.
pub fn skip_verification(self) -> VerifiedKeyFrag {
VerifiedKeyFrag { kfrag: self }
}
}

/// Verified key fragment, good for reencryption.
/// Can be serialized, but cannot be deserialized directly.
/// It can only be obtained from [`KeyFrag::verify`].
/// It can only be obtained from [`KeyFrag::verify`] or [`KeyFrag::skip_verification`].
#[derive(Debug, Clone, PartialEq)]
pub struct VerifiedKeyFrag {
pub(crate) kfrag: KeyFrag,
kfrag: KeyFrag,
}

impl RepresentableAsArray for VerifiedKeyFrag {
Expand Down Expand Up @@ -415,6 +423,14 @@ impl VerifiedKeyFrag {
pub fn from_verified_bytes(data: impl AsRef<[u8]>) -> Result<Self, DeserializationError> {
KeyFrag::from_bytes(data).map(|kfrag| Self { kfrag })
}

/// Clears the verification status from the keyfrag.
/// Useful for the cases where it needs to be put in the protocol structure
/// containing [`KeyFrag`] types (since those are the ones
/// that can be serialized/deserialized freely).
pub fn to_unverified(&self) -> KeyFrag {
self.kfrag.clone()
}
}

pub(crate) struct KeyFragBase {
Expand Down
6 changes: 3 additions & 3 deletions umbral-pre/src/pre.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ pub fn reencrypt_with_rng(
capsule: &Capsule,
verified_kfrag: &VerifiedKeyFrag,
) -> VerifiedCapsuleFrag {
VerifiedCapsuleFrag::reencrypted(rng, capsule, &verified_kfrag.kfrag)
let kfrag = verified_kfrag.to_unverified();
VerifiedCapsuleFrag::reencrypted(rng, capsule, &kfrag)
}

/// A synonym for [`reencrypt_with_rng`] with the default RNG.
Expand Down Expand Up @@ -179,8 +180,7 @@ pub fn decrypt_reencrypted(
) -> Result<Box<[u8]>, ReencryptionError> {
let cfrags: Vec<_> = verified_cfrags
.iter()
.cloned()
.map(|vcfrag| vcfrag.cfrag)
.map(|vcfrag| vcfrag.to_unverified())
.collect();
let key_seed = capsule
.open_reencrypted(receiving_sk, delegating_pk, &cfrags)
Expand Down

0 comments on commit 3cf47a1

Please sign in to comment.