From 745187c91114297bba2fbc6e6d1086793d2945a6 Mon Sep 17 00:00:00 2001 From: quadrismegistus Date: Fri, 4 Sep 2020 16:37:12 +0100 Subject: [PATCH] The Operator is actually just another Caller... --- komrade/api/persona.py | 2 +- komrade/backend/caller.py | 48 +++++++++----- komrade/backend/crypt.py | 18 ++--- komrade/backend/keymaker.py | 47 ++++++++----- komrade/backend/the_operator.py | 114 ++++++++++++-------------------- 5 files changed, 116 insertions(+), 113 deletions(-) diff --git a/komrade/api/persona.py b/komrade/api/persona.py index 95d8797..072a8bb 100644 --- a/komrade/api/persona.py +++ b/komrade/api/persona.py @@ -72,7 +72,7 @@ class Persona(Model): if __name__ == '__main__': import random idnum = random.choice(list(range(1000))) - persona = Persona('elon'+str(idnum)) + persona = Persona('Op'+str(idnum)) print('\n\n\nREGISTERING\n\n\n') persona.register(passphrase='bb') diff --git a/komrade/backend/caller.py b/komrade/backend/caller.py index 3c9f07b..f0ba59f 100644 --- a/komrade/backend/caller.py +++ b/komrade/backend/caller.py @@ -1,6 +1,6 @@ import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..'))) from komrade.backend.crypt import Crypt -from komrade.backend.the_operator import TheOperator +# from komrade.backend.the_operator import TheOperator from komrade.backend.keymaker import Keymaker from komrade import KomradeException,Logger @@ -35,11 +35,13 @@ PATH_CRYPT_DATA = os.path.join(PATH_CALLER,'.ca.db.data.encr') class Caller(Keymaker): + PATH_CRYPT_KEYS=PATH_CRYPT_KEYS + PATH_CRYPT_DATA=PATH_CRYPT_DATA ### INIT CODE def __init__(self,name): self.name=name - self.op = TheOperator() + # self.op = TheOperator() ## CRYPT BASICS @@ -48,14 +50,30 @@ class Caller(Keymaker): pass ### CREATION OF KEYS - def exists(self): - return self.op.exists(self.name) + # def exists(self): + # return self.op.exists(self.name) - - def create_keys(self,pubkey_pass = None, privkey_pass = None, adminkey_pass = None): + def get_new_keys(self,pubkey_pass = None, privkey_pass = None, adminkey_pass = None): # Get keys back from The Operator - res = self.op.create_keys(self.name) + keychain = self.op.forge_keys(self.name) self.log('create_keys() res from Operator? <-',res) + + def lock_new_keys(self,keychain): + # we're not going to store the decryptor keys directly though + passphrase=getpass.getpass('Forge the password of memory: ') + cell = SCellSeal(passphrase=passphrase) + # encrypt the decryptor keys + pubkey_decr_encr = cell.encrypt(keychain['pubkey_decr']) + privkey_decr_encr = cell.encrypt(keychain['privkey_decr']) + adminkey_decr_encr = cell.encrypt(keychain['adminkey_decr']) + + # set to crypt, like a caller + self.crypt_keys.set(self.name,pubkey_decr_encr,prefix='/pubkey_decr_encr/') + self.crypt_keys.set(keychain['pubkey_decr'],privkey_decr_encr,prefix='/privkey_decr_encr/') + self.crypt_keys.set(keychain['privkey_decr'],adminkey_decr_encr,prefix='/adminkey_decr_encr/') + + lock_keys_ + assert type(res)==tuple and len(res)==3 (pubkey_decr, privkey_decr, adminkey_decr) = res @@ -74,20 +92,20 @@ class Caller(Keymaker): # self.log('pubkey_decr_encr <--',pubkey_decr_encr) # store double encrypted keys - self.crypt_keys.set(self.name,pubkey_decr_encr,prefix='/pub_decr_encr/') - # self.crypt_keys.set(pubkey_decr,privkey_decr_encr,prefix='/priv_decr_encr/') - # self.crypt_keys.set(privkey_decr,adminkey_decr_encr,prefix='/admin_decr_encr/') + self.crypt_keys.set(self.name,pubkey_decr_encr,prefix='/pubkey_decr_encr/') + # self.crypt_keys.set(pubkey_decr,privkey_decr_encr,prefix='/privkey_decr_encr/') + # self.crypt_keys.set(privkey_decr,adminkey_decr_encr,prefix='/adminkey_decr_encr/') # store decryption keys if not passworded? - if pubkey_decr_decr_key: self.crypt_keys.set(self.name,pubkey_decr_decr_key,prefix='/pub_decr_decr_key/') - # if privkey_passkey: self.crypt_keys.set(pubkey_decr,privkey_passkey,prefix='/priv_decr_decr_key/') - # if adminkey_passkey: self.crypt_keys.set(privkey_decr,adminkey_passkey,prefix='/admin_decr_decr_key/') + if pubkey_decr_decr_key: self.crypt_keys.set(self.name,pubkey_decr_decr_key,prefix='/pubkey_decr_decr_key/') + # if privkey_passkey: self.crypt_keys.set(pubkey_decr,privkey_passkey,prefix='/privkey_decr_decr_key/') + # if adminkey_passkey: self.crypt_keys.set(privkey_decr,adminkey_passkey,prefix='/adminkey_decr_decr_key/') # done? if __name__ == '__main__': - caller = Caller('elon2') - + #caller = Caller('elon2') + Op = Caller() # caller.register() \ No newline at end of file diff --git a/komrade/backend/crypt.py b/komrade/backend/crypt.py index ac6568f..e79e818 100644 --- a/komrade/backend/crypt.py +++ b/komrade/backend/crypt.py @@ -14,7 +14,7 @@ import zlib from komrade import KomradeException,Logger -LOG_GET_SET = False +LOG_GET_SET = True @@ -61,28 +61,28 @@ class Crypt(Logger): def set(self,k,v,prefix=''): - self.log('set() k -->',k) + # self.log('set() k -->',prefix,k) k_b=self.package_key(k,prefix=prefix) - self.log('set() k_b -->',k_b) + # self.log('set() k_b -->',k_b) - self.log('set() v -->',v) + # self.log('set() v -->',v) v_b=self.package_val(v) - self.log('set() v_b -->',v_b) + self.log(f'set(\n\t{prefix}{k},\n\t\n\t{v_b}\n)\n') return self.store.put(k_b,v_b) def get(self,k,prefix=''): - self.log('get() k -->',k) + # self.log('get() k -->',prefix,k) k_b=self.package_key(k,prefix=prefix) - self.log('get() k_b -->',k_b) + # self.log('get() k_b -->',k_b) try: v=self.store.get(k_b) except KeyError: return None - self.log('get() v -->',v) + # self.log('get() v -->',v) v_b=self.unpackage_val(v) - self.log('get() v_b -->',v_b) + self.log('get()',prefix,k,'-->',v_b) return v_b diff --git a/komrade/backend/keymaker.py b/komrade/backend/keymaker.py index 9b20428..448f99b 100644 --- a/komrade/backend/keymaker.py +++ b/komrade/backend/keymaker.py @@ -1,17 +1,25 @@ -class Keymaker(Logger): +from komrade.backend.crypt import Crypt +from komrade import KomradeException,Logger +from pythemis.skeygen import KEY_PAIR_TYPE, GenerateKeyPair +from pythemis.smessage import SMessage, ssign, sverify +from pythemis.skeygen import GenerateSymmetricKey +from pythemis.scell import SCellSeal +from pythemis.exception import ThemisError +import getpass,os +class Keymaker(Logger): ### BASE STORAGE @property def crypt_keys(self): if not hasattr(self,'_crypt_keys'): - self._crypt_keys = Crypt(fn=PATH_CRYPT_KEYS) + self._crypt_keys = Crypt(fn=self.PATH_CRYPT_KEYS) return self._crypt_keys @property def crypt_data(self): if not hasattr(self,'_crypt_data'): - self._crypt_data = Crypt(fn=PATH_CRYPT_DATA) + self._crypt_data = Crypt(fn=self.PATH_CRYPT_DATA) return self._crypt_data @@ -32,33 +40,38 @@ class Keymaker(Logger): ## 2) I can assemble the key key_encr = self.findkey(keyname+'_encr', keychain,uri) - key_decr_key = self.findkey(keyname+'_decr_key', keychain, uri) - key_decr_cell = self.findkey(keyname+'_decr_cell', keychain, uri) - key_decr_pass = self.findkey(keyname+'_decr_pass', keychain, uri) - key = self.assemble_key(key_encr, key_decr_key, key_decr_cell, key_decr_pass) + key_decr = self.findkey(keyname+'_decr', keychain, uri) + key = self.assemble_key(key_encr, key_decr) return key - def assemble_key(self, key_encr, key_decr_key, key_decr_cell, key_decr_pass): + def get_cell(self, str_or_key_or_cell): + if type(str_or_key_or_cell)==SCellSeal: + return str_or_key_or_cell + elif type(str_or_key_or_cell)==str: + return SCellSeal(passphrase=str_or_key_or_cell) + elif type(str_or_key_or_cell)==bytes: + return SCellSeal(key=key) + + def assemble_key(self, key_encr, key_decr): # need the encrypted half if not key_encr: self.log('!! encrypted half not given') return + if not key_decr: + self.log('!! decryptor half not given') + return # need some way to regenerate the decryptor - if not key_decr_cell: - if key_decr_key: - key_decr_cell = SCellSeal(key=key_decr_key) - elif key_decr_pass: - key_decr_cell = SCellSeal(passphrase=passphrase) - + decr_cell = self.get_cell(key_decr) + # need the decryptor half - if not key_decr_cell: - self.log('!! decryptor half not given') + if not decr_cell: + self.log('!! decryptor cell not regenerable') return # decrypt! try: - key = key_decr_cell.decrypt(key_encr) + key = decr_cell.decrypt(key_encr) self.log('assembled_key built:',key) return key except ThemisError as e: diff --git a/komrade/backend/the_operator.py b/komrade/backend/the_operator.py index 0590496..10cff02 100644 --- a/komrade/backend/the_operator.py +++ b/komrade/backend/the_operator.py @@ -4,6 +4,7 @@ Running on node prime. """ import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..'))) from komrade.backend.crypt import Crypt +from komrade.backend.caller import Caller from komrade.backend.keymaker import Keymaker from flask import Flask from flask_classful import FlaskView @@ -38,96 +39,54 @@ if not os.path.exists(PATH_OPERATOR): os.makedirs(PATH_OPERATOR) -class TheOperator(Keymaker): +class TheOperator(Caller): """ The operator. """ + PATH_CRYPT_KEYS=PATH_CRYPT_KEYS + PATH_CRYPT_DATA=PATH_CRYPT_DATA - def __init__(self, passphrase = None): + def __init__(self, name = 'Operator', passphrase = None): """ Boot up the operator. Requires knowing or setting a password of memory. """ + self.name = name - + # Do I have my keys? + have_keys = self.have_keys() # If not, forge them -- only once! - if not have_keys: self.forge_keys() + # if not have_keys: self.forge_keys() # load keys - self.pubkey,self.privkey = self.get_keys() + # self.pubkey,self.privkey = self.get_op_keys() # That's it! - - - def op_keychain_encr(self): - self.log('loading encrypted keys from disk') - with open(PATH_OPERATOR_PUBKEY,'rb') as f_pub, open(PATH_OPERATOR_PRIVKEY,'rb') as f_priv: - pubkey_encr = f_pub.read() - privkey_encr = f_priv.read() - self.log('Operator pubkey_encr <--',pubkey_encr) - self.log('Operator privkey <--',privkey_encr) - return (pubkey_encr,privkey_encr) - - def get_op_keys(self): - # Get passphrase - passphrase = 'aa' #@ HACK!!! - self.crypt_key,self. = self.get_k - - - # Do I have my keys? - have_keys = self.check_keys() - - - pubkey_encr,privkey_encr = self.get_encypted_keys() - - # decrypt according to password of memory - try: - pubkey = self.cell.decrypt(pubkey_encr) - privkey = self.cell.decrypt(privkey_encr) - except ThemisError: - self.log('\nERROR: Incorrect password of memory! Shutting down.') - exit() - - # self.log(f'decrypted keys to:\npubkey={pubkey}\nprivkey={privkey}') - return (pubkey,privkey) - - def check_keys(self): + def have_keys(self): self.log('checking for keys...') - have_keys = (os.path.exists(PATH_OPERATOR_PUBKEY) and os.path.exists(PATH_OPERATOR_PRIVKEY)) + have_keys = self.crypt_keys.get(self.name,prefix='/pubkey_encr/') self.log('have_keys =',have_keys) return have_keys - def forge_keys(self): - self.log('forging keys...') - - # Initialize asymmetric keys - keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC) - privkey = keypair.export_private_key() - pubkey = keypair.export_public_key() + # def forge_keys(self): + # self.log('forging keys...') - # Also create a symmetric passworded key! - ## It is up to you, forger of the keys, to remember this: - ## otherwise the whole system topples! + # # first time only! + # # this will save the three encrypted keys + # # all are returned, including the decryptor keys + # keychain = self.create_keys(self.name,return_all_keys=True) + + - # Encrypt private public keys - privkey = self.cell.encrypt(privkey) - pubkey = self.cell.encrypt(pubkey) - - # Save - with open(PATH_OPERATOR_PUBKEY,'wb') as of: of.write(pubkey) - with open(PATH_OPERATOR_PRIVKEY,'wb') as of: of.write(privkey) - - self.log('Keys forged!') - - #### # Key CRUD #### - def create_keys(self,name,pubkey_is_public=False): + def forge_new_keys(self,name,pubkey_is_public=False,return_all_keys=False): + self.log('forging new keys...') # Create public and private keys keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC) @@ -146,21 +105,34 @@ class TheOperator(Keymaker): adminkey_encr = SCellSeal(key=adminkey_decr).encrypt(adminkey) # store encrypted on my hardware - self.crypt_keys.set(name,pubkey_encr,prefix='/pub_encr/') - self.crypt_keys.set(pubkey,privkey_encr,prefix='/priv_encr/') - self.crypt_keys.set(privkey,adminkey_encr,prefix='/admin_encr/') + self.crypt_keys.set(name,pubkey_encr,prefix='/pubkey_encr/') + self.crypt_keys.set(pubkey,privkey_encr,prefix='/privkey_encr/') + self.crypt_keys.set(privkey,adminkey_encr,prefix='/adminkey_encr/') # store permissions file? secret_admin_val = pubkey_encr + BSEP + b'find,read,admin' if pubkey_is_public: secret_admin_val += b'*'+BSEP+b'find' secret_admin_val_encr = SCellSeal(key=adminkey).encrypt(secret_admin_val) - self.crypt_keys.set(adminkey,secret_admin_val_encr,prefix='/perm_encr/') + self.crypt_keys.set(adminkey,secret_admin_val_encr,prefix='/permkey_encr/') # keep public key? - if pubkey_is_public: self.crypt_keys.set(name,pubkey_decr,prefix='/pub_decr/') + if pubkey_is_public: self.crypt_keys.set(name,pubkey_decr,prefix='/pubkey_decr/') # send back decryption keys to client - return (pubkey_decr, privkey_decr, adminkey_decr) + if not return_all_keys: # default situation + keychain = { + 'pubkey_decr':pubkey_decr, + 'privkey_decr':privkey_decr, + 'adminkey_decr':adminkey_decr + } + else: # only in special case! + keychain = { + 'pubkey':pubkey,'pubkey_encr':pubkey_encr,'pubkey_decr':pubkey_decr, + 'privkey':privkey,'privkey_encr':privkey_encr,'privkey_decr':privkey_decr, + 'adminkey':adminkey,'adminkey_encr':adminkey_encr,'adminkey_decr':adminkey_decr + } + return keychain + # Magic key attributes @@ -193,7 +165,7 @@ class TheOperator(Keymaker): def exists(self,name): - return self.crypt_keys.get(name,prefix='/pub_encr/') is not None + return self.crypt_keys.get(name,prefix='/pubkey_encr/') is not None def login(self, name, keychain_encr): pass @@ -250,4 +222,4 @@ if __name__ == '__main__': #print(op.crypt_keys.set('aaaa','1111')) # print(op.crypt_keys.get('aaaa')) - op.create_keys(name='marx') \ No newline at end of file + # print(op.forge_keys()) \ No newline at end of file