From 285557f5fff1f25bb5f3050bfb9e579f31dc07f4 Mon Sep 17 00:00:00 2001 From: quadrismegistus Date: Thu, 3 Sep 2020 22:11:58 +0100 Subject: [PATCH] gitgo --- .gitignore | 4 +- backend/caller.py | 14 +- backend/crypt.py | 96 +++++++++++++ backend/storage.py | 5 - backend/the_operator.py | 294 ++++++++++++++++++++++++++++++---------- docs/cryptosystems.html | 11 ++ 6 files changed, 340 insertions(+), 84 deletions(-) create mode 100644 backend/crypt.py delete mode 100644 backend/storage.py create mode 100644 docs/cryptosystems.html diff --git a/.gitignore b/.gitignore index eac6b2b..ab21119 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ dbm.* .DS_Store lib *.venv -*.key \ No newline at end of file +*.key +*.key.* +.op.* \ No newline at end of file diff --git a/backend/caller.py b/backend/caller.py index 6d246b9..89fa96c 100644 --- a/backend/caller.py +++ b/backend/caller.py @@ -1,5 +1,11 @@ -""" -Code for Caller to interact with Operator -""" +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 -pass \ No newline at end of file + +class Caller(object): + def create_keys(self,name): + # + pass \ No newline at end of file diff --git a/backend/crypt.py b/backend/crypt.py new file mode 100644 index 0000000..4ee2e4d --- /dev/null +++ b/backend/crypt.py @@ -0,0 +1,96 @@ +""" +Storage for both keys and data +""" +from simplekv.fs import FilesystemStore +from simplekv.memory.redisstore import RedisStore +import redis +import hashlib,os +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 zlib + + + + + +class Crypt(object): + def log(self,*x): print(*x) + + def __init__(self,name=None,fn=None,cell=None): + if not name and fn: name=os.path.basename(fn).replace('.','_') + + self.name,self.fn,self.cell = name,fn,cell + self.store = FilesystemStore(self.fn) + + def hash(self,binary_data): + return hashlib.sha256(binary_data).hexdigest() + # return zlib.adler32(binary_data) + + def force_binary(self,k_b): + if type(k_b)==str: k_b=k_b.encode() + if type(k_b)!=bytes: k_b=str(k_b).encode() + return k_b + + def package_key(self,k): + k_b = self.force_binary(k) + # k_b = self.cell.encrypt(k_b) + k_b = self.hash(k_b) + return k_b + + def package_val(self,k): + k_b = self.force_binary(k) + k_b = self.cell.encrypt(k_b) + return k_b + + + def unpackage_val(self,k_b): + try: + return self.cell.decrypt(k_b) + except ThemisError: + return None + + + def set(self,k,v): + self.log('set() k -->',k) + k_b=self.package_key(k) + self.log('set() k_b -->',k_b) + + self.log('set() v -->',v) + v_b=self.package_val(v) + self.log('set() v_b -->',v_b) + + return self.store.put(k_b,v_b) + + def get(self,k): + self.log('get() k -->',k) + k_b=self.package_key(k) + self.log('get() k_b -->',k_b) + + v=self.store.get(k_b) + self.log('get() v -->',v) + v_b=self.unpackage_val(v) + self.log('get() v_b -->',v_b) + return v_b + + +class KeyCrypt(Crypt): + def __init__(self): + return super().__init__(name=PATH_CRYPT_KEYS.replace('.','_')) + + +class DataCrypt(Crypt): + def __init__(self): + return super().__init__(name=PATH_CRYPT_DATA.replace('.','_')) + + + + +if __name__=='__main__': + crypt = Crypt('testt') + + print(crypt.set('hellothere',b'ryan')) + + # print(crypt.get(b'hello there')) \ No newline at end of file diff --git a/backend/storage.py b/backend/storage.py deleted file mode 100644 index 283e48e..0000000 --- a/backend/storage.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -Storage for both keys and data -""" - -pass \ No newline at end of file diff --git a/backend/the_operator.py b/backend/the_operator.py index c788e38..1402f84 100644 --- a/backend/the_operator.py +++ b/backend/the_operator.py @@ -2,84 +2,230 @@ There is only one operator! Running on node prime. """ -import os +import os,sys from flask import Flask -from flask import request -import asyncio +from flask_classful import FlaskView 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 from base64 import b64encode,b64decode -BSEP=b'||||||||||' -BSEP2=b'@@@@@@@@@@' -BSEP3=b'##########' - -HOME_OPERATOR = os.path.abspath(__file__) -PATH_DB_KEYS = os.path.join(HOME_OPERATOR, '.keydb') - - -keyhome = os.path.join(os.path.expanduser('~'),'.komrade','.keyserver') -if not os.path.exists(keyhome): os.makedirs(keyhome) - -keyserver = 'komrade.app' -keyserver_port = 5566 - -app = Flask(__name__) - -async def init(): - from api import Api - api = Api() - # keyserver = await api.personate('keyserver') - - keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC) - privkey = keypair.export_private_key() - pubkey = keypair.export_public_key() - - print('pubkey:',pubkey) - with open('.keyserver.loc','wb') as of: of.write(b64encode(pubkey)) - with open(os.path.join(keyhome,'.keyserver.key'),'wb') as of: of.write(b64encode(privkey)) - -## load pubkey -PATH_PUBKEY = os.path.join(os.path.dirname(__file__),'.keyserver.loc') -PATH_PRIVKEY = os.path.join(keyhome,'.keyserver.key') -if not os.path.exists(PATH_PRIVKEY) or not os.path.exists(PATH_PUBKEY): - asyncio.run(init()) - -with open(PATH_PUBKEY) as f: - PUBKEY_b64 = f.read() - PUBKEY = b64decode(PUBKEY_b64) -with open(PATH_PRIVKEY) as f: - PRIVKEY_b64 = f.read() - PRIVKEY = b64decode(PRIVKEY_b64) - -@app.route('/pub') -def pubkey(): - return PUBKEY_b64 - -@app.route('/add/',methods=['POST']) -def add(name): - key_fn = os.path.join(keyhome,name+'.loc') - if not os.path.exists(key_fn): - with open(key_fn,'wb') as of: - pubkey,signed_pubkey=request.data.split(BSEP) - server_signed_pubkey = b64encode(ssign(PRIVKEY,pubkey)) - package = pubkey + BSEP + signed_pubkey + BSEP + server_signed_pubkey - package_b64 = b64encode(package) - print('add package -->',package) - print('add package_b64 -->',package_b64) - of.write(package_b64) - return package_b64 - return None - -@app.route('/get/') -def get(name): - key_fn = os.path.join(keyhome,name+'.loc') - if os.path.exists(key_fn): - with open(key_fn,'rb') as f: - signed_key=f.read() - return signed_key - return b'' +import getpass +PATH_HERE = os.path.dirname(__file__) +sys.path.append(PATH_HERE) +from crypt import * + +# paths +PATH_KOMRADE = os.path.abspath(os.path.join(os.path.expanduser('~'),'.komrade')) +PATH_OPERATOR = os.path.join(PATH_KOMRADE,'.operator') +PATH_OPERATOR_PUBKEY = os.path.join(PATH_OPERATOR,'.op.key.pub.encr') +PATH_OPERATOR_PRIVKEY = os.path.join(PATH_OPERATOR,'.op.key.priv.encr') +PATH_CRYPT_KEYS = os.path.join(PATH_OPERATOR,'.op.db.keys.crypt') +PATH_CRYPT_DATA = os.path.join(PATH_OPERATOR,'.op.db.data.encr') + +# init req paths +if not os.path.exists(PATH_OPERATOR): os.makedirs(PATH_OPERATOR) + + + + +class TheOperator(object): + """ + The operator. + """ + + + def __init__(self): + """ + Boot up the operator. Requires knowing or setting a password of memory. + """ + + # Establish encryption/decryption cell + self.cell = SCellSeal(passphrase=getpass.getpass('What is the password of memory? ')) + + # Do I have my keys? + have_keys = self.check_keys() + + # If not, forge them -- only once! + if not have_keys: self.forge_keys() + + # load keys + self.pubkey,self.privkey = self.get_keys() + + # That's it! + + + @property + def crypt_keys(self): + if not hasattr(self,'_crypt_keys'): + self._crypt_keys = Crypt(fn=PATH_CRYPT_KEYS, cell=self.cell) + return self._crypt_keys + + @property + def crypt_data(self): + if not hasattr(self,'_crypt_data'): + self._crypt_data = Crypt(fn=PATH_CRYPT_DATA, cell=self.cell) + return self._crypt_data + + def log(self,*x): + print(*x) + + def get_encypted_keys(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('loaded encrypted pubkey is:',pubkey_encr) + #self.log('loaded encrypted privkey is:',privkey_encr) + return (pubkey_encr,privkey_encr) + + def get_keys(self): + 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): + self.log('checking for keys...') + have_keys = (os.path.exists(PATH_OPERATOR_PUBKEY) and os.path.exists(PATH_OPERATOR_PRIVKEY)) + 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() + + # Also create a symmetric passworded key! + ## It is up to you, forger of the keys, to remember this: + ## otherwise the whole system topples! + + # 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): + + # Create public and private keys + keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC) + privkey = keypair.export_private_key() + pubkey = keypair.export_public_key() + + # Create permission keys + permkey_find = GenerateSymmetricKey() + permkey_read = GenerateSymmetricKey() + permkey_admin = GenerateSymmetricKey() + permkey_adminX = GenerateSymmetricKey() + + # (1) Encrypted pubkey + pubkey_decr = permkey_find + pubkey_encr = SCellSeal(key=pubkey_decr).encrypt(pubkey) + + # (2) Encnrypted priv key + privkey_decr = permkey_read + privkey_encr = SCellSeal(key=privkey_decr).encrypt(privkey) + + # (3) Encrypted admin key? + adminkey_decr = permkey_adminX + adminkey_encr = SCellSeal(key=adminkey_decr).encrypt(permkey_admin) + + + + + + self.log(f'priv_key saved to {self.key_path_priv}') + with open(self.key_path_priv, "wb") as private_key_file: + private_key_file.write(self.privkey_b64) + + with open(self.key_path_pub, "wb") as public_key_file: + # save SIGNED public key + public_key_file.write(self.pubkey_b64) + + with open(self.key_path_pub_enc,'wb') as signed_public_key_file: + # self.log('encrypted_pubkey_b64 -->',self.encrypted_pubkey_b64) + pubkey_b64 = b64encode(self.pubkey) + self.log('pubkey',self.pubkey) + self.log('pubkey_b64',pubkey_b64) + + encrypted_pubkey_b64 = self.encrypt(pubkey_b64, pubkey_b64, KOMRADE_PRIV_KEY) + self.log('encrypted_pubkey_b64 -->',encrypted_pubkey_b64) + + signed_public_key_file.write(encrypted_pubkey_b64) + + + + def create_permissions_file(self): + pass + + + + + + + + + + + + + + +class TheOperatorView(FlaskView): + route_prefix = '/' + def index(self): + print('hello') + return "
".join(quotes) + + def something(self): + return 'something' + + + + + + + + + + + +## Main + +def run_forever(): + app = Flask(__name__) + TheOperator.register(app, route_base='/op/', route_prefix=None) + app.run(debug=True) if __name__ == '__main__': - app.run(host='0.0.0.0',port=keyserver_port) - # asyncio.run(init()) \ No newline at end of file + #run_forever() + + op = TheOperator() + + print(op.crypt_keys.set('aaaa','1111')) + + print(op.crypt_keys.get('aaaa')) \ No newline at end of file diff --git a/docs/cryptosystems.html b/docs/cryptosystems.html new file mode 100644 index 0000000..b041e43 --- /dev/null +++ b/docs/cryptosystems.html @@ -0,0 +1,11 @@ + + + + +cryptosystems + + +
+ + + \ No newline at end of file