mirror of https://github.com/nucypher/nucypher.git
Implement Keystore with new models
parent
b894ca6d18
commit
893ae8d24c
|
@ -18,9 +18,9 @@ class Key(Base):
|
|||
is_signing = Column(Boolean, unique=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
def __init__(self, key_data, is_signing):
|
||||
def __init__(self, fingerprint, key_data, is_signing):
|
||||
self.fingerprint = fingerprint
|
||||
self.key_data = key_data
|
||||
self.fingerprint = self.get_fingerprint()
|
||||
self.is_signing = is_signing
|
||||
|
||||
|
||||
|
@ -57,9 +57,11 @@ class Workorder(Base):
|
|||
|
||||
id = Column(Integer, primary_key=True)
|
||||
bob_pubkey_sig_id = Column(Integer, ForeignKey('keys.id'))
|
||||
bob_signature = Column(LargeBinary, unique=True)
|
||||
hrac = Column(LargeBinary, unique=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
def __init__(self, bob_pubkey_sig_id, hrac):
|
||||
def __init__(self, bob_pubkey_sig_id, bob_signature, hrac):
|
||||
self.bob_pubkey_sig_id = bob_pubkey_sig_id
|
||||
self.bob_signature = bob_signature
|
||||
self.hrac = hrac
|
||||
|
|
|
@ -34,7 +34,7 @@ class Keypair(object):
|
|||
else:
|
||||
raise ValueError("Either pass a valid key as umbral_key or, if you want to generate keys, set generate_keys_if_needed to True.")
|
||||
|
||||
def serialize_pubkey(self, as_bytes=True) -> Union[bytes, str]:
|
||||
def serialize_pubkey(self, as_b64=False) -> bytes:
|
||||
"""
|
||||
Serializes the pubkey for storage/transport in either urlsafe base64
|
||||
or as a bytestring.
|
||||
|
@ -43,9 +43,9 @@ class Keypair(object):
|
|||
|
||||
:return: The serialized pubkey in bytes
|
||||
"""
|
||||
if as_bytes:
|
||||
return bytes(self.pubkey)
|
||||
return self.pubkey.save_key()
|
||||
if as_b64:
|
||||
return self.pubkey.save_key()
|
||||
return bytes(self.pubkey)
|
||||
|
||||
def get_fingerprint(self):
|
||||
"""
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import sha3
|
||||
|
||||
from nkms.crypto.constants import KFRAG_LENGTH
|
||||
from nkms.keystore.db.models import Key, KeyFrag
|
||||
from nkms.keystore.db.models import Key, PolicyContract, Workorder
|
||||
from nkms.crypto.utils import BytestringSplitter
|
||||
from nkms.crypto.signature import Signature
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from typing import Union
|
||||
|
||||
from umbral.fragments import KFrag
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from . import keypairs
|
||||
|
||||
|
||||
class KeyNotFound(KeyError):
|
||||
class NotFound(Exception):
|
||||
"""
|
||||
Exception class for KeyStore get_key calls for keys that don't exist.
|
||||
Exception class for KeyStore calls for objects that don't exist.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
@ -32,45 +31,23 @@ class KeyStore(object):
|
|||
"""
|
||||
self.session = sessionmaker(bind=sqlalchemy_engine)()
|
||||
|
||||
def _get_fingerprint(self, key: bytes) -> bytes:
|
||||
def add_key(self,
|
||||
keypair: Union[keypairs.EncryptingKeypair
|
||||
keypairs.SigningKeypair]) -> Key:
|
||||
"""
|
||||
Hashes the key using keccak_256 and returns the hexdigest in bytes.
|
||||
:param keypair: Keypair object to store in the keystore.
|
||||
|
||||
:param key: Key to hash
|
||||
|
||||
:return: Hexdigest fingerprint of key (keccak 256) in bytes
|
||||
:return: The newly added key object.
|
||||
"""
|
||||
return sha3.keccak_256(key).hexdigest().encode()
|
||||
fingerprint = keypair.get_fingerprint()
|
||||
key_data = keypair.serialize_pubkey(as_b64=True)
|
||||
is_signing = isinstance(keypair, keypairs.SigningKeypair)
|
||||
|
||||
def generate_encrypting_keypair(self, gen_priv=True) -> keypairs.EncryptingKeypair:
|
||||
"""
|
||||
Generates an ECIES keypair.
|
||||
new_key = Key(fingerprint, key_data, is_signing)
|
||||
|
||||
TODO: Initalize keypair with provided data.
|
||||
|
||||
:param gen_priv: Generate private key or not?
|
||||
|
||||
:return: ECIES encrypting keypair
|
||||
"""
|
||||
ecies_keypair = keypairs.EncryptingKeypair()
|
||||
if gen_priv:
|
||||
ecies_keypair.gen_privkey()
|
||||
return ecies_keypair
|
||||
|
||||
def generate_signing_keypair(self, gen_priv=True) -> keypairs.SigningKeypair:
|
||||
"""
|
||||
Generates an ECDSA keypair.
|
||||
|
||||
TODO: Initalize keypair with provided data.
|
||||
|
||||
:param gen_priv: Generate private key or not?
|
||||
|
||||
:return ECDSA signing keypair
|
||||
"""
|
||||
ecdsa_keypair = keypairs.SigningKeypair()
|
||||
if gen_priv:
|
||||
ecdsa_keypair.gen_privkey()
|
||||
return ecdsa_keypair
|
||||
self.session.add(new_key)
|
||||
self.session.commit()
|
||||
return new_key
|
||||
|
||||
def get_key(self, fingerprint: bytes) -> Union[keypairs.EncryptingKeypair,
|
||||
keypairs.SigningKeypair]:
|
||||
|
@ -80,74 +57,14 @@ class KeyStore(object):
|
|||
:param fingerprint: Fingerprint, in bytes, of key to return
|
||||
|
||||
:return: Keypair of the returned key.
|
||||
|
||||
"""
|
||||
key = self.session.query(Key).filter_by(fingerprint=fingerprint).first()
|
||||
if not key:
|
||||
raise KeyNotFound(
|
||||
raise NotFound(
|
||||
"No key with fingerprint {} found.".format(fingerprint))
|
||||
return keypairs.Keypair.deserialize_key(key.key_data)
|
||||
|
||||
def get_kfrag(self, hrac: bytes, get_sig: bool=False):
|
||||
"""
|
||||
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, kfrag = self.kfrag_splitter(kfrag.key_frag)
|
||||
|
||||
if get_sig:
|
||||
return (kfrag, sig)
|
||||
return kfrag
|
||||
|
||||
def add_key(self,
|
||||
keypair: Union[keypairs.EncryptingKeypair,
|
||||
keypairs.SigningKeypair],
|
||||
store_pub: bool = True) -> bytes:
|
||||
"""
|
||||
Gets a fingerprint of the key and adds it to the keystore.
|
||||
|
||||
:param key: Key, in bytes, to add to lmdb
|
||||
|
||||
:return: Fingerprint, in bytes, of the added key
|
||||
"""
|
||||
if store_pub:
|
||||
fingerprint = self._get_fingerprint(keypair.pubkey)
|
||||
key = keypair.serialize_pubkey()
|
||||
else:
|
||||
fingerprint = self._get_fingerprint(keypair.privkey)
|
||||
key = keypair.serialize_privkey()
|
||||
|
||||
# Create new Key object and commit to db
|
||||
self.session.add(Key(key))
|
||||
self.session.commit()
|
||||
return fingerprint
|
||||
|
||||
def add_kfrag(self, hrac: bytes, kfrag, 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 += bytes(kfrag)
|
||||
|
||||
kfrag = KeyFrag(hrac, kfrag_data)
|
||||
self.session.add(kfrag)
|
||||
self.session.commit()
|
||||
if key.is_signing:
|
||||
pubkey = UmbralPublicKey(key.key_data, as_b64=True)
|
||||
return keypairs.SigningKeypair(pubkey)
|
||||
|
||||
def del_key(self, fingerprint: bytes):
|
||||
"""
|
||||
|
@ -158,11 +75,69 @@ class KeyStore(object):
|
|||
self.session.query(Key).filter_by(fingerprint=fingerprint).delete()
|
||||
self.session.commit()
|
||||
|
||||
def del_kfrag(self, hrac: bytes):
|
||||
def add_policy_contract(self, expiration, deposit, hrac,
|
||||
alice_pubkey_sig, alice_pubkey_enc,
|
||||
bob_pubkey_sig, alice_signature) -> PolicyContract:
|
||||
"""
|
||||
Deletes a RekeyFrag from sqlite.
|
||||
Creates a PolicyContract to the Keystore.
|
||||
|
||||
:return: The newly added PolicyContract object
|
||||
"""
|
||||
# TODO: This can be optimized to one commit/write.
|
||||
alice_pubkey_sig = self.add_key(alice_pubkey_sig)
|
||||
alice_pubkey_enc = self.add_key(alice_pubkey_enc)
|
||||
bob_pubkey_sig = self.add_key(bob_pubkey_sig)
|
||||
|
||||
:param hrac: Hashed Resource Authentication Code
|
||||
new_policy_contract = PolicyContract(
|
||||
expiration, deposit, hrac, alice_pubkey_sig.id,
|
||||
alice_pubkey_enc.id, bob_pubkey_sig.id, alice_signature
|
||||
)
|
||||
|
||||
self.session.add(new_policy_contract)
|
||||
|
||||
return new_policy_contract
|
||||
|
||||
def get_policy_contract(self, hrac: bytes) -> PolicyContract:
|
||||
"""
|
||||
self.session.query(KeyFrag).filter_by(hrac=hrac).delete()
|
||||
Returns the PolicyContract by its HRAC.
|
||||
|
||||
:return: The PolicyContract object
|
||||
"""
|
||||
policy_contract = self.session.query(PolicyContract).filter_by(hrac=hrac).first()
|
||||
if not policy_contract:
|
||||
raise NotFound("No PolicyContract with {} HRAC found.".format(hrac))
|
||||
return policy_contract
|
||||
|
||||
def del_policy_contract(self, hrac: bytes):
|
||||
"""
|
||||
Deletes a PolicyContract from the Keystore.
|
||||
"""
|
||||
self.session.query(PolicyContract).filter_by(hrac=hrac).delete()
|
||||
self.session.commit()
|
||||
|
||||
def add_workorder(self, bob_pubkey_sig, bob_signature, hrac) -> Workorder:
|
||||
"""
|
||||
Adds a Workorder to the keystore.
|
||||
"""
|
||||
bob_pubkey_sig = self.add_key(bob_pubkey_sig)
|
||||
new_workorder = Workorder(bob_pubkey_sig.id, bob_signature, hrac)
|
||||
|
||||
self.session.add(new_workorder)
|
||||
self.session.commit()
|
||||
return new_workorder
|
||||
|
||||
def get_workorder(self, hrac: bytes) -> Workorder:
|
||||
"""
|
||||
Returns a list of Workorders by HRAC.
|
||||
"""
|
||||
workorders = self.session.query(Workorder).filter_by(hrac)
|
||||
if not workorders:
|
||||
raise NotFound("No Workorders with {} HRAC found.".format(hrac))
|
||||
return workorders
|
||||
|
||||
def del_workorder(self, hrac: bytes):
|
||||
"""
|
||||
Deletes a Workorder from the Keystore.
|
||||
"""
|
||||
self.session.query(Workorder).filter_by(hrac=hrac).delete()
|
||||
self.session.commit()
|
||||
|
|
Loading…
Reference in New Issue