mirror of https://github.com/nucypher/nucypher.git
commit
7d97a6c503
|
@ -1,5 +1,8 @@
|
||||||
ENC_KEYPAIR_BYTE = b'E'
|
ENC_KEYPAIR_BYTE = b'E'
|
||||||
SIG_KEYPAIR_BYTE = b'S'
|
SIG_KEYPAIR_BYTE = b'S'
|
||||||
|
|
||||||
|
REKEY_FRAG_ID_LEN = 32
|
||||||
|
REKEY_FRAG_KEY_LEN = 32
|
||||||
|
|
||||||
PUB_KEY_BYTE = b'0'
|
PUB_KEY_BYTE = b'0'
|
||||||
PRIV_KEY_BYTE = b'1'
|
PRIV_KEY_BYTE = b'1'
|
||||||
|
|
|
@ -24,3 +24,15 @@ class Key(Base):
|
||||||
:return: Fingerprint of key as a string
|
:return: Fingerprint of key as a string
|
||||||
"""
|
"""
|
||||||
return sha3.keccak_256(self.key_data[2:]).hexdigest().encode()
|
return sha3.keccak_256(self.key_data[2:]).hexdigest().encode()
|
||||||
|
|
||||||
|
|
||||||
|
class KeyFrag(Base):
|
||||||
|
__tablename__ = 'keyfrags'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
hrac = Column(LargeBinary, unique=True)
|
||||||
|
key_frag = Column(LargeBinary, unique=True)
|
||||||
|
|
||||||
|
def __init__(self, hrac, key_frag):
|
||||||
|
self.hrac = hrac
|
||||||
|
self.key_frag = key_frag
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import sha3
|
import sha3
|
||||||
from nkms.keystore import keypairs, constants
|
from nkms.keystore import keypairs, constants
|
||||||
from nkms.keystore.db.models import Key
|
from nkms.keystore.db.models import Key, KeyFrag
|
||||||
|
from nkms.crypto.utils import BytestringSplitter
|
||||||
|
from nkms.crypto.signature import Signature
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
from npre.umbral import RekeyFrag
|
||||||
|
|
||||||
|
|
||||||
class KeyNotFound(KeyError):
|
class KeyNotFound(KeyError):
|
||||||
|
@ -17,6 +20,12 @@ class KeyStore(object):
|
||||||
A storage class of cryptographic keys.
|
A storage class of cryptographic keys.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
kFrag_splitter = BytestringSplitter(
|
||||||
|
Signature,
|
||||||
|
(bytes, constants.REKEY_FRAG_ID_LEN),
|
||||||
|
(bytes, constants.REKEY_FRAG_KEY_LEN)
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, sqlalchemy_engine=None):
|
def __init__(self, sqlalchemy_engine=None):
|
||||||
"""
|
"""
|
||||||
Initalizes a KeyStore object.
|
Initalizes a KeyStore object.
|
||||||
|
@ -81,6 +90,28 @@ class KeyStore(object):
|
||||||
"No key with fingerprint {} found.".format(fingerprint))
|
"No key with fingerprint {} found.".format(fingerprint))
|
||||||
return keypairs.Keypair.deserialize_key(key.key_data)
|
return keypairs.Keypair.deserialize_key(key.key_data)
|
||||||
|
|
||||||
|
def get_kfrag(self, hrac: bytes, get_sig: bool=False) -> RekeyFrag:
|
||||||
|
"""
|
||||||
|
Returns a RekeyFrag from the KeyStore.
|
||||||
|
|
||||||
|
:param hrac: HRAC in bytes
|
||||||
|
|
||||||
|
:return: Deserialized RekeyFrag from KeyStore
|
||||||
|
"""
|
||||||
|
kfrag = self.session.query(KeyFrag).filter_by(hrac=hrac).first()
|
||||||
|
if not kfrag:
|
||||||
|
raise KeyNotFound(
|
||||||
|
"No KeyFrag with HRAC {} found."
|
||||||
|
.format(hrac)
|
||||||
|
)
|
||||||
|
# TODO: Make this use a class
|
||||||
|
sig, id, key = self.kFrag_splitter(kfrag.key_frag)
|
||||||
|
|
||||||
|
kFrag = RekeyFrag(id=id, key=key)
|
||||||
|
if get_sig:
|
||||||
|
return (kFrag, sig)
|
||||||
|
return kFrag
|
||||||
|
|
||||||
def add_key(self,
|
def add_key(self,
|
||||||
keypair: Union[keypairs.EncryptingKeypair,
|
keypair: Union[keypairs.EncryptingKeypair,
|
||||||
keypairs.SigningKeypair],
|
keypairs.SigningKeypair],
|
||||||
|
@ -89,7 +120,6 @@ class KeyStore(object):
|
||||||
Gets a fingerprint of the key and adds it to the keystore.
|
Gets a fingerprint of the key and adds it to the keystore.
|
||||||
|
|
||||||
:param key: Key, in bytes, to add to lmdb
|
:param key: Key, in bytes, to add to lmdb
|
||||||
::
|
|
||||||
|
|
||||||
:return: Fingerprint, in bytes, of the added key
|
:return: Fingerprint, in bytes, of the added key
|
||||||
"""
|
"""
|
||||||
|
@ -105,6 +135,23 @@ class KeyStore(object):
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
return fingerprint
|
return fingerprint
|
||||||
|
|
||||||
|
def add_kfrag(self, hrac: bytes, kfrag: RekeyFrag, sig: bytes=None):
|
||||||
|
"""
|
||||||
|
Adds a RekeyFrag to sqlite.
|
||||||
|
|
||||||
|
:param hrac: Hashed Resource Authenticate Code
|
||||||
|
:param kfrag: RekeyFrag instance to add to sqlite
|
||||||
|
:param sig: Signature of kfrag (if exists)
|
||||||
|
"""
|
||||||
|
kfrag_data = b''
|
||||||
|
if sig:
|
||||||
|
kfrag_data += sig
|
||||||
|
kfrag_data += kfrag.id + kfrag.key
|
||||||
|
|
||||||
|
kfrag = KeyFrag(hrac, kfrag_data)
|
||||||
|
self.session.add(kfrag)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
def del_key(self, fingerprint: bytes):
|
def del_key(self, fingerprint: bytes):
|
||||||
"""
|
"""
|
||||||
Deletes a key from the KeyStore.
|
Deletes a key from the KeyStore.
|
||||||
|
@ -113,3 +160,12 @@ class KeyStore(object):
|
||||||
"""
|
"""
|
||||||
self.session.query(Key).filter_by(fingerprint=fingerprint).delete()
|
self.session.query(Key).filter_by(fingerprint=fingerprint).delete()
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
|
|
||||||
|
def del_kfrag(self, hrac: bytes):
|
||||||
|
"""
|
||||||
|
Deletes a RekeyFrag from sqlite.
|
||||||
|
|
||||||
|
:param hrac: Hashed Resource Authentication Code
|
||||||
|
"""
|
||||||
|
self.session.query(KeyFrag).filter_by(hrac=hrac).delete()
|
||||||
|
self.session.commit()
|
||||||
|
|
|
@ -3,6 +3,8 @@ import sha3
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from nkms.keystore.db import Base
|
from nkms.keystore.db import Base
|
||||||
from nkms.keystore import keystore, keypairs
|
from nkms.keystore import keystore, keypairs
|
||||||
|
from npre.umbral import RekeyFrag
|
||||||
|
from nkms.crypto import api as API
|
||||||
|
|
||||||
|
|
||||||
class TestKeyStore(unittest.TestCase):
|
class TestKeyStore(unittest.TestCase):
|
||||||
|
@ -24,7 +26,7 @@ class TestKeyStore(unittest.TestCase):
|
||||||
self.assertEqual(bytes, type(keypair.privkey))
|
self.assertEqual(bytes, type(keypair.privkey))
|
||||||
self.assertEqual(bytes, type(keypair.pubkey))
|
self.assertEqual(bytes, type(keypair.pubkey))
|
||||||
|
|
||||||
def test_sqlite_keystore(self):
|
def test_key_sqlite_keystore(self):
|
||||||
keypair = self.ks.generate_encrypting_keypair()
|
keypair = self.ks.generate_encrypting_keypair()
|
||||||
self.assertEqual(keypairs.EncryptingKeypair, type(keypair))
|
self.assertEqual(keypairs.EncryptingKeypair, type(keypair))
|
||||||
self.assertEqual(bytes, type(keypair.privkey))
|
self.assertEqual(bytes, type(keypair.privkey))
|
||||||
|
@ -69,3 +71,23 @@ class TestKeyStore(unittest.TestCase):
|
||||||
self.ks.del_key(fingerprint_priv)
|
self.ks.del_key(fingerprint_priv)
|
||||||
with self.assertRaises(keystore.KeyNotFound):
|
with self.assertRaises(keystore.KeyNotFound):
|
||||||
key = self.ks.get_key(fingerprint_priv)
|
key = self.ks.get_key(fingerprint_priv)
|
||||||
|
|
||||||
|
def test_keyfrag_sqlite(self):
|
||||||
|
rand_sig = API.secure_random(65)
|
||||||
|
rand_id = API.secure_random(32)
|
||||||
|
rand_key = API.secure_random(32)
|
||||||
|
rand_hrac = API.secure_random(32)
|
||||||
|
|
||||||
|
kfrag = RekeyFrag(id=rand_id, key=rand_key)
|
||||||
|
self.ks.add_kfrag(rand_hrac, kfrag, sig=rand_sig)
|
||||||
|
|
||||||
|
# Check that kfrag was added
|
||||||
|
kfrag, signature = self.ks.get_kfrag(rand_hrac, get_sig=True)
|
||||||
|
self.assertEqual(rand_sig, signature)
|
||||||
|
self.assertEqual(kfrag.id, rand_id)
|
||||||
|
self.assertEqual(kfrag.key, rand_key)
|
||||||
|
|
||||||
|
# Check that kfrag gets deleted
|
||||||
|
self.ks.del_kfrag(rand_hrac)
|
||||||
|
with self.assertRaises(keystore.KeyNotFound):
|
||||||
|
key = self.ks.get_key(rand_hrac)
|
||||||
|
|
Loading…
Reference in New Issue