operator-time
quadrismegistus 4 years ago
parent caee9fc35c
commit 285557f5ff

4
.gitignore vendored

@ -6,4 +6,6 @@ dbm.*
.DS_Store .DS_Store
lib lib
*.venv *.venv
*.key *.key
*.key.*
.op.*

@ -1,5 +1,11 @@
""" from pythemis.skeygen import KEY_PAIR_TYPE, GenerateKeyPair
Code for Caller to interact with Operator from pythemis.smessage import SMessage, ssign, sverify
""" from pythemis.skeygen import GenerateSymmetricKey
from pythemis.scell import SCellSeal
from pythemis.exception import ThemisError
pass
class Caller(object):
def create_keys(self,name):
#
pass

@ -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'))

@ -1,5 +0,0 @@
"""
Storage for both keys and data
"""
pass

@ -2,84 +2,230 @@
There is only one operator! There is only one operator!
Running on node prime. Running on node prime.
""" """
import os import os,sys
from flask import Flask from flask import Flask
from flask import request from flask_classful import FlaskView
import asyncio
from pythemis.skeygen import KEY_PAIR_TYPE, GenerateKeyPair from pythemis.skeygen import KEY_PAIR_TYPE, GenerateKeyPair
from pythemis.smessage import SMessage, ssign, sverify from pythemis.smessage import SMessage, ssign, sverify
from pythemis.skeygen import GenerateSymmetricKey
from pythemis.scell import SCellSeal
from pythemis.exception import ThemisError from pythemis.exception import ThemisError
from base64 import b64encode,b64decode from base64 import b64encode,b64decode
BSEP=b'||||||||||' import getpass
BSEP2=b'@@@@@@@@@@' PATH_HERE = os.path.dirname(__file__)
BSEP3=b'##########' sys.path.append(PATH_HERE)
from crypt import *
HOME_OPERATOR = os.path.abspath(__file__)
PATH_DB_KEYS = os.path.join(HOME_OPERATOR, '.keydb') # paths
PATH_KOMRADE = os.path.abspath(os.path.join(os.path.expanduser('~'),'.komrade'))
PATH_OPERATOR = os.path.join(PATH_KOMRADE,'.operator')
keyhome = os.path.join(os.path.expanduser('~'),'.komrade','.keyserver') PATH_OPERATOR_PUBKEY = os.path.join(PATH_OPERATOR,'.op.key.pub.encr')
if not os.path.exists(keyhome): os.makedirs(keyhome) PATH_OPERATOR_PRIVKEY = os.path.join(PATH_OPERATOR,'.op.key.priv.encr')
PATH_CRYPT_KEYS = os.path.join(PATH_OPERATOR,'.op.db.keys.crypt')
keyserver = 'komrade.app' PATH_CRYPT_DATA = os.path.join(PATH_OPERATOR,'.op.db.data.encr')
keyserver_port = 5566
# init req paths
app = Flask(__name__) if not os.path.exists(PATH_OPERATOR): os.makedirs(PATH_OPERATOR)
async def init():
from api import Api
api = Api()
# keyserver = await api.personate('keyserver') class TheOperator(object):
"""
keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC) The operator.
privkey = keypair.export_private_key() """
pubkey = keypair.export_public_key()
print('pubkey:',pubkey) def __init__(self):
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)) Boot up the operator. Requires knowing or setting a password of memory.
"""
## load pubkey
PATH_PUBKEY = os.path.join(os.path.dirname(__file__),'.keyserver.loc') # Establish encryption/decryption cell
PATH_PRIVKEY = os.path.join(keyhome,'.keyserver.key') self.cell = SCellSeal(passphrase=getpass.getpass('What is the password of memory? '))
if not os.path.exists(PATH_PRIVKEY) or not os.path.exists(PATH_PUBKEY):
asyncio.run(init()) # Do I have my keys?
have_keys = self.check_keys()
with open(PATH_PUBKEY) as f:
PUBKEY_b64 = f.read() # If not, forge them -- only once!
PUBKEY = b64decode(PUBKEY_b64) if not have_keys: self.forge_keys()
with open(PATH_PRIVKEY) as f:
PRIVKEY_b64 = f.read() # load keys
PRIVKEY = b64decode(PRIVKEY_b64) self.pubkey,self.privkey = self.get_keys()
@app.route('/pub') # That's it!
def pubkey():
return PUBKEY_b64
@property
@app.route('/add/<name>',methods=['POST']) def crypt_keys(self):
def add(name): if not hasattr(self,'_crypt_keys'):
key_fn = os.path.join(keyhome,name+'.loc') self._crypt_keys = Crypt(fn=PATH_CRYPT_KEYS, cell=self.cell)
if not os.path.exists(key_fn): return self._crypt_keys
with open(key_fn,'wb') as of:
pubkey,signed_pubkey=request.data.split(BSEP) @property
server_signed_pubkey = b64encode(ssign(PRIVKEY,pubkey)) def crypt_data(self):
package = pubkey + BSEP + signed_pubkey + BSEP + server_signed_pubkey if not hasattr(self,'_crypt_data'):
package_b64 = b64encode(package) self._crypt_data = Crypt(fn=PATH_CRYPT_DATA, cell=self.cell)
print('add package -->',package) return self._crypt_data
print('add package_b64 -->',package_b64)
of.write(package_b64) def log(self,*x):
return package_b64 print(*x)
return None
def get_encypted_keys(self):
@app.route('/get/<name>') self.log('loading encrypted keys from disk')
def get(name): with open(PATH_OPERATOR_PUBKEY,'rb') as f_pub, open(PATH_OPERATOR_PRIVKEY,'rb') as f_priv:
key_fn = os.path.join(keyhome,name+'.loc') pubkey_encr = f_pub.read()
if os.path.exists(key_fn): privkey_encr = f_priv.read()
with open(key_fn,'rb') as f: #self.log('loaded encrypted pubkey is:',pubkey_encr)
signed_key=f.read() #self.log('loaded encrypted privkey is:',privkey_encr)
return signed_key return (pubkey_encr,privkey_encr)
return b''
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 "<br>".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__': if __name__ == '__main__':
app.run(host='0.0.0.0',port=keyserver_port) #run_forever()
# asyncio.run(init())
op = TheOperator()
print(op.crypt_keys.set('aaaa','1111'))
print(op.crypt_keys.get('aaaa'))

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save