umbral-pre is the Rust implementation of the Umbral
threshold proxy re-encryption scheme.
umbral-pre, Alice (the data owner) can delegate decryption rights to Bob
for any ciphertext intended to her, through a re-encryption process
performed by a set of semi-trusted proxies or Ursulas.
When a threshold of these proxies participate by performing re-encryption,
Bob is able to combine these independent re-encryptions and decrypt the original message
using his private key.
default-rng- adds methods that use the system RNG (default).
serde-based serialization and deserialization.
bindings-python- adds a
bindings_pythonsubmodule allowing dependent crates to use and re-export some of the Python-wrapped Umbral types.
bindings-wasm- adds a
bindings_wasmsubmodule allowing dependent crates to use and re-export some of the WASM-wrapped Umbral types.
use umbral_pre::*; // As in any public-key cryptosystem, users need a pair of public and private keys. // Additionally, users that delegate access to their data (like Alice, in this example) // need a signing keypair. // Key Generation (on Alice's side) let alice_sk = SecretKey::random(); let alice_pk = alice_sk.public_key(); let signer = Signer::new(SecretKey::random()); let verifying_pk = signer.verifying_key(); // Key Generation (on Bob's side) let bob_sk = SecretKey::random(); let bob_pk = bob_sk.public_key(); // Now let's encrypt data with Alice's public key. // Invocation of `encrypt()` returns both the ciphertext and a capsule. // Note that anyone with Alice's public key can perform this operation. let plaintext = b"peace at dawn"; let (capsule, ciphertext) = encrypt(&alice_pk, plaintext).unwrap(); // Since data was encrypted with Alice's public key, Alice can open the capsule // and decrypt the ciphertext with her private key. let plaintext_alice = decrypt_original(&alice_sk, &capsule, &ciphertext).unwrap(); assert_eq!(&plaintext_alice as &[u8], plaintext); // When Alice wants to grant Bob access to open her encrypted messages, // she creates re-encryption key fragments, or "kfrags", which are then // sent to `shares` proxies or Ursulas. let shares = 3; // how many fragments to create let threshold = 2; // how many should be enough to decrypt let verified_kfrags = generate_kfrags(&alice_sk, &bob_pk, &signer, threshold, shares, true, true); // Bob asks several Ursulas to re-encrypt the capsule so he can open it. // Each Ursula performs re-encryption on the capsule using the kfrag provided by Alice, // obtaining this way a "capsule fragment", or cfrag. // Simulate network transfer let kfrag0 = KeyFrag::from_array(&verified_kfrags.to_array()).unwrap(); let kfrag1 = KeyFrag::from_array(&verified_kfrags.to_array()).unwrap(); // Bob collects the resulting cfrags from several Ursulas. // Bob must gather at least `threshold` cfrags in order to open the capsule. // Ursulas must check that the received kfrags are valid // and perform the reencryption // Ursula 0 let verified_kfrag0 = kfrag0.verify(&verifying_pk, Some(&alice_pk), Some(&bob_pk)).unwrap(); let verified_cfrag0 = reencrypt(&capsule, verified_kfrag0); // Ursula 1 let verified_kfrag1 = kfrag1.verify(&verifying_pk, Some(&alice_pk), Some(&bob_pk)).unwrap(); let verified_cfrag1 = reencrypt(&capsule, verified_kfrag1); // ... // Simulate network transfer let cfrag0 = CapsuleFrag::from_array(&verified_cfrag0.to_array()).unwrap(); let cfrag1 = CapsuleFrag::from_array(&verified_cfrag1.to_array()).unwrap(); // Finally, Bob opens the capsule by using at least `threshold` cfrags, // and then decrypts the re-encrypted ciphertext. // Bob must check that cfrags are valid let verified_cfrag0 = cfrag0 .verify(&capsule, &verifying_pk, &alice_pk, &bob_pk) .unwrap(); let verified_cfrag1 = cfrag1 .verify(&capsule, &verifying_pk, &alice_pk, &bob_pk) .unwrap(); let plaintext_bob = decrypt_reencrypted( &bob_sk, &alice_pk, &capsule, [verified_cfrag0, verified_cfrag1], &ciphertext).unwrap(); assert_eq!(&plaintext_bob as &[u8], plaintext);
Encapsulated symmetric key used to encrypt the plaintext.
Errors that can happen during deserializing an object from a bytestring of correct length.
A public key.
A container for secret data. Makes the usage of secret data explicit and easy to track, prevents the secret data from being put on stack, and zeroizes the contents on drop.
A secret key.
This class handles keyring material for Umbral, by allowing deterministic
SecretKey objects based on labels.
ECDSA signature object.
An object used to sign messages. For security reasons cannot be serialized.
The provided bytestring is of an incorrect size.
Errors that can happend during symmetric decryption.
Errors that can happen during object deserialization.
Errors that can happen during symmetric encryption.
Errors that can happen when opening a
Capsule using reencrypted
Errors that can happen when decrypting a reencrypted ciphertext.
This is a helper trait for
SecretBox, asserting that the type implementing it
can either be zeroized
(in which case
is implemented accordingly),
or is zeroized on drop
(in which case
In other words, with this trait we are sure that one way or the other,
on drop of
SecretBox the contents are zeroized.
A trait denoting that the object can be deserialized from an array of bytes with size known at compile time.
A reflection trait providing access to the type’s name.
A trait denoting that the object can be represented as an array of bytes with size known at compile time.
A trait denoting that the object can be serialized to an array of bytes with size known at compile time.
A trait denoting that the object can be serialized to an array of bytes containing secret data.
Attempts to decrypt the ciphertext using the receiver’s secret key.
Decrypts the ciphertext using previously reencrypted capsule fragments.
Encrypts the given plaintext message using a DEM scheme,
and encapsulates the key for later reencryption.
Returns the KEM
Capsule and the ciphertext.
shares fragments of
which will be possible to reencrypt to allow the creator of
decrypt the ciphertext encrypted with