Alternate finnegans wake demo for Lynx testnet.

pull/2560/head
Kieran Prasch 2021-02-09 00:57:27 -08:00
parent c302f9c2cd
commit 00c4f3c530
1 changed files with 191 additions and 0 deletions

View File

@ -0,0 +1,191 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import datetime
import maya
import os
from umbral.keys import UmbralPublicKey
from web3.main import Web3
from nucypher.blockchain.eth.signers.base import Signer
from nucypher.characters.lawful import Alice, Bob, Ursula
from nucypher.characters.lawful import Enrico as Enrico
from nucypher.crypto.powers import SigningPower, DecryptingPower
from nucypher.utilities.logging import GlobalLoggerSettings
# Twisted Logger
GlobalLoggerSettings.set_log_level(log_level_name='debug')
GlobalLoggerSettings.start_console_logging()
# Execute the download script (download_finnegans_wake.sh) to retrieve the book
BOOK_PATH = os.path.join('.', 'finnegans-wake.txt')
# Change this value to to perform more or less total re-encryptions
# in order to avoid processing the entire book's text. (it's long)
NUMBER_OF_LINES_TO_REENCRYPT = 25
# Seednode
SEEDNODE_URI = "https://lynx.nucypher.network:9151"
SEEDNODE = Ursula.from_seed_and_stake_info(SEEDNODE_URI)
######################
# Boring setup stuff #
######################
# Configuration
DOMAIN = 'lynx' # testnet
# Replace with ethereum RPC endpoint
ETH_PROVIDER = ''
PROVIDER_URI = os.environ.get('NUCYPHER_PROVIDER_URI', ETH_PROVIDER)
# Replace with signer URI
WALLET_FILEPATH = ''
ETH_WALLET = f'keystore://{WALLET_FILEPATH}'
SIGNER_URI = os.environ.get('NUCYPHER_SIGNER_URI', ETH_WALLET)
# Replace with alice's ethereum address
ETH_ADDRESS = ''
ALICE_ETH_ADDRESS = os.environ.get('ALICE_ETH_ADDRESS', ETH_ADDRESS)
#####################
# Bob the BUIDLer ##
#####################
# First there was Bob.
BOB = Bob(
known_nodes=[SEEDNODE],
domain=DOMAIN,
provider_uri=PROVIDER_URI
)
# Bob gives his public keys to alice.
verifying_key = BOB.public_keys(SigningPower)
encrypting_key = BOB.public_keys(DecryptingPower)
######################################
# Alice, the Authority of the Policy #
######################################
# Alice ethereum wallet
wallet = Signer.from_signer_uri(SIGNER_URI)
password = input(f'Enter password to unlock {ALICE_ETH_ADDRESS}: ')
wallet.unlock_account(account=ALICE_ETH_ADDRESS, password=password)
ALICE = Alice(
# Connection details
domain=DOMAIN,
known_nodes=[SEEDNODE],
provider_uri=PROVIDER_URI,
# Wallet details
checksum_address=ALICE_ETH_ADDRESS,
signer=wallet,
client_password=password
)
# Here are the Policy details.
policy_end_datetime = maya.now() + datetime.timedelta(days=5)
m, n = 2, 3
label = b"secret/files/and/stuff"
# Alice can get the public key even before creating the policy.
# From this moment on, any Data Source that knows the public key
# can encrypt data originally intended for Alice, but that can be shared with
# any Bob that Alice grants access.
policy_pubkey = ALICE.get_policy_encrypting_key_from_label(label)
# Alice already knows Bob's public keys from a side-channel.
bob = Bob.from_public_keys(encrypting_key=encrypting_key, verifying_key=verifying_key)
# Alice grants access to bob.
policy = ALICE.grant(
bob=bob,
label=label,
m=m,
n=n,
rate=Web3.toWei(50, 'gwei'),
expiration=policy_end_datetime
)
# Alice puts her public key somewhere for Bob to find later...
alices_pubkey_bytes_saved_for_posterity = bytes(ALICE.stamp)
# ...and then disappears from the internet.
ALICE.disenchant()
del ALICE
del bob
#####################
# some time passes. #
# ... #
# #
# ... #
# And now for Bob. #
#####################
BOB.join_policy(label, alices_pubkey_bytes_saved_for_posterity)
# Now that Bob has joined the Policy, let's show how Enrico the Encryptor
# can share data with the members of this Policy and then how Bob retrieves it.
# In order to avoid re-encrypting the entire book in this demo, we only read some lines.
with open(BOOK_PATH, 'rb') as file:
finnegans_wake = file.readlines()[:NUMBER_OF_LINES_TO_REENCRYPT]
print()
print("**************James Joyce's Finnegan's Wake**************")
print()
print("---------------------------------------------------------")
for counter, plaintext in enumerate(finnegans_wake):
#########################
# Enrico, the Encryptor #
#########################
enrico = Enrico(policy_encrypting_key=policy_pubkey)
# In this case, the plaintext is a
# single passage from James Joyce's Finnegan's Wake.
# The matter of whether encryption makes the passage more or less readable
# is left to the reader to determine.
single_passage_ciphertext, _signature = enrico.encrypt_message(plaintext)
data_source_public_key = bytes(enrico.stamp)
del enrico
###############
# Back to Bob #
###############
enrico_as_understood_by_bob = Enrico.from_public_keys(
verifying_key=data_source_public_key,
policy_encrypting_key=policy_pubkey
)
# Now Bob can retrieve the original message.
alice_pubkey_restored_from_ancient_scroll = UmbralPublicKey.from_bytes(alices_pubkey_bytes_saved_for_posterity)
delivered_cleartexts = BOB.retrieve(single_passage_ciphertext,
enrico=enrico_as_understood_by_bob,
alice_verifying_key=alice_pubkey_restored_from_ancient_scroll,
label=label)
# We show that indeed this is the passage originally encrypted by Enrico.
assert plaintext == delivered_cleartexts[0]
print("Retrieved: {}".format(delivered_cleartexts[0]))
BOB.disenchant()