Cleanups and prepping for encryption

This cleans up some types, moves some typing to loading and saving keys,
uses clearer object names, and passes a crypto system into chatter.

This lays the groundwork for adding encryption.
This commit is contained in:
Teknique 2023-08-02 21:12:26 -07:00
parent 9a65f1b1bf
commit 04354d79c9
2 changed files with 44 additions and 31 deletions

View File

@ -19,17 +19,20 @@ async def noop_callback(*args, **kwargs):
return return
async def chatter(rc: veilid.api.RoutingContext, key: str, send_channel: int, recv_channel: int): async def chatter(
router: veilid.api.RoutingContext,
crypto_system: veilid.CryptoSystem,
key: veilid.TypedKey,
send_subkey: veilid.ValueSubkey,
recv_subkey: veilid.ValueSubkey,
):
"""Read input, write it to the DHT, and print the response from the DHT.""" """Read input, write it to the DHT, and print the response from the DHT."""
last_seq = -1 last_seq = -1
send_subkey = veilid.types.ValueSubkey(send_channel)
recv_subkey = veilid.types.ValueSubkey(recv_channel)
# Prime the pumps. Especially when starting the conversation, this # Prime the pumps. Especially when starting the conversation, this
# causes the DHT key to propagate to the network. # causes the DHT key to propagate to the network.
await rc.set_dht_value(key, send_subkey, b"Hello from the world!") await router.set_dht_value(key, send_subkey, b"Hello from the world!")
while True: while True:
try: try:
@ -37,11 +40,11 @@ async def chatter(rc: veilid.api.RoutingContext, key: str, send_channel: int, re
except EOFError: except EOFError:
# Cat got your tongue? Hang up. # Cat got your tongue? Hang up.
print("Closing the chat.") print("Closing the chat.")
await rc.set_dht_value(key, send_subkey, QUIT) await router.set_dht_value(key, send_subkey, QUIT)
return return
# Write the input message to the DHT key. # Write the input message to the DHT key.
await rc.set_dht_value(key, send_subkey, msg.encode()) await router.set_dht_value(key, send_subkey, msg.encode())
# In the real world, don't do this. People may tease you for it. # In the real world, don't do this. People may tease you for it.
# This is meant to be easy to understand for demonstration # This is meant to be easy to understand for demonstration
@ -49,7 +52,7 @@ async def chatter(rc: veilid.api.RoutingContext, key: str, send_channel: int, re
# callback function to handle events asynchronously. # callback function to handle events asynchronously.
while True: while True:
# Try to get an updated version of the receiving subkey. # Try to get an updated version of the receiving subkey.
resp = await rc.get_dht_value(key, recv_subkey, True) resp = await router.get_dht_value(key, recv_subkey, True)
if resp is None: if resp is None:
continue continue
@ -72,30 +75,32 @@ async def start(host: str, port: int, name: str):
conn = await veilid.json_api_connect(host, port, noop_callback) conn = await veilid.json_api_connect(host, port, noop_callback)
keys = config.read_keys() keys = config.read_keys()
my_key = veilid.KeyPair(keys["self"]) my_keypair = keys["self"]
their_key = keys["peers"][name]
members = [ members = [
veilid.types.DHTSchemaSMPLMember(my_key.key(), 1), veilid.DHTSchemaSMPLMember(my_keypair.key(), 1),
veilid.types.DHTSchemaSMPLMember(keys["peers"][name], 1), veilid.DHTSchemaSMPLMember(their_key, 1),
] ]
router = await(await conn.new_routing_context()).with_privacy() router = await (await conn.new_routing_context()).with_privacy()
async with router: crypto_system = await conn.get_crypto_system(veilid.CryptoKind.CRYPTO_KIND_VLD0)
rec = await router.create_dht_record(veilid.DHTSchema.smpl(0, members)) async with router, crypto_system:
print(f"New chat key: {rec.key}") record = await router.create_dht_record(veilid.DHTSchema.smpl(0, members))
print(f"New chat key: {record.key}")
print("Give that to your friend!") print("Give that to your friend!")
# Close this key first. We'll reopen it for writing with our saved key. # Close this key first. We'll reopen it for writing with our saved key.
await router.close_dht_record(rec.key) await router.close_dht_record(record.key)
await router.open_dht_record(rec.key, veilid.KeyPair(keys["self"])) await router.open_dht_record(record.key, my_keypair)
try: try:
# Write to the 1st subkey and read from the 2nd. # Write to the 1st subkey and read from the 2nd.
await chatter(router, rec.key, 0, 1) await chatter(router, crypto_system, record.key, 0, 1)
finally: finally:
await router.close_dht_record(rec.key) await router.close_dht_record(record.key)
await router.delete_dht_record(rec.key) await router.delete_dht_record(record.key)
async def respond(host: str, port: int, key: str): async def respond(host: str, port: int, key: str):
@ -104,14 +109,15 @@ async def respond(host: str, port: int, key: str):
conn = await veilid.json_api_connect(host, port, noop_callback) conn = await veilid.json_api_connect(host, port, noop_callback)
keys = config.read_keys() keys = config.read_keys()
my_key = veilid.KeyPair(keys["self"]) my_keypair = keys["self"]
router = await(await conn.new_routing_context()).with_privacy() router = await (await conn.new_routing_context()).with_privacy()
async with router: crypto_system = await conn.get_crypto_system(veilid.CryptoKind.CRYPTO_KIND_VLD0)
await router.open_dht_record(key, my_key) async with router, crypto_system:
await router.open_dht_record(key, my_keypair)
# As the responder, we're writing to the 2nd subkey and reading from the 1st. # As the responder, we're writing to the 2nd subkey and reading from the 1st.
await chatter(router, key, 1, 0) await chatter(router, crypto_system, key, 1, 0)
async def keygen(host: str, port: int): async def keygen(host: str, port: int):
@ -121,17 +127,17 @@ async def keygen(host: str, port: int):
crypto_system = await conn.get_crypto_system(veilid.CryptoKind.CRYPTO_KIND_VLD0) crypto_system = await conn.get_crypto_system(veilid.CryptoKind.CRYPTO_KIND_VLD0)
async with crypto_system: async with crypto_system:
my_key = await crypto_system.generate_key_pair() my_keypair = await crypto_system.generate_key_pair()
keys = config.read_keys() keys = config.read_keys()
if keys["self"]: if keys["self"]:
print("You already have a keypair.") print("You already have a keypair.")
sys.exit(1) sys.exit(1)
keys["self"] = my_key keys["self"] = my_keypair
config.write_keys(keys) config.write_keys(keys)
print(f"Your new public key is {my_key.key()}. Share it with your friends!") print(f"Your new public key is {my_keypair.key()}. Share it with your friends!")
async def add_friend(host: str, port: int, name: str, pubkey: str): async def add_friend(host: str, port: int, name: str, pubkey: str):
@ -147,7 +153,7 @@ async def clean(host: str, port: int, key: str):
conn = await veilid.json_api_connect(host, port, noop_callback) conn = await veilid.json_api_connect(host, port, noop_callback)
router = await(await conn.new_routing_context()).with_privacy() router = await (await conn.new_routing_context()).with_privacy()
async with router: async with router:
await router.close_dht_record(key) await router.close_dht_record(key)
await router.delete_dht_record(key) await router.delete_dht_record(key)

View File

@ -3,6 +3,8 @@
import json import json
from pathlib import Path from pathlib import Path
import veilid
KEYFILE = Path(".demokeys") KEYFILE = Path(".demokeys")
@ -10,14 +12,19 @@ def read_keys() -> dict:
"""Load the stored keys from disk.""" """Load the stored keys from disk."""
try: try:
keydata = KEYFILE.read_text() raw = KEYFILE.read_text()
except FileNotFoundError: except FileNotFoundError:
return { return {
"self": None, "self": None,
"peers": {}, "peers": {},
} }
return json.loads(keydata) keys = json.loads(raw)
if keys["self"] is not None:
keys["self"] = veilid.KeyPair(keys["self"])
for name, pubkey in keys["peers"].items():
keys["peers"][name] = veilid.PublicKey(pubkey)
return keys
def write_keys(keydata: dict): def write_keys(keydata: dict):