Merge branch 'master' of github.com:nucypher/nucypher-kms

pull/24/head
tuxxy 2017-09-05 18:54:29 -06:00
commit e9ce021283
6 changed files with 100 additions and 11 deletions

View File

@ -161,7 +161,7 @@ rather than just one rekey.
After the calculation, the rk is stored with the KMS network. It will be stored in the following
persistent mapping::
hmac(pk_b, '/'.join(path[:i])) -> (rk, policy, algorithm, sign(hash + rk + policy + algorithm, pk_o))
hmac(pk_o + pk_b, '/'.join(path[:i])) -> (rk, policy, algorithm, sign(hash + rk + policy + algorithm, pk_o))
The policy is signed by the owner's public key in order to protect from submitting by someone else.
In order to protect from submitting after being revoked, the signature can be saved on blockchain
@ -182,7 +182,7 @@ with miner's public key (on the client side)::
# Path is transformed into a series of hashes
path_split = path.split('/')
path_pieces = ['/'.join(path_split[:i + 1]) for i in len(path_split)]
path_hashes = [hmac(pk_b, piece) for piece in path_pieces]
path_hashes = [hmac(pk_o + pk_b, piece) for piece in path_pieces]
# Multiple pieces are when m-of-n split-key reencryption is used
# if not, there is only one piece

43
nkms/db.py Normal file
View File

@ -0,0 +1,43 @@
import appdirs
import lmdb
import msgpack
import os.path
CONFIG_APPNAME = 'nucypher-kms'
DB_NAME = 'rekeys-db'
class DB(object):
def __init__(self, path=None):
self.path = path or os.path.join(
appdirs.user_data_dir(CONFIG_APPNAME), DB_NAME)
db_dir = os.path.dirname(self.path)
if not os.path.exists(db_dir):
os.makedirs(db_dir)
self.db = lmdb.open(self.path)
# XXX removal when expired? Indexing by time?
def __setitem__(self, key, value):
with self.db.begin(write=True) as tx:
tx.put(key, msgpack.dumps(value))
def __getitem__(self, key):
with self.db.begin(write=False) as tx:
result = tx.get(key)
if result is None:
raise KeyError(key)
else:
return msgpack.loads(result)
def __delitem__(self, key):
with self.db.begin(write=True) as tx:
tx.pop(key)
def __contains__(self, key):
with self.db.begin(write=False) as tx:
cursor = tx.cursor()
return cursor.set_key(key)
def close(self):
self.db.close()

View File

@ -1,8 +1,6 @@
from collections import defaultdict
from nkms.db import DB
from nkms import crypto
_storage = defaultdict(dict)
class Client(object):
"""
@ -22,7 +20,9 @@ class Client(object):
"""
def __init__(self, **kw):
pass
# Dummy client stores in lmdb
# in the actual network it should be done on the server
self._storage = DB()
def store_rekeys(self, pub, k, rekeys, algorithm):
"""
@ -39,11 +39,11 @@ class Client(object):
'm-of-n reencryption not yet available')
rekeys = rekeys[0]
# Should specify and check signature also
_storage[pub][k] = {'rk': rekeys, 'algorithm': algorithm}
self._storage[k] = {b'rk': rekeys, b'algorithm': algorithm}
def remove_rekeys(self, pub, k):
# Should specify and check signature also
del _storage[pub][k]
del self._storage[k]
def reencrypt(self, pub, k, ekey):
"""
@ -51,8 +51,8 @@ class Client(object):
:param bytes k: Address of the rekey derived from the path/pubkey
:param bytes ekey: Encrypted symmetric key to reencrypt
"""
rekey = _storage[pub][k]['rk']
algorithm = _storage[pub][k]['algorithm']
rekey = self._storage[k][b'rk']
algorithm = self._storage[k][b'algorithm']
pre = crypto.pre_from_algorithm(algorithm)
return pre.reencrypt(rekey, ekey)

View File

@ -3,7 +3,7 @@ from setuptools import setup, find_packages
INSTALL_REQUIRES = [
'kademlia>=1.0',
'rpcudp>=3.0',
'ZODB>=5.0',
'lmdb',
'pynacl',
'npre',
'pysha3==1.0.2',

16
tests/conftest.py Normal file
View File

@ -0,0 +1,16 @@
import nkms.db
import shutil
import os
import appdirs
def pytest_runtest_setup(item):
# Monkey-patching for tests so that we don't overwrite the default db
nkms.db.DB_NAME = 'debug-rekeys-db'
def pytest_runtest_teardown(item, nextitem):
path = os.path.join(
appdirs.user_data_dir(nkms.db.CONFIG_APPNAME), nkms.db.DB_NAME)
if os.path.exists(path):
shutil.rmtree(path)

30
tests/test_db.py Normal file
View File

@ -0,0 +1,30 @@
from nkms.db import DB
import pytest
def test_db():
db = DB()
db[b'x'] = b'y'
assert db[b'x'] == b'y'
db.close()
db2 = DB()
assert b'x' in db2
assert db2[b'x'] == b'y'
del db2[b'x']
db2.close()
db = DB()
with pytest.raises(KeyError):
db[b'x']
assert b'x' not in db
db.close()
assert db.path == db2.path
def test_store_dict():
db = DB()
db[b'x'] = {b'a': 1, b'b': 2}
assert db[b'x'][b'a'] == 1
db.close()