Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add skip_verification() and to_unverified() to kfrags/cfrags #84

Merged
merged 2 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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