pyUmbral/docs/examples/umbral_simple_api.py

147 lines
4.6 KiB
Python
Raw Normal View History

2018-07-25 17:55:12 +00:00
"""
Copyright (C) 2018 NuCypher
This file is part of pyUmbral.
pyUmbral is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pyUmbral is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pyUmbral. If not, see <https://www.gnu.org/licenses/>.
"""
2018-02-16 20:36:07 +00:00
#1
# Sets a default curve (secp256k1)
import random
2018-07-26 13:18:09 +00:00
from umbral import pre, keys, config, signing
2018-02-16 20:36:07 +00:00
config.set_default_curve()
#2
2018-07-26 13:18:09 +00:00
# Generate an Umbral key pair
# ---------------------------
# First, Let's generate two asymmetric key pairs for Alice:
# A delegating key pair and a Signing key pair.
2018-02-16 20:36:07 +00:00
2018-07-26 13:18:09 +00:00
alices_private_key = keys.UmbralPrivateKey.gen_key()
alices_public_key = alices_private_key.get_pubkey()
alices_signing_key = keys.UmbralPrivateKey.gen_key()
alices_verifying_key = alices_signing_key.get_pubkey()
alices_signer = signing.Signer(private_key=alices_signing_key)
2018-02-16 20:36:07 +00:00
#3
# Encrypt some data for Alice
2018-07-26 13:18:09 +00:00
# ---------------------------
# Now let's encrypt data with Alice's public key.
# Invocation of `pre.encrypt` returns both the `ciphertext`,
2018-07-29 06:22:25 +00:00
# and a `capsule`. Anyone with Alice's public key can perform
2018-07-26 13:18:09 +00:00
# this operation.
plaintext = b'Proxy Re-encryption is cool!'
ciphertext, capsule = pre.encrypt(alices_public_key, plaintext)
print(ciphertext)
2018-02-16 20:36:07 +00:00
#4
# Decrypt data for Alice
2018-07-26 13:18:09 +00:00
# ----------------------
# Since data was encrypted with Alice's public key,
# Alice can open the capsule and decrypt the ciphertext with her private key.
cleartext = pre.decrypt(ciphertext=ciphertext,
capsule=capsule,
decrypting_key=alices_private_key)
print(cleartext)
2018-02-16 20:36:07 +00:00
#5
2018-07-26 13:18:09 +00:00
# Bob Exists
# -----------
bobs_private_key = keys.UmbralPrivateKey.gen_key()
bobs_public_key = bobs_private_key.get_pubkey()
2018-02-16 20:36:07 +00:00
#6
2018-07-26 13:18:09 +00:00
# Bob receives a capsule through a side channel (s3, ipfs, Google cloud, etc)
bob_capsule = capsule
#7
2018-02-16 20:36:07 +00:00
# Attempt Bob's decryption (fail)
try:
2018-07-26 13:18:09 +00:00
fail_decrypted_data = pre.decrypt(ciphertext=ciphertext,
capsule=bob_capsule,
decrypting_key=bobs_private_key)
2018-02-16 20:36:07 +00:00
except:
2018-07-26 13:18:09 +00:00
print("Decryption failed! Bob doesn't has access granted yet.")
2018-02-16 20:36:07 +00:00
#8
2018-07-26 13:18:09 +00:00
# Alice grants access to Bob by generating kfrags
# -----------------------------------------------
# When Alice wants to grant Bob access to open her encrypted messages,
# she creates *threshold split re-encryption keys*, or *"kfrags"*,
# which are next sent to N proxies or *Ursulas*.
# She uses her private key, and Bob's public key, and she sets a minimum
# threshold of 10, for 20 total shares
kfrags = pre.split_rekey(delegating_privkey=alices_private_key,
signer=alices_signer,
receiving_pubkey=bobs_public_key,
threshold=10,
N=20)
2018-02-16 20:36:07 +00:00
#9
2018-07-26 13:18:09 +00:00
# Ursulas perform re-encryption
# ------------------------------
# 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`
2018-07-29 06:22:25 +00:00
# provided by Alice, obtaining this way a "capsule fragment", or `cfrag`.
2018-07-26 13:18:09 +00:00
# Let's mock a network or transport layer by sampling `threshold` random `kfrags`,
# one for each required Ursula.
import random
kfrags = random.sample(kfrags, # All kfrags from above
10) # M - Threshold
# Bob collects the resulting `cfrags` from several Ursulas.
# Bob must gather at least `threshold` `cfrags` in order to activate the capsule.
cfrags = list() # Bob's cfrag collection
for kfrag in kfrags:
cfrag = pre.reencrypt(kfrag=kfrag, capsule=bob_capsule)
cfrags.append(cfrag) # Bob collects a cfrag
assert len(cfrags) == 10
#10
# Bob attaches cfrags to the capsule
# ----------------------------------
# Bob attaches at least `threshold` `cfrags` to the capsule;
# then it can become *activated*.
bob_capsule.set_correctness_keys(delegating=alices_public_key,
receiving=bobs_public_key,
verifying=alices_verifying_key)
for cfrag in cfrags:
bob_capsule.attach_cfrag(cfrag)
#11
# Bob activates and opens the capsule
# ------------------------------------
# Finally, Bob activates and opens the capsule,
# then decrypts the re-encrypted ciphertext.
bob_cleartext = pre.decrypt(ciphertext=ciphertext, capsule=bob_capsule, decrypting_key=bobs_private_key)
print(bob_cleartext)
assert bob_cleartext == plaintext