2020-09-05 16:26:37 +00:00
|
|
|
import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..')))
|
|
|
|
from komrade import *
|
2020-09-05 21:11:42 +00:00
|
|
|
from komrade.backend.crypt import *
|
2020-09-06 14:45:40 +00:00
|
|
|
from abc import ABC, abstractmethod
|
2020-09-11 14:35:47 +00:00
|
|
|
|
|
|
|
# common external imports
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
|
2020-09-10 21:32:59 +00:00
|
|
|
class KomradeKey(ABC,Logger):
|
2020-09-06 14:45:40 +00:00
|
|
|
@abstractmethod
|
|
|
|
def encrypt(self,msg,**kwargs): pass
|
|
|
|
@abstractmethod
|
|
|
|
def decrypt(self,msg,**kwargs): pass
|
|
|
|
@abstractmethod
|
|
|
|
def data(self): pass
|
2020-09-10 14:58:54 +00:00
|
|
|
@property
|
2020-09-12 14:52:55 +00:00
|
|
|
def data_b64(self):return b64encode(self.data) if type(self.data)==bytes else self.data.data_b64
|
2020-09-10 14:58:54 +00:00
|
|
|
@property
|
2020-09-12 20:19:53 +00:00
|
|
|
def data_b64_s(self):
|
2020-09-12 20:20:06 +00:00
|
|
|
return self.data_b64.decode()
|
2020-09-12 20:19:53 +00:00
|
|
|
@property
|
2020-09-10 15:02:26 +00:00
|
|
|
def discreet(self): return make_key_discreet(self.data)
|
2020-09-11 14:35:47 +00:00
|
|
|
def __str__(self):
|
|
|
|
return repr(self)
|
2020-09-06 13:07:27 +00:00
|
|
|
|
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
class KomradeSymmetricKey(KomradeKey):
|
|
|
|
def encrypt(self,msg,**kwargs):
|
2020-09-12 15:34:51 +00:00
|
|
|
if hasattr(msg,'data'): msg=msg.data
|
2020-09-12 15:43:16 +00:00
|
|
|
# print('??? dec',msg,kwargs)
|
2020-09-12 15:34:08 +00:00
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
return self.cell.encrypt(msg,**kwargs)
|
|
|
|
def decrypt(self,msg,**kwargs):
|
2020-09-12 15:34:51 +00:00
|
|
|
if hasattr(msg,'data'): msg=msg.data
|
2020-09-12 15:43:16 +00:00
|
|
|
# print('??? dec',msg,kwargs)
|
2020-09-12 15:34:08 +00:00
|
|
|
|
2020-09-12 15:29:17 +00:00
|
|
|
try:
|
|
|
|
return self.cell.decrypt(msg,**kwargs)
|
|
|
|
except TypeError:
|
|
|
|
return self.cell.decrypt(msg.data,**kwargs)
|
2020-09-10 21:32:59 +00:00
|
|
|
|
2020-09-11 14:35:47 +00:00
|
|
|
|
2020-09-10 21:32:59 +00:00
|
|
|
def getpass_status(passphrase=None):
|
|
|
|
while not passphrase:
|
|
|
|
passphrase1 = getpass(f'@Keymaker: What is a *memorable* pass word or phrase? Do not write it down.\n@{name}: ')
|
|
|
|
passphrase2 = getpass(f'@Keymaker: Could you repeat that?')
|
|
|
|
if passphrase1!=passphrase2:
|
|
|
|
self.status('@Keymaker: Those passwords didn\'t match. Please try again.',clear=False,pause=False)
|
|
|
|
else:
|
|
|
|
return passphrase1
|
|
|
|
|
2020-09-12 07:55:23 +00:00
|
|
|
# get_pass_func = getpass_status if SHOW_STATUS else getpass
|
|
|
|
from getpass import getpass
|
2020-09-06 13:07:27 +00:00
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
class KomradeSymmetricKeyWithPassphrase(KomradeSymmetricKey):
|
2020-09-12 14:32:03 +00:00
|
|
|
def hash(self,x): return self.crypt_keys.hash(x)
|
|
|
|
|
2020-09-14 08:25:55 +00:00
|
|
|
@property
|
|
|
|
def passhash(self):
|
|
|
|
if not self._passhash:
|
2020-09-14 19:25:24 +00:00
|
|
|
self._passhash = hasher(getpass(WHY_MSG))
|
2020-09-14 08:25:55 +00:00
|
|
|
return self._passhash
|
|
|
|
|
|
|
|
def __init__(self,passphrase=None,passhash=None):
|
|
|
|
if passhash:
|
|
|
|
self._passhash = passhash
|
|
|
|
elif passphrase:
|
|
|
|
self._passhash = hasher(passphrase)
|
2020-09-13 19:42:04 +00:00
|
|
|
else:
|
2020-09-14 08:25:55 +00:00
|
|
|
self._passhash = None
|
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
@property
|
|
|
|
def data(self): return KEY_TYPE_SYMMETRIC_WITH_PASSPHRASE.encode('utf-8')
|
2020-09-14 08:25:55 +00:00
|
|
|
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'[Symmetric Key] (generated by password)'
|
2020-09-14 08:25:55 +00:00
|
|
|
|
2020-09-13 18:47:25 +00:00
|
|
|
@property
|
|
|
|
def cell(self):
|
|
|
|
if not hasattr(self,'_cell'):
|
|
|
|
from getpass import getpass
|
2020-09-13 19:42:04 +00:00
|
|
|
self._cell = SCellSeal(passphrase=self.passhash)
|
2020-09-13 18:47:25 +00:00
|
|
|
return self._cell
|
|
|
|
|
2020-09-06 13:07:27 +00:00
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
class KomradeSymmetricKeyWithoutPassphrase(KomradeSymmetricKey):
|
2020-09-07 14:51:59 +00:00
|
|
|
def __init__(self,key=None):
|
|
|
|
self.key = GenerateSymmetricKey() if not key else key
|
2020-09-06 14:45:40 +00:00
|
|
|
@property
|
|
|
|
def data(self): return self.key
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'[Symmetric Key]\n ({self.discreet})'
|
2020-09-14 09:28:56 +00:00
|
|
|
@property
|
|
|
|
def cell(self):
|
|
|
|
if not hasattr(self,'_cell'):
|
|
|
|
self._cell = SCellSeal(key=self.key)
|
|
|
|
return self._cell
|
2020-09-06 14:45:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class KomradeAsymmetricKey(KomradeKey):
|
2020-09-11 14:35:47 +00:00
|
|
|
def __init__(self,pubkey=None,privkey=None):
|
|
|
|
if not pubkey or not privkey:
|
|
|
|
keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC)
|
|
|
|
privkey = keypair.export_private_key()
|
|
|
|
pubkey = keypair.export_public_key()
|
2020-09-06 14:45:40 +00:00
|
|
|
self.pubkey=pubkey
|
2020-09-11 14:35:47 +00:00
|
|
|
self.privkey=privkey
|
|
|
|
self.privkey_obj = KomradeAsymmetricPrivateKey(privkey,pubkey)
|
|
|
|
self.pubkey_obj = KomradeAsymmetricPublicKey(pubkey,privkey)
|
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
def encrypt(self,msg,pubkey=None,privkey=None):
|
2020-09-12 15:32:23 +00:00
|
|
|
if issubclass(type(msg), KomradeKey) or issubclass(type(msg), KomradeEncryptedKey): msg=msg.data
|
2020-09-06 14:45:40 +00:00
|
|
|
pubkey=pubkey if pubkey else self.pubkey
|
|
|
|
privkey=privkey if privkey else self.privkey
|
|
|
|
return SMessage(privkey,pubkey).wrap(msg)
|
|
|
|
def decrypt(self,msg,pubkey=None,privkey=None):
|
2020-09-12 15:32:23 +00:00
|
|
|
if issubclass(type(msg), KomradeKey) or issubclass(type(msg), KomradeEncryptedKey): msg=msg.data
|
2020-09-06 14:45:40 +00:00
|
|
|
pubkey=pubkey if pubkey else self.pubkey
|
|
|
|
privkey=privkey if privkey else self.privkey
|
2020-09-12 15:32:23 +00:00
|
|
|
return SMessage(privkey.data,pubkey.data).unwrap(msg)
|
2020-09-06 14:45:40 +00:00
|
|
|
@property
|
|
|
|
def data(self): return self.key
|
2020-09-10 14:35:54 +00:00
|
|
|
|
2020-09-06 14:45:40 +00:00
|
|
|
class KomradeAsymmetricPublicKey(KomradeAsymmetricKey):
|
2020-09-10 21:32:59 +00:00
|
|
|
def __init__(self,pubkey,privkey=None):
|
|
|
|
self.pubkey=pubkey
|
|
|
|
self.privkey=privkey
|
2020-09-06 14:45:40 +00:00
|
|
|
@property
|
|
|
|
def key(self): return self.pubkey
|
2020-09-10 14:58:54 +00:00
|
|
|
@property
|
|
|
|
def data(self): return self.pubkey
|
|
|
|
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'''[Asymmetric Public Key]\n ({self.data_b64.decode()})'''
|
2020-09-06 14:45:40 +00:00
|
|
|
class KomradeAsymmetricPrivateKey(KomradeAsymmetricKey):
|
2020-09-10 21:32:59 +00:00
|
|
|
def __init__(self,privkey,pubkey=None):
|
|
|
|
self.pubkey=pubkey
|
|
|
|
self.privkey=privkey
|
2020-09-10 14:58:54 +00:00
|
|
|
@property
|
|
|
|
def data(self): return self.privkey
|
2020-09-06 14:45:40 +00:00
|
|
|
@property
|
|
|
|
def key(self): return self.privkey
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'''[Asymmetric Private Key]\n ({self.discreet})'''
|
2020-09-06 13:07:27 +00:00
|
|
|
|
2020-09-13 07:59:46 +00:00
|
|
|
def make_key_discreet(data,chance_unredacted=0.25):
|
2020-09-10 21:32:59 +00:00
|
|
|
import random
|
|
|
|
|
|
|
|
if not data: return '?'
|
|
|
|
if not isBase64(data): data=b64encode(data)
|
|
|
|
key=data.decode()
|
|
|
|
|
2020-09-13 07:47:51 +00:00
|
|
|
return ''.join((k if random.random()<chance_unredacted else '-') for k in key)
|
|
|
|
# return ''.join((k if not i%6 or not i%3 else '-') for i,k in enumerate(key))
|
2020-09-13 07:46:04 +00:00
|
|
|
|
2020-09-10 21:32:59 +00:00
|
|
|
|
2020-09-13 07:59:46 +00:00
|
|
|
def make_key_discreet_str(string,chance_unredacted=0.25):
|
2020-09-11 14:35:47 +00:00
|
|
|
import random
|
|
|
|
if not string: return '?'
|
2020-09-12 07:55:23 +00:00
|
|
|
return ''.join((k if random.random()<chance_unredacted else '-') for k in string)
|
2020-09-11 14:35:47 +00:00
|
|
|
|
2020-09-10 21:32:59 +00:00
|
|
|
|
|
|
|
def make_key_discreet1(data,len_start=10,len_end=10,ellipsis='.',show_len=True):
|
2020-09-10 15:01:33 +00:00
|
|
|
if not data: return '?'
|
|
|
|
if not isBase64(data): data=b64encode(data)
|
|
|
|
data=data.decode()
|
2020-09-10 15:07:57 +00:00
|
|
|
amt_missing = len(data) - len_start - len_end
|
2020-09-10 15:08:57 +00:00
|
|
|
dstr = data[:len_start] + (ellipsis*amt_missing)
|
2020-09-10 15:06:41 +00:00
|
|
|
if len_end: dstr+=data[-len_end:]
|
2020-09-10 15:07:57 +00:00
|
|
|
return f'{dstr}' #' (+{len(data)-len_start-len_end})'
|
2020-09-10 14:45:48 +00:00
|
|
|
|
2020-09-10 21:32:59 +00:00
|
|
|
class KomradeEncryptedKey(Logger):
|
2020-09-10 14:45:48 +00:00
|
|
|
def __init__(self,data): self.data=data
|
2020-09-10 14:47:23 +00:00
|
|
|
@property
|
2020-09-10 14:58:54 +00:00
|
|
|
def data_b64(self): return b64encode(self.data).decode()
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'[Encrypted Key]\n ({self.discreet})'
|
2020-09-10 15:01:33 +00:00
|
|
|
@property
|
2020-09-10 15:02:26 +00:00
|
|
|
def discreet(self): return make_key_discreet(self.data)
|
2020-09-11 14:35:47 +00:00
|
|
|
def __str__(self):
|
|
|
|
return repr(self)
|
2020-09-10 14:45:48 +00:00
|
|
|
|
|
|
|
class KomradeEncryptedAsymmetricPrivateKey(KomradeEncryptedKey):
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'[Encrypted Asymmetric Private Key]\n ({self.discreet})'
|
2020-09-10 14:45:48 +00:00
|
|
|
class KomradeEncryptedAsymmetricPublicKey(KomradeEncryptedKey):
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'[Encrypted Asymmetric Public Key]\n ({self.discreet})'
|
2020-09-10 14:45:48 +00:00
|
|
|
class KomradeEncryptedSymmetricKey(KomradeEncryptedKey):
|
2020-09-12 07:55:23 +00:00
|
|
|
def __repr__(self): return f'[Encrypted Symmetric Key]\n ({self.discreet})'
|
2020-09-10 14:45:48 +00:00
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
KEYMAKER_DEFAULT_KEY_TYPES = {
|
|
|
|
'pubkey':KomradeAsymmetricPublicKey,
|
|
|
|
'privkey':KomradeAsymmetricPrivateKey,
|
|
|
|
'adminkey':KomradeSymmetricKeyWithoutPassphrase,
|
2020-09-10 14:45:48 +00:00
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
'pubkey_decr':KomradeSymmetricKeyWithoutPassphrase,
|
|
|
|
'privkey_decr':KomradeSymmetricKeyWithPassphrase,
|
|
|
|
'adminkey_decr':KomradeSymmetricKeyWithPassphrase,
|
|
|
|
|
|
|
|
'pubkey_decr_decr':KomradeSymmetricKeyWithoutPassphrase,
|
|
|
|
'privkey_decr_decr':KomradeSymmetricKeyWithPassphrase,
|
|
|
|
'adminkey_decr_decr':KomradeSymmetricKeyWithPassphrase,
|
|
|
|
|
|
|
|
'pubkey_encr_decr':KomradeSymmetricKeyWithoutPassphrase,
|
|
|
|
'privkey_encr_decr':KomradeSymmetricKeyWithPassphrase,
|
|
|
|
'adminkey_encr_decr':KomradeSymmetricKeyWithPassphrase,
|
2020-09-10 14:45:48 +00:00
|
|
|
|
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
# encrypted keys
|
|
|
|
'pubkey_encr':KomradeEncryptedAsymmetricPublicKey,
|
|
|
|
'privkey_encr':KomradeEncryptedAsymmetricPrivateKey,
|
|
|
|
'adminkey_encr':KomradeEncryptedSymmetricKey,
|
|
|
|
'pubkey_encr_encr':KomradeEncryptedSymmetricKey,
|
|
|
|
'privkey_encr_encr':KomradeEncryptedSymmetricKey,
|
|
|
|
'adminkey_encr_encr':KomradeEncryptedSymmetricKey,
|
|
|
|
'pubkey_decr_encr':KomradeEncryptedSymmetricKey,
|
|
|
|
'privkey_decr_encr':KomradeEncryptedSymmetricKey,
|
|
|
|
'adminkey_decr_encr':KomradeEncryptedSymmetricKey
|
|
|
|
}
|
2020-09-10 14:45:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-14 08:25:55 +00:00
|
|
|
def get_key_obj(keyname,data,key_types=KEYMAKER_DEFAULT_KEY_TYPES):
|
|
|
|
try:
|
|
|
|
data_s = data.decode()
|
|
|
|
if data_s == KomradeSymmetricKeyWithPassphrase.__name__:
|
|
|
|
return KomradeSymmetricKeyWithPassphrase()
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
pass
|
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
return key_types[keyname](data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-10 14:45:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-04 15:37:12 +00:00
|
|
|
class Keymaker(Logger):
|
2020-09-08 07:01:35 +00:00
|
|
|
def __init__(self,
|
|
|
|
name=None,
|
|
|
|
uri_id=None,
|
|
|
|
keychain={},
|
2020-09-10 10:25:49 +00:00
|
|
|
path_crypt_keys=PATH_CRYPT_CA_KEYS,
|
|
|
|
path_crypt_data=PATH_CRYPT_CA_DATA):
|
2020-09-08 07:01:35 +00:00
|
|
|
|
|
|
|
# set defaults
|
2020-09-05 14:09:31 +00:00
|
|
|
self.name=name
|
2020-09-08 08:13:35 +00:00
|
|
|
self._uri_id=uri_id
|
2020-09-08 11:23:41 +00:00
|
|
|
self._pubkey=None
|
2020-09-13 19:25:43 +00:00
|
|
|
self._keychain={**keychain}
|
2020-09-06 09:48:01 +00:00
|
|
|
self.path_crypt_keys=path_crypt_keys
|
|
|
|
self.path_crypt_data=path_crypt_data
|
2020-09-05 14:09:31 +00:00
|
|
|
|
2020-09-13 18:47:25 +00:00
|
|
|
# boot keychain
|
2020-09-14 08:25:55 +00:00
|
|
|
self._keychain = self.keychain()
|
2020-09-13 18:47:25 +00:00
|
|
|
|
2020-09-09 14:38:37 +00:00
|
|
|
|
2020-09-12 20:19:53 +00:00
|
|
|
def find_pubkey(self,name=None):
|
2020-09-12 21:30:37 +00:00
|
|
|
if not name: name=self.name
|
|
|
|
if 'pubkey' in self._keychain and self._keychain['pubkey']:
|
2020-09-13 20:12:13 +00:00
|
|
|
pk=self._keychain['pubkey']
|
|
|
|
return KomradeAsymmetricPublicKey(b64dec(pk)) if type(pk)==bytes else pk
|
2020-09-12 21:30:37 +00:00
|
|
|
res = self.crypt_keys.get(name, prefix='/pubkey/')
|
|
|
|
res = self.load_qr(self.name)
|
|
|
|
if not res: return
|
2020-09-13 20:08:58 +00:00
|
|
|
return KomradeAsymmetricPublicKey(b64dec(res))
|
2020-09-12 21:30:37 +00:00
|
|
|
|
|
|
|
# self.log('I don\'t know my public key! Do I need to register?')
|
|
|
|
# raise KomradeException(f'I don\'t know my public key!\n{self}\n{self._keychain}')
|
|
|
|
# return res
|
|
|
|
|
|
|
|
def find_name(self,pubkey_b64):
|
2020-09-13 19:10:53 +00:00
|
|
|
res = self.crypt_keys.get(b64enc(q), prefix='/name/')
|
2020-09-12 21:30:37 +00:00
|
|
|
return res
|
2020-09-09 18:31:36 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def keys(self):
|
|
|
|
return sorted(list(self.keychain().keys()))
|
|
|
|
|
|
|
|
@property
|
|
|
|
def top_keys(self):
|
|
|
|
return [k for k in self.keys if k.count('_')==0]
|
2020-09-08 11:23:41 +00:00
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
def load_keychain_from_bytes(self,keychain):
|
|
|
|
for keyname,keyval in keychain.items():
|
|
|
|
keychain[keyname] = get_key_obj(keyname,keyval)
|
|
|
|
return keychain
|
|
|
|
|
2020-09-14 08:25:55 +00:00
|
|
|
def keychain(self,look_for=KEYMAKER_DEFAULT_ALL_KEY_NAMES):
|
2020-09-09 14:38:37 +00:00
|
|
|
# load existing keychain
|
2020-09-12 20:19:53 +00:00
|
|
|
keys = self._keychain
|
2020-09-09 14:38:37 +00:00
|
|
|
|
|
|
|
# get uri
|
2020-09-14 08:25:55 +00:00
|
|
|
pubkey = self.find_pubkey()
|
2020-09-12 21:33:49 +00:00
|
|
|
if pubkey:
|
2020-09-14 08:25:55 +00:00
|
|
|
keys['pubkey'] = pubkey
|
|
|
|
|
2020-09-12 21:36:19 +00:00
|
|
|
uri = pubkey.data_b64
|
2020-09-12 21:33:49 +00:00
|
|
|
#uri = b64encode(pubkey) if type(pubkey)==bytes else b64encode(pubkey.encode())
|
|
|
|
# get from cache
|
|
|
|
for keyname in look_for:
|
2020-09-13 06:09:00 +00:00
|
|
|
# print(self.name,'looking for key:',keyname)
|
2020-09-13 20:07:18 +00:00
|
|
|
if keyname in keys and keys[keyname]: continue
|
2020-09-12 21:33:49 +00:00
|
|
|
key = self.crypt_keys.get(uri,prefix=f'/{keyname}/')
|
2020-09-13 06:09:00 +00:00
|
|
|
# print('found in crypt:',key,'for',keyname)
|
2020-09-13 06:08:11 +00:00
|
|
|
if key: keys[keyname]=get_key_obj(keyname,key)
|
2020-09-08 15:14:48 +00:00
|
|
|
|
2020-09-08 11:23:41 +00:00
|
|
|
# try to assemble
|
2020-09-14 08:25:55 +00:00
|
|
|
keys = self.assemble(self.assemble(keys))
|
2020-09-09 14:38:37 +00:00
|
|
|
|
|
|
|
#store to existing set
|
2020-09-13 19:25:43 +00:00
|
|
|
self._keychain = {**keys}
|
2020-09-09 14:38:37 +00:00
|
|
|
|
|
|
|
#return
|
2020-09-08 11:23:41 +00:00
|
|
|
return keys
|
|
|
|
|
2020-09-11 14:35:47 +00:00
|
|
|
|
2020-09-09 14:38:37 +00:00
|
|
|
@property
|
|
|
|
def pubkey(self): return self.keychain().get('pubkey')
|
2020-09-08 11:23:41 +00:00
|
|
|
@property
|
2020-09-10 08:19:08 +00:00
|
|
|
def pubkey_b64(self): return b64encode(self.pubkey) #self.keychain().get('pubkey')
|
|
|
|
@property
|
2020-09-08 15:14:48 +00:00
|
|
|
def privkey(self): return self.keychain().get('privkey')
|
2020-09-08 11:23:41 +00:00
|
|
|
@property
|
2020-09-08 15:14:48 +00:00
|
|
|
def adminkey(self): return self.keychain().get('adminkey')
|
2020-09-09 17:34:19 +00:00
|
|
|
@property
|
|
|
|
def pubkey_encr(self): return self.keychain().get('pubkey_encr')
|
|
|
|
@property
|
|
|
|
def privkey_encr(self): return self.keychain().get('privkey_encr')
|
|
|
|
@property
|
|
|
|
def adminkey_encr(self): return self.keychain().get('adminkey_encr')
|
|
|
|
@property
|
|
|
|
def pubkey_decr(self): return self.keychain().get('pubkey_decr')
|
|
|
|
@property
|
|
|
|
def privkey_decr(self): return self.keychain().get('privkey_decr')
|
|
|
|
@property
|
|
|
|
def adminkey_decr(self): return self.keychain().get('adminkey_decr')
|
2020-09-08 11:23:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
def load_qr(self,name):
|
2020-09-14 06:02:17 +00:00
|
|
|
if not name: return
|
2020-09-08 11:23:41 +00:00
|
|
|
# try to load?
|
|
|
|
contact_fnfn = os.path.join(PATH_QRCODES,name+'.png')
|
2020-09-08 15:31:16 +00:00
|
|
|
if not os.path.exists(contact_fnfn): return ''
|
2020-09-08 11:23:41 +00:00
|
|
|
# with open(contact_fnfn,'rb') as f: dat=f.read()
|
|
|
|
from pyzbar.pyzbar import decode
|
|
|
|
from PIL import Image
|
2020-09-08 15:14:48 +00:00
|
|
|
res= decode(Image.open(contact_fnfn))[0].data
|
2020-09-08 11:23:41 +00:00
|
|
|
|
2020-09-08 15:14:48 +00:00
|
|
|
# self.log('QR??',res,b64decode(res))
|
|
|
|
return b64decode(res)
|
2020-09-08 11:23:41 +00:00
|
|
|
|
2020-09-08 08:13:35 +00:00
|
|
|
@property
|
|
|
|
def uri_id(self):
|
2020-09-08 15:14:48 +00:00
|
|
|
if not self._uri_id:
|
2020-09-12 20:19:53 +00:00
|
|
|
pubkey = self.pubkey #find_pubkey()
|
2020-09-13 09:46:10 +00:00
|
|
|
self._uri_id = pubkey.data_b64
|
2020-09-08 08:13:35 +00:00
|
|
|
return self._uri_id
|
|
|
|
|
2020-09-04 12:46:22 +00:00
|
|
|
### BASE STORAGE
|
|
|
|
@property
|
|
|
|
def crypt_keys(self):
|
|
|
|
if not hasattr(self,'_crypt_keys'):
|
2020-09-06 09:48:01 +00:00
|
|
|
self._crypt_keys = Crypt(fn=self.path_crypt_keys)
|
2020-09-04 12:46:22 +00:00
|
|
|
return self._crypt_keys
|
|
|
|
|
|
|
|
@property
|
|
|
|
def crypt_data(self):
|
|
|
|
if not hasattr(self,'_crypt_data'):
|
2020-09-06 09:48:01 +00:00
|
|
|
self._crypt_data = Crypt(fn=self.path_crypt_data)
|
2020-09-04 12:46:22 +00:00
|
|
|
return self._crypt_data
|
|
|
|
|
2020-09-07 08:13:08 +00:00
|
|
|
|
2020-09-14 09:28:56 +00:00
|
|
|
|
2020-09-10 09:31:32 +00:00
|
|
|
def get_path_qrcode(self,name=None,dir=None,ext='.png'):
|
|
|
|
if not name: name=self.name
|
|
|
|
if not dir: dir = PATH_QRCODES
|
|
|
|
fnfn = os.path.join(dir,name+ext)
|
|
|
|
return fnfn
|
|
|
|
|
2020-09-10 12:28:36 +00:00
|
|
|
@property
|
2020-09-10 12:52:07 +00:00
|
|
|
def qr(self): return self.qr_str(data=self.uri_id)
|
|
|
|
|
|
|
|
def qr_str(self,data=None):
|
2020-09-11 14:35:47 +00:00
|
|
|
data = self.uri_id if not data else data
|
|
|
|
return get_qr_str(data)
|
|
|
|
|
2020-09-10 12:24:06 +00:00
|
|
|
|
2020-09-10 09:31:32 +00:00
|
|
|
def save_uri_as_qrcode(self,uri_id=None,name=None):
|
|
|
|
if not uri_id: uri_id = self.uri_id
|
2020-09-08 07:13:48 +00:00
|
|
|
if not uri_id and not self.uri_id: raise KomradeException('Need URI id to save!')
|
2020-09-10 09:31:32 +00:00
|
|
|
if not name: name=self.name
|
2020-09-08 07:13:48 +00:00
|
|
|
|
|
|
|
# gen
|
|
|
|
import pyqrcode
|
2020-09-08 07:20:42 +00:00
|
|
|
qr = pyqrcode.create(uri_id)
|
2020-09-10 09:31:32 +00:00
|
|
|
ofnfn = self.get_path_qrcode(name=name)
|
2020-09-08 07:32:44 +00:00
|
|
|
qr.png(ofnfn,scale=5)
|
2020-09-10 12:24:06 +00:00
|
|
|
|
2020-09-10 12:28:36 +00:00
|
|
|
self._uri_id = uri_id
|
2020-09-13 10:35:05 +00:00
|
|
|
self.log(f'''Saved public key as QR code to:\n{ofnfn}\n\n{self.qr}''')
|
2020-09-13 09:46:10 +00:00
|
|
|
return ofnfn
|
2020-09-07 08:13:08 +00:00
|
|
|
|
2020-09-08 06:58:54 +00:00
|
|
|
def save_keychain(self,name,keychain,keys_to_save=None,uri_id=None):
|
2020-09-07 23:34:27 +00:00
|
|
|
if not keys_to_save: keys_to_save = list(keychain.keys())
|
2020-09-10 15:34:26 +00:00
|
|
|
if not uri_id and 'pubkey' in keychain:
|
|
|
|
uri_id = b64encode(keychain['pubkey'].data).decode() #uri_id = get_random_id() + get_random_id()
|
2020-09-10 09:31:32 +00:00
|
|
|
# self.log(f'SAVING KEYCHAIN FOR {name} under URI {uri_id}')
|
2020-09-08 08:13:35 +00:00
|
|
|
self._uri_id = uri_id
|
2020-09-06 14:45:40 +00:00
|
|
|
# filter for transfer
|
|
|
|
for k,v in keychain.items():
|
|
|
|
if issubclass(type(v),KomradeKey):
|
|
|
|
v=v.data
|
|
|
|
keychain[k]=v
|
2020-09-07 08:13:08 +00:00
|
|
|
|
2020-09-07 23:34:27 +00:00
|
|
|
# save keychain
|
|
|
|
keys_saved_d={}
|
|
|
|
for keyname in keys_to_save:
|
2020-09-08 08:34:01 +00:00
|
|
|
if not '_' in keyname and keyname!='pubkey':
|
2020-09-11 14:35:47 +00:00
|
|
|
self.log('there is no private property in a socialist network! all keys must be split between komrades',keyname)
|
2020-09-07 23:34:27 +00:00
|
|
|
if keyname in keychain:
|
2020-09-08 09:14:42 +00:00
|
|
|
# uri = uri_id
|
2020-09-09 17:52:54 +00:00
|
|
|
uri = uri_id if keyname!='pubkey' else name
|
2020-09-10 15:34:26 +00:00
|
|
|
if not uri: raise KomradeException('invalid URI! {uri}')
|
2020-09-10 14:50:07 +00:00
|
|
|
val = keychain[keyname]
|
|
|
|
if issubclass(type(keychain[keyname]), KomradeKey) or issubclass(type(keychain[keyname]), KomradeEncryptedKey):
|
|
|
|
val = val.data
|
|
|
|
self.crypt_keys.set(uri,val,prefix=f'/{keyname}/')
|
2020-09-07 23:34:27 +00:00
|
|
|
keys_saved_d[keyname] = keychain[keyname]
|
2020-09-07 08:13:08 +00:00
|
|
|
|
2020-09-09 15:35:38 +00:00
|
|
|
# save pubkey as QR
|
|
|
|
if not 'pubkey' in keys_saved_d:
|
2020-09-10 11:02:41 +00:00
|
|
|
# self.log('did not save pubkey in crypt, storing as QR...')
|
2020-09-10 09:31:32 +00:00
|
|
|
self.save_uri_as_qrcode(name=name, uri_id=uri_id)
|
|
|
|
|
|
|
|
# set to my keychain right away
|
2020-09-13 19:25:43 +00:00
|
|
|
self._keychain = {**keychain}
|
2020-09-09 15:35:38 +00:00
|
|
|
|
2020-09-08 07:16:22 +00:00
|
|
|
return (uri_id,keys_saved_d,keychain)
|
2020-09-06 18:02:18 +00:00
|
|
|
|
2020-09-14 09:28:56 +00:00
|
|
|
def assemble(self,keychain,key_types=KEYMAKER_DEFAULT_KEY_TYPES,decrypt=True):
|
2020-09-12 14:32:03 +00:00
|
|
|
encr_keys = [k for k in keychain.keys() if k.endswith('_encr')]
|
|
|
|
for encr_key_name in encr_keys:
|
|
|
|
decr_key_name = encr_key_name[:-5] + '_decr'
|
|
|
|
unencr_key_name = encr_key_name[:-5]
|
2020-09-12 15:20:31 +00:00
|
|
|
# self.log(encr_key_name,decr_key_name,unencr_key_name)
|
|
|
|
if decrypt and unencr_key_name in keychain: continue
|
2020-09-12 14:32:03 +00:00
|
|
|
if not decr_key_name in keychain:
|
2020-09-14 08:25:55 +00:00
|
|
|
self.log('! not in keychain: decr key name:',decr_key_name,keychain)
|
2020-09-12 19:22:26 +00:00
|
|
|
continue
|
2020-09-12 14:32:03 +00:00
|
|
|
decr_key = keychain.get(decr_key_name)
|
2020-09-12 16:45:21 +00:00
|
|
|
try:
|
|
|
|
if decrypt:
|
|
|
|
encr_key = keychain.get(encr_key_name)
|
2020-09-14 19:25:24 +00:00
|
|
|
self.log(f'about to decrypt {encr_key} with {decr_key} and {decr_key.cell}')
|
2020-09-12 16:45:21 +00:00
|
|
|
unencr_key = decr_key.decrypt(encr_key.data)
|
2020-09-12 18:18:37 +00:00
|
|
|
keychain[unencr_key_name] = get_key_obj(unencr_key_name,unencr_key)
|
2020-09-12 16:45:21 +00:00
|
|
|
else:
|
2020-09-13 07:08:15 +00:00
|
|
|
# unencr_key = keychain.get(unencr_key_name)
|
2020-09-13 06:46:53 +00:00
|
|
|
self.log(f'about to encrypt {unencr_key} with {decr_key}')
|
2020-09-12 16:45:21 +00:00
|
|
|
encr_key = decr_key.encrypt(unencr_key.data)
|
2020-09-12 18:18:37 +00:00
|
|
|
keychain[encr_key_name] = get_key_obj(encr_key_name,encr_key)
|
2020-09-13 06:46:53 +00:00
|
|
|
except ThemisError as e:
|
2020-09-14 19:25:24 +00:00
|
|
|
self.log('error!!',e,decrypt,decr_key,encr_key,decr_key_name,encr_key_name)
|
2020-09-12 16:45:21 +00:00
|
|
|
pass
|
2020-09-12 15:09:26 +00:00
|
|
|
|
2020-09-12 14:32:03 +00:00
|
|
|
return keychain
|
2020-09-06 14:45:40 +00:00
|
|
|
|
2020-09-12 15:09:26 +00:00
|
|
|
def disassemble(self,keychain,**kwargs):
|
|
|
|
return self.assemble(keychain,decrypt=False,**kwargs)
|
|
|
|
|
|
|
|
|