Skip to content

Commit

Permalink
Enforce verification of kfrags and cfrags
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Apr 24, 2021
1 parent bb640b4 commit 0b81a46
Show file tree
Hide file tree
Showing 13 changed files with 530 additions and 225 deletions.
18 changes: 13 additions & 5 deletions umbral-pre-python/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,26 +117,26 @@ API reference
Decrypts ``ciphertext`` with the key used to encrypt it.

.. py:function:: generate_kfrags(delegating_sk: SecretKey, receiving_pk: PublicKey, signer: Signer, threshold: int, num_kfrags: int, sign_delegating_key: bool, sign_receiving_key: bool) -> List[KeyFrag]
.. py:function:: generate_kfrags(delegating_sk: SecretKey, receiving_pk: PublicKey, signer: Signer, threshold: int, num_kfrags: int, sign_delegating_key: bool, sign_receiving_key: bool) -> List[VerifiedKeyFrag]
Generates ``num_kfrags`` key fragments that can be used to reencrypt the capsule for the holder of the secret key corresponding to ``receiving_pk``. ``threshold`` fragments will be enough for decryption.

If ``sign_delegating_key`` or ``sign_receiving_key`` are ``True``, include these keys in the signature allowing proxies to verify the fragments were created with a given key or for a given key, respectively.

.. py:function:: reencrypt(capsule: Capsule, kfrag: KeyFrag, metadata: Optional[bytes]) -> CapsuleFrag
.. py:function:: reencrypt(capsule: Capsule, kfrag: VerifiedKeyFrag, metadata: Optional[bytes]) -> VerifiedCapsuleFrag
Reencrypts a capsule using a key fragment.
May include optional ``metadata`` to sign.

.. py:function:: decrypt_reencrypted(decrypting_sk: SecretKey, delegating_pk: PublicKey, capsule: Capsule, cfrags: Sequence[CapsuleFrag], ciphertext: bytes) -> Optional[bytes]
.. py:function:: decrypt_reencrypted(decrypting_sk: SecretKey, delegating_pk: PublicKey, capsule: Capsule, cfrags: Sequence[VerifiedCapsuleFrag], ciphertext: bytes) -> Optional[bytes]
Attempts to decrypt the plaintext using the original capsule and reencrypted capsule fragments (at least ``threshold`` of them, see :py:func:`generate_kfrags`).

.. py:class:: KeyFrag
A fragment of a public key used by proxies during reencryption.

.. py:method:: verify(verifying_pk: PublicKey, delegating_pk: Optional[PublicKey], receiving_pk: Optional[PublicKey]) -> bool:
.. py:method:: verify(verifying_pk: PublicKey, delegating_pk: Optional[PublicKey], receiving_pk: Optional[PublicKey]) -> VerifiedKeyFrag:
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`).

Expand All @@ -152,11 +152,15 @@ API reference
Returns a hash of self.

.. py:class:: VerifiedKeyFrag
A verified key fragment, good for reencryption.

.. py:class:: CapsuleFrag
A reencrypted fragment of an encapsulated symmetric key.

.. py:method:: verify(capsule: Capsule, verifying_pk: PublicKey, delegating_pk: PublicKey, receiving_pk: PublicKey, metadata: Optional[bytes]) -> bool
.. py:method:: verify(capsule: Capsule, verifying_pk: PublicKey, delegating_pk: PublicKey, receiving_pk: PublicKey, metadata: Optional[bytes]) -> VerifiedCapsuleFrag
Verifies the integrity of the fragment.

Expand All @@ -172,6 +176,10 @@ API reference
Returns a hash of self.

.. py:class:: VerifiedCapsuleFrag
A verified capsule fragment, good for decryption.


Indices and tables
==================
Expand Down
28 changes: 18 additions & 10 deletions umbral-pre-python/example/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
m = 2 # how many should be enough to decrypt

# Split Re-Encryption Key Generation (aka Delegation)
kfrags = umbral_pre.generate_kfrags(
verified_kfrags = umbral_pre.generate_kfrags(
alice_sk, bob_pk, signer, m, n,
True, # add the delegating key (alice_pk) to the signature
True, # add the receiving key (bob_pk) to the signature
Expand All @@ -57,29 +57,37 @@
# Bob must gather at least `m` cfrags
# in order to open the capsule.

# Ursulas can optionally check that the received kfrags
# Simulate network transfer
kfrag0 = KeyFrag.from_bytes(bytes(verified_kfrags[0]))
kfrag1 = KeyFrag.from_bytes(bytes(verified_kfrags[1]))

# Ursulas must check that the received kfrags
# are valid and perform the reencryption.

# Ursula 0
metadata0 = b"metadata0"
assert kfrags[0].verify(verifying_pk, alice_pk, bob_pk)
cfrag0 = umbral_pre.reencrypt(capsule, kfrags[0], metadata0)
verified_kfrag0 = kfrag0.verify(verifying_pk, alice_pk, bob_pk)
verified_cfrag0 = umbral_pre.reencrypt(capsule, kfrags[0], metadata0)

# Ursula 1
metadata1 = b"metadata1"
assert kfrags[1].verify(verifying_pk, alice_pk, bob_pk)
cfrag1 = umbral_pre.reencrypt(capsule, kfrags[1], metadata1)
verified_kfrag1 = kfrag1.verify(verifying_pk, alice_pk, bob_pk)
verified_cfrag1 = umbral_pre.reencrypt(capsule, kfrags[1], metadata1)

# ...

# Simulate network transfer
cfrag0 = CapsuleFrag.from_bytes(bytes(verified_cfrag0))
cfrag1 = CapsuleFrag.from_bytes(bytes(verified_cfrag1))

# Finally, Bob opens the capsule by using at least `m` cfrags,
# and then decrypts the re-encrypted ciphertext.

# Bob can optionally check that cfrags are valid
assert cfrag0.verify(capsule, verifying_pk, alice_pk, bob_pk, metadata0)
assert cfrag1.verify(capsule, verifying_pk, alice_pk, bob_pk, metadata1)
# Bob must check that cfrags are valid
verified_cfrag0 = cfrag0.verify(capsule, verifying_pk, alice_pk, bob_pk, metadata0)
verified_cfrag1 = cfrag1.verify(capsule, verifying_pk, alice_pk, bob_pk, metadata1)

# Decryption by Bob
plaintext_bob = umbral_pre.decrypt_reencrypted(
bob_sk, alice_pk, capsule, [cfrag0, cfrag1], ciphertext)
bob_sk, alice_pk, capsule, [verified_cfrag0, verified_cfrag1], ciphertext)
assert plaintext_bob == plaintext
Loading

0 comments on commit 0b81a46

Please sign in to comment.