Added more Policy and PolicyGroup logic. Now conforms to @tux's crypto APIs.

pull/44/head
jMyles 2017-09-19 14:30:35 -07:00
parent f6b9111b63
commit 9e314d8b81
5 changed files with 107 additions and 37 deletions

10
nkms/crypto/hash.py Normal file
View File

@ -0,0 +1,10 @@
import random
# TODO: Replace these with actual hash functions.
def signature_hash(hash_input):
return random.getrandbits(128)
def content_hash(hash_input):
return random.getrandbits(128)

12
nkms/crypto/pre/keygen.py Normal file
View File

@ -0,0 +1,12 @@
# TODO: Make this actually work.
def generate_re_encryption_keys(seckey_enc_alice,
pubkey_enc_bob,
m,
n):
kfrags = [
'sfasdfsd9',
'dfasd09fi',
'sdfksd3f9',
]
return kfrags

1
nkms/policy/constants.py Normal file
View File

@ -0,0 +1 @@
UNKNOWN_KFRAG = 550

View File

@ -1,5 +1,6 @@
from nkms.crypto.pre.keys import generate_re_encryption_keys
from nkms.crypto import nkms_hash
from nkms.crypto.hash import content_hash
from nkms.crypto.pre.keygen import generate_re_encryption_keys
from nkms.policy.constants import UNKNOWN_KFRAG
class PolicyGroup(object):
@ -7,38 +8,42 @@ class PolicyGroup(object):
The terms and conditions by which Alice shares with Bob.
"""
def __init__(self):
self.policies = []
def __init__(self, policies=None):
self.policies = policies or []
def craft(self,
keychain_alice: "KeyChain",
pubkey_enc_bob: tuple,
uri: bytes,
m: int,
n: int
):
@staticmethod
def craft(keychain_alice: "KeyChain",
pubkey_enc_bob: tuple,
uri: bytes,
m: int,
n: int
):
"""
Alice dictates a new group of policies.
"""
re_enc_keys = generate_re_encryption_keys(keychain_alice.seckey_end,
re_enc_keys = generate_re_encryption_keys(keychain_alice.enc_keypair.priv_key,
pubkey_enc_bob,
m,
n)
policies = []
for kfrag_id, key in enumerate(re_enc_keys):
policy = Policy.from_alice(
key, # Bob won't know this.
keychain_alice.pubkey_sig,
keychain_alice.sig_keypair.pub_key,
pubkey_enc_bob,
uri, # Ursula won't know this.
kfrag_id,
)
self.policies.append(policy)
policies.append(policy)
return PolicyGroup(policies)
def transmit(self, networky_stuff):
for policy in self.policies:
policy_offer = policy.craft_offer()
policy_offer = policy.craft_offer(networky_stuff)
result = networky_stuff.transmit_offer(policy.ursula, policy_offer)
if result.was_accepted():
if result.was_accepted:
policy.update_treasure_map(result)
@ -55,6 +60,11 @@ class Policy(object):
ursula = None
hashed_part = None
def __init__(self, kfrag=UNKNOWN_KFRAG, challenge_size=20):
self.kfrag = kfrag
self.challenge_size = challenge_size
self.treasure_map = []
@staticmethod
def from_alice(kfrag,
pubkey_sig_alice,
@ -62,16 +72,16 @@ class Policy(object):
uri,
kfrag_id
):
policy = Policy()
policy.generate_challenge_pack(kfrag)
policy.hash(pubkey_enc_bob, uri, kfrag_id, pubkey_sig_alice=pubkey_sig_alice)
policy = Policy(kfrag)
policy.generate_challenge_pack()
policy.hash(pubkey_sig_alice=pubkey_sig_alice, hash_input=(pubkey_enc_bob, uri, kfrag_id))
return policy
def hash(self, pubkey_sig_alice, *args):
self.hashed_part = nkms_hash(*args)
self.id = nkms_hash(pubkey_sig_alice, self.hashed_part)
def hash(self, pubkey_sig_alice, hash_input):
self.hashed_part = content_hash(hash_input)
hash_input_for_id = (pubkey_sig_alice, self.hashed_part)
self.id = content_hash(hash_input_for_id)
return self.id
def craft_offer(self, networky_stuff):
@ -79,4 +89,18 @@ class Policy(object):
Find an Ursula and craft an offer for her.
"""
self.ursula = networky_stuff.find_ursula(self.id, self.hashed_part)
return self.ursula.encrypt_for(self.kfrag, self.challenge_pack, self.treasure_map)
return self.ursula.encrypt_for((self.kfrag, self.challenge_pack, self.treasure_map))
def generate_challenge_pack(self):
if self.kfrag == UNKNOWN_KFRAG:
raise TypeError("Can't generate a challenge pack unless we know the kfrag. Are you Alice?")
# TODO: make this work instead of being random.
import random
self.challenge_pack = [(random.getrandbits(32), random.getrandbits(32)) for x in range(self.challenge_size)]
return True
def update_treasure_map(self, policy_offer_result):
# TODO: parse the result and add the node information to the treasure map.
self.treasure_map.append(policy_offer_result)

View File

@ -1,22 +1,45 @@
from nkms.crypto.keys import KeyChain
from nkms.crypto.keyring import KeyRing
from nkms.policy.models import PolicyGroup
class MockUrsula(object):
def encrypt_for(self, payload):
# TODO: Make this a testable result
import random
return random.getrandbits(32)
class MockPolicyOfferResponse(object):
was_accepted = True
class MockNetworkyStuff(object):
def transmit_offer(self, ursula, policy_offer):
return MockPolicyOfferResponse()
def find_ursula(self, id, hashed_part):
return MockUrsula()
def test_alice_has_ursulas_public_key_and_uses_it_to_encode_policy_payload():
keychain_alice = KeyChain()
keychain_bob = KeyChain()
keychain_ursula = KeyChain()
keychain_alice = KeyRing()
keychain_bob = KeyRing()
keychain_ursula = KeyRing()
# For example, a hashed path.
resource_id = b"as098duasdlkj213098asf"
kfrag_id = 74
# Alice runs this to get a policy object.
policy_group = PolicyGroup.craft(keychain_alice.pubkey_sig,
keychain_bob.pubkey_sig,
resource_id,
kfrag_id
)
policy_group.transmit()
policy_group = PolicyGroup.craft(keychain_alice,
keychain_bob.enc_keypair.pub_key,
resource_id,
m=20,
n=50
)
networky_stuff = MockNetworkyStuff()
policy_group.transmit(networky_stuff)