mirror of https://github.com/nucypher/nucypher.git
Enhancements and inclusion of some suggestions via PR #1338.
parent
3f31f3a4c7
commit
ff1358ffe5
|
@ -1,106 +1,143 @@
|
||||||
# NuCypher Quickstart
|
# NuCypher Quickstart
|
||||||
|
|
||||||
|
|
||||||
## A Note about Side-Channels
|
## A Note about Side Channels
|
||||||
|
|
||||||
The NuCypher network does not store or handle an application's data; instead - it manages access *to* application data
|
The NuCypher network does not store or handle an application's data; instead - it manages access *to* application data.
|
||||||
Management of encrypted secrets and public keys tends to be highly domain-specific. In other words, the surrounding architecture will vary greatly depending on the throughput, sensitivity and sharing cadence of the data in question, to name but a few influencing factors.
|
Management of encrypted secrets and public keys tends to be highly domain-specific - The surrounding architecture
|
||||||
In all cases however, NuCypher must be integrated with a storage and transport layer in order to function properly.
|
will vary greatly depending on the throughput, sensitivity, and sharing cadence of application secrets.
|
||||||
Along with the transport of ciphertexts, the application also needs to include
|
In all cases, NuCypher must be integrated with a storage and transport layer in order to function properly.
|
||||||
facilities for several other pieces of cryptographic material, specifically, channels
|
Along with the transport of ciphertexts, a nucypher application also needs to include channels for Alice and Bob
|
||||||
for Alice and Bob to discover each other's public keys, as well as a way to provide the policy's public key
|
to discover each other's public keys, and provide policy encrypting information to Bob and Enrico.
|
||||||
to Bob and Enrico.
|
|
||||||
|
|
||||||
##### Side Channel Data:
|
##### Side Channel Data:
|
||||||
- Secrets:
|
- Secrets:
|
||||||
- Message Kits (Ciphertext)
|
- Message Kits (Ciphertext)
|
||||||
- Labels
|
|
||||||
- Identities:
|
- Identities:
|
||||||
- Alice Verifying Key
|
- Alice Verifying Key
|
||||||
- Bob Encrypting Key
|
- Bob Encrypting Key
|
||||||
- Bob Verifying Key
|
- Bob Verifying Key
|
||||||
- Policies:
|
- Policies:
|
||||||
- Policy Encrypting Key
|
- Policy Encrypting Key
|
||||||
|
- Labels
|
||||||
|
|
||||||
|
## Running an Ethereum Node
|
||||||
|
|
||||||
## Connecting to the NuCypher Network
|
Operation of a decentralized NuCypher character [`Alice`, `Bob`, `Ursula`] requires
|
||||||
|
a connection to an Ethereum node and wallet.
|
||||||
|
|
||||||
### Running an Ethereum Node
|
To run a Goerli-connected Geth node in *fast* syncing mode:
|
||||||
|
|
||||||
Operation of NuCypher cryptological characters [`Alice`, `Bob`, `Ursula`] requires
|
|
||||||
a running Ethereum node and wallet (we recommend Geth).
|
|
||||||
|
|
||||||
To run a Goerli connected Geth node:
|
|
||||||
```bash
|
```bash
|
||||||
$ geth --goerl
|
$ geth --goerl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To run a Goerli-connected Geth node in *light* syncing mode:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ geth --goerl --syncmode light
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that using `--syncmode light` is not 100% stable but can be a life savior when using
|
||||||
|
a mobile connection (or congested hackathon wifi...).
|
||||||
|
|
||||||
### Provider URI
|
### Provider URI
|
||||||
|
|
||||||
Nucypher uses the node's IPC-File to communicate, specified by `provider_uri`.
|
Nucypher uses the node's IPC-File to communicate, specified by `provider_uri`.
|
||||||
By default in ubuntu, the path is `~/.ethereum/goerli/geth.ipc` - This path
|
By default in ubuntu, the path is `~/.ethereum/goerli/geth.ipc` - This path
|
||||||
will also be logged to the geth-running console on startup.
|
will also be logged to the geth-running console on startup.
|
||||||
|
|
||||||
|
Connect to the Geth Console to test your ethereum node's IPC:
|
||||||
|
```bash
|
||||||
|
$ geth attach ~/.ethereum/goerli/geth.ipc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Wallets
|
||||||
|
|
||||||
|
To list available accounts on your geth node:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ geth attach ~/.ethereum/goerli/geth.ipc
|
||||||
|
> eth.accounts
|
||||||
|
["0x287a817426dd1ae78ea23e9918e2273b6733a43d", "0xc080708026a3a280894365efd51bb64521c45147"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Hardware wallet addresses will also be listed here if one is attached to the system hardware.
|
||||||
|
Note that the Geth console does not return EIP-55 compliant checksum addresses, and instead will output
|
||||||
|
the *lowercase* version of the address. Since Nucypher requires EIP-55 checksum addresses, you will need
|
||||||
|
to convert your address to checksum format:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> web3.toChecksumAddress(eth.accounts[0])
|
||||||
|
"0x287A817426DD1AE78ea23e9918e2273b6733a43D"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connecting to The NuCypher Network
|
||||||
|
|
||||||
|
### Connecting Nucypher to an Ethereum Provider
|
||||||
|
|
||||||
|
```python
|
||||||
|
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||||
|
BlockchainInterfaceFactory.initialize_interface(provider_uri='~/.ethereum/goerli/geth.ipc')
|
||||||
|
```
|
||||||
|
|
||||||
### Ursula: Untrusted Re-Encryption Proxies
|
### Ursula: Untrusted Re-Encryption Proxies
|
||||||
|
|
||||||
When initializing an `Alice`, `Bob`, or `Ursula`, an initial "Stranger-`Ursula`" is needed to perform
|
When initializing an `Alice`, `Bob`, or `Ursula`, an initial "Stranger-`Ursula`" is needed to perform
|
||||||
the role of a `Teacher`, or "seednode". The `known_nodes` will inform your character of all of the nodes
|
the role of a `Teacher`, or "seednode":
|
||||||
they know about network-wide, then kick-off the automated node-discovery loop.
|
|
||||||
|
|
||||||
Stranger `Ursula`s can be created by invoking the `from_seed_and_stake_info` method, then a `list` of `known_nodes`
|
|
||||||
can be passed into any `Character`'s init:
|
|
||||||
```python
|
```python
|
||||||
from nucypher.characters.lawful import Ursula, Alice
|
from nucypher.characters.lawful import Ursula, Alice
|
||||||
|
|
||||||
ursula = Ursula.from_seed_and_stake_info(seed_uri=<URI>) # ie. https://0.0.0.0:9151
|
ursula = Ursula.from_seed_and_stake_info(seed_uri=<URI>, federated_only=False) # ie. https://0.0.0.0:9151
|
||||||
another_ursula = Ursula.from_seed_and_stake_info(seed_uri=<URI>)
|
another_ursula = Ursula.from_seed_and_stake_info(seed_uri=<URI>, federated_only=False)
|
||||||
|
```
|
||||||
|
|
||||||
alice = Alice(checksum_address='0xdeadbeef',
|
Stranger `Ursula`s can be created by invoking the `from_seed_and_stake_info` method, then a `list` of `known_nodes`
|
||||||
provider_uri=<PROVIDER URI>,
|
can be passed into any `Character`'s init. The `known_nodes` will inform your character of all of the nodes
|
||||||
known_nodes=[ursula, another_ursula])
|
they know about network-wide, then kick-off the automated node-discovery loop:
|
||||||
|
|
||||||
|
```python
|
||||||
|
alice = Alice(known_nodes=[ursula, another_ursula], ...)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Alice: Grant Access to a Secret
|
## Alice: Grant Access to a Secret
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from nucypher.characters.lawful import Alice, Bob, Ursula
|
from nucypher.characters.lawful import Alice, Bob, Ursula
|
||||||
|
from nucypher.network.middleware import RestMiddleware
|
||||||
|
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
||||||
|
|
||||||
# Application Side-Channel
|
# Application Side-Channel
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# bob_encrypting_key = <Side Channel>
|
# bob_encrypting_key = <Side Channel>
|
||||||
# bob_verifying_key = <Side Channel>
|
# bob_verifying_key = <Side Channel>
|
||||||
|
|
||||||
ursula = Ursula.from_seed_and_stake_info(seed_uri='https://0.0.0.0:9151')
|
ursula = Ursula.from_seed_and_stake_info(seed_uri='https://0.0.0.0:9151', federated_only=False)
|
||||||
alice = Alice(checksum_address='0xdeadbeef',
|
alice = Alice(known_nodes=[ursula],
|
||||||
provider_uri=<PROVIDER URI>,
|
checksum_address="0x287A817426DD1AE78ea23e9918e2273b6733a43D",
|
||||||
known_nodes=[ursula])
|
registry=InMemoryContractRegistry.from_latest_publication(),
|
||||||
|
network_middleware=RestMiddleware())
|
||||||
bob = Bob.from_public_keys(verifying_key=bob_verifying_key, encrypting_key=bob_encrypting_key)
|
bob = Bob.from_public_keys(verifying_key=bob_verifying_key, encrypting_key=bob_encrypting_key)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime
|
||||||
|
import maya
|
||||||
|
|
||||||
#
|
#
|
||||||
# Grant
|
# Grant
|
||||||
#
|
#
|
||||||
|
|
||||||
expiration = datetime.now() + timedelta(days=5) # Five days from now.
|
policy_end_datetime = maya.now() + datetime.timedelta(days=5) # Five days from now
|
||||||
policy = alice.grant(bob,
|
policy = alice.grant(bob,
|
||||||
label=b'my-secret-stuff',
|
label=b'my-secret-stuff',
|
||||||
m=2, n=3,
|
m=2, n=3,
|
||||||
expiration=expiration)
|
expiration=policy_end_datetime)
|
||||||
|
|
||||||
policy_encrypting_key = policy.public_key
|
policy_encrypting_key = policy.public_key
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that Alice can get the public key even before creating the policy.
|
|
||||||
From this moment on, any Data Source (Enrico) that knows the public key
|
|
||||||
can encrypt data originally intended for Alice, but can be shared with
|
|
||||||
any Bob that Alice grants access.
|
|
||||||
|
|
||||||
`policy_pubkey = alice.get_policy_encrypting_key_from_label(label)`
|
|
||||||
|
|
||||||
|
|
||||||
## Enrico: Encrypt a Secret
|
## Enrico: Encrypt a Secret
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -111,15 +148,23 @@ from nucypher.characters.lawful import Enrico
|
||||||
# policy_encrypting_key = <Side Channel>
|
# policy_encrypting_key = <Side Channel>
|
||||||
|
|
||||||
enrico = Enrico(policy_encrypting_key=policy_encrypting_key)
|
enrico = Enrico(policy_encrypting_key=policy_encrypting_key)
|
||||||
ciphertext = enrico.encrypt_message(message=b'Peace at dawn.')
|
ciphertext, signature = enrico.encrypt_message(message=b'Peace at dawn.')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that Alice can get the public key even before creating the policy.
|
||||||
|
From this moment on, any Data Source (Enrico) that knows the public key
|
||||||
|
can encrypt data originally intended for Alice, but can be shared with
|
||||||
|
any Bob that Alice grants access.
|
||||||
|
|
||||||
|
`policy_pubkey = alice.get_policy_encrypting_key_from_label(label)`
|
||||||
|
|
||||||
|
|
||||||
## Bob: Decrypt a Secret
|
## Bob: Decrypt a Secret
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from nucypher.characters.lawful import Alice, Bob, Enrico, Ursula
|
from nucypher.characters.lawful import Alice, Bob, Enrico, Ursula
|
||||||
|
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
||||||
|
from nucypher.network.middleware import RestMiddleware
|
||||||
|
|
||||||
# Application Side-Channel
|
# Application Side-Channel
|
||||||
# --------------------------
|
# --------------------------
|
||||||
|
@ -129,11 +174,12 @@ from nucypher.characters.lawful import Alice, Bob, Enrico, Ursula
|
||||||
# alice_verifying_key = <Side Channel>
|
# alice_verifying_key = <Side Channel>
|
||||||
|
|
||||||
# Everyone!
|
# Everyone!
|
||||||
ursula = Ursula.from_seed_and_stake_info(seed_uri='https://0.0.0.0:9151')
|
ursula = Ursula.from_seed_and_stake_info(seed_uri='https://0.0.0.0:9151', federated_only=False)
|
||||||
alice = Alice.from_public_keys(verifying_key=alice_verifying_key)
|
alice = Alice.from_public_keys(verifying_key=alice_verifying_key)
|
||||||
bob = Bob(checksum_address='0xdeadbeef',
|
bob = Bob(known_nodes=[ursula],
|
||||||
provider_uri=<PROVIDER URI>,
|
checksum_address="0xc080708026a3a280894365efd51bb64521c45147",
|
||||||
known_nodes=[ursula])
|
registry=InMemoryContractRegistry.from_latest_publication(),
|
||||||
|
network_middleware=RestMiddleware())
|
||||||
enrico = Enrico(policy_encrypting_key=policy_encrypting_key)
|
enrico = Enrico(policy_encrypting_key=policy_encrypting_key)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue