@ -37,9 +37,12 @@ class KomradeSymmetricKey(KomradeKey):
self . _cell = SCellSeal ( key = self . key )
return self . _cell
def encrypt ( self , msg , * * kwargs ) :
if issubclass ( type ( msg ) , KomradeKey ) : msg = msg . data
if issubclass ( type ( msg ) , KomradeKey ) or issubclass ( type ( msg ) , KomradeEncryptedKey ) :
msg = msg . data
return self . cell . encrypt ( msg , * * kwargs )
def decrypt ( self , msg , * * kwargs ) :
if issubclass ( type ( msg ) , KomradeKey ) or issubclass ( type ( msg ) , KomradeEncryptedKey ) :
msg = msg . data
return self . cell . decrypt ( msg , * * kwargs )
@ -56,11 +59,14 @@ def getpass_status(passphrase=None):
from getpass import getpass
class KomradeSymmetricKeyWithPassphrase ( KomradeSymmetricKey ) :
def hash ( self , x ) : return self . crypt_keys . hash ( x )
def __init__ ( self , passphrase = DEBUG_DEFAULT_PASSPHRASE , why = WHY_MSG ) :
self . passphrase = passphrase
if not self . passphrase :
self . passphrase = getpass ( why )
#return self.passphrase
if not passphrase :
self . passphrase = hasher ( getpass ( why ) )
else :
self . passphrase = hasher ( passphrase )
@property
def data ( self ) : return KEY_TYPE_SYMMETRIC_WITH_PASSPHRASE . encode ( ' utf-8 ' )
def __repr__ ( self ) : return f ' [Symmetric Key] (generated by password) '
@ -158,21 +164,48 @@ class KomradeEncryptedAsymmetricPublicKey(KomradeEncryptedKey):
class KomradeEncryptedSymmetricKey ( KomradeEncryptedKey ) :
def __repr__ ( self ) : return f ' [Encrypted Symmetric Key] \n ( { self . discreet } ) '
def get_encrypted_key_obj ( data , name_of_encrypted_key ) :
if name_of_encrypted_key . startswith ( ' privkey ' ) :
return KomradeEncryptedAsymmetricPrivateKey ( data )
elif name_of_encrypted_key . startswith ( ' pubkey ' ) :
return KomradeEncryptedAsymmetricPublicKey ( data )
else :
return KomradeEncryptedSymmetricKey ( data )
KEYMAKER_DEFAULT_KEY_TYPES = {
' pubkey ' : KomradeAsymmetricPublicKey ,
' privkey ' : KomradeAsymmetricPrivateKey ,
' adminkey ' : KomradeSymmetricKeyWithoutPassphrase ,
' 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 ,
# 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
}
def get_key_obj ( keyname , data , passphrase = None , key_types = KEYMAKER_DEFAULT_KEY_TYPES ) :
return key_types [ keyname ] ( data )
@ -222,6 +255,11 @@ class Keymaker(Logger):
def top_keys ( self ) :
return [ k for k in self . keys if k . count ( ' _ ' ) == 0 ]
def load_keychain_from_bytes ( self , keychain ) :
for keyname , keyval in keychain . items ( ) :
keychain [ keyname ] = get_key_obj ( keyname , keyval )
return keychain
def keychain ( self , look_for = KEYMAKER_DEFAULT_ALL_KEY_NAMES ) :
# load existing keychain
keys = self . _keychain #self._keychain = keys = {**self._keychain}
@ -231,16 +269,16 @@ class Keymaker(Logger):
pubkey = self . _keychain [ ' pubkey ' ]
# get uri
uri = b64encode ( pubkey )
uri = b64encode ( pubkey ) if type ( pubkey ) == bytes else b64encode ( pubkey . data )
# get from cache
for keyname in look_for :
if keyname in keys and keys [ keyname ] : continue
key = self . crypt_keys . get ( uri , prefix = f ' / { keyname } / ' )
if key : keys [ keyname ] = key #get_encrypted_key_obj(key,keyname)
if key : keys [ keyname ] = get_ key_obj( keyname , key ) #get_encrypted_key_obj(key,keyname)
# try to assemble
keys = self . assemble ( self . assemble ( keys ) )
keys = self . assemble ( keys )
#store to existing set
self . _keychain = keys
@ -248,11 +286,6 @@ class Keymaker(Logger):
#return
return keys
def keychain_obj ( self , look_for = KEYMAKER_DEFAULT_ALL_KEY_NAMES ) :
keychain = self . keychain ( )
for keyname , key_b in keychain . items ( ) :
keychain [ keyname ] = get_encrypted_key_obj ( key_b , keyname )
return keychain
@property
def pubkey ( self ) : return self . keychain ( ) . get ( ' pubkey ' )
@ -328,7 +361,6 @@ class Keymaker(Logger):
def gen_keys_from_types ( self , key_types = KEYMAKER_DEFAULT_KEY_TYPES , passphrase = DEBUG_DEFAULT_PASSPHRASE ) :
"""
Get new asymmetric / symmetric keys , given a dictionary of constants describing their type
@ -338,30 +370,26 @@ class Keymaker(Logger):
asymmetric_pubkey = None
asymmetric_privkey = None
keychain = { }
# print('hello?')
for key_name , key_type_desc in key_types . items ( ) :
# print(key_name,key_type_desc)
if key_type_desc in { KEY_TYPE_ASYMMETRIC_PUBKEY , KEY_TYPE_ASYMMETRIC_PRIVKEY } :
# gen keys requested
for key_name , key_class in key_types . items ( ) :
## asymmetric?
if issubclass ( key_class , KomradeAsymmetricKey ) :
if not asymmetric_privkey or asymmetric_pubkey :
asymmetric_keys = KomradeAsymmetricKey ( )
asymmetric_pubkey = asymmetric_keys . pubkey_obj
asymmetric_privkey = asymmetric_keys . privkey_obj
if not asymmetric_privkey or not asymmetric_pubkey :
keypair = GenerateKeyPair ( KEY_PAIR_TYPE . EC )
asymmetric_privkey = keypair . export_private_key ( )
asymmetric_pubkey = keypair . export_public_key ( )
if key_class == KomradeAsymmetricPublicK ey:
key chain[ key_name ] = asymmetric_pubkey
elif key_class == KomradeAsymmetricPrivateKey :
keychain[ key_name ] = asymmetric_privkey
if key_type_desc == KEY_TYPE_ASYMMETRIC_PRIVKEY :
keychain [ key_name ] = KomradeAsymmetricPrivateKey ( asymmetric_pubkey , asymmetric_privkey )
elif key_type_desc == KEY_TYPE_ASYMMETRIC_PUBKEY :
keychain [ key_name ] = KomradeAsymmetricPublicKey ( asymmetric_pubkey , asymmetric_privkey )
## otherwise, just gen?
elif key_type_desc == KEY_TYPE_SYMMETRIC_WITHOUT_PASSPHRASE :
keychain [ key_name ] = KomradeSymmetricKeyWithoutPassphrase ( )
elif key_type_desc == KEY_TYPE_SYMMETRIC_WITH_PASSPHRASE :
if not passphrase and not self . passphrase :
self . passphrase = getpass ( WHY_MSG )
passphrase = passphrase if passphrase else self . passphrase
keychain [ key_name ] = KomradeSymmetricKeyWithPassphrase ( passphrase = passphrase )
return keychain
@ -375,21 +403,17 @@ class Keymaker(Logger):
# generate encrypted keys too
for key_name in keys_to_gen :
if key_name . endswith ( ' _encr ' ) and key_name not in keychain :
# encrypt it with the associated decr
# self.log(f'let\'s encrypt {key_name}!')
# get data to encrypt
name_of_what_to_encrypt = key_name [ : - len ( ' _encr ' ) ]
the_key_to_encrypt_it_with = name_of_what_to_encrypt + ' _decr '
if the_key_to_encrypt_it_with in keychain and name_of_what_to_encrypt in keychain :
_key_decr = keychain [ the_key_to_encrypt_it_with ]
_key_decr _obj = keychain [ the_key_to_encrypt_it_with ]
_key = keychain [ name_of_what_to_encrypt ]
# self.log(f'about to encrypt key {name_of_what_to_encrypt}, using {the_key_to_encrypt_it_with}, which is a type {KEYMAKER_DEFAULT_KEY_TYPES[the_key_to_encrypt_it_with]} and has value {keychain[the_key_to_encrypt_it_with]}')
_key_encr = _key_decr . encrypt ( _key )
_key_encr = _key_decr . encrypt ( _key . data )
_key_encr_obj = get_encrypted_key_obj ( _key_encr , name_of_what_to_encrypt )
# self.log(f'{_key}\n-- encrypting ----->\n{_key_encr}')
# keychain[key_name]=_key_encr
keychain [ key_name ] = _key_encr_obj
return keychain
@ -440,14 +464,14 @@ Keymaker ({self}) is forging new keys for {name}
keychain = self . gen_encr_keys ( keychain , keys_to_gen , passphrase = passphrase )
# self.log('I built this keychain!',dict_format(keychain,tab=2))
# self.status('@Keymaker: I ended up building these keys:',keychain )
self . status ( ' @Keymaker: I ended up building these keys: ' , keychain )
# save keys!
if save_keychain :
# get URI id to save under (except for pubkeys, accessible by name)
uri_id , keys_saved_d , keychain = self . save_keychain ( name , keychain , keys_to_save )
# self.log('I saved this keychain:',dict_format(keys_saved_d,tab=2),'using the generated-from-pubkey URI ID',uri_id )
self . log ( ' I saved this keychain: ' , dict_format ( keys_saved_d , tab = 2 ) , ' using the generated-from-pubkey URI ID ' , uri_id )
# return keys!
if return_all_keys :
@ -455,12 +479,10 @@ Keymaker ({self}) is forging new keys for {name}
if return_keychain :
keys_returned = self . return_keychain ( keychain , keys_to_return )
# self.log('I am returning this keychain:',dict_format(keys_returned,tab=2) )
self . log ( ' I am returning this keychain: ' , dict_format ( keys_returned , tab = 2 ) )
# return (uri_id,keys_returned)
return keys_returned
raise KomradeException ( ' What did you want me to do here? ' )
@ -537,74 +559,25 @@ Keymaker ({self}) is forging new keys for {name}
return ( uri_id , keys_saved_d , keychain )
def assemble ( self , _keychain ) :
# last minute assemblies?
encr_keys = [ k for k in _keychain if k . endswith ( ' _encr ' ) ]
for ekey in encr_keys :
eval = _keychain [ ekey ]
if not eval : continue
unencrkey = ekey [ : - len ( ' _encr ' ) ]
if unencrkey in _keychain : continue
decrkey = unencrkey + ' _decr '
if decrkey not in _keychain : continue
dval = _keychain [ decrkey ]
if not dval : continue
# self.log(ekey,decrkey,'??')
# self.log(eval,dval,'????')
new_val = self . assemble_key ( eval , dval )
# self.log('!!#!',new_val)
if new_val :
_keychain [ unencrkey ] = new_val
return _keychain
def assemble_key ( self , key_encr , key_decr , key_encr_name = None , key_decr_name = None ) :
# self.log(f'assembling key: {key_decr} decrypting {key_encr}')
# need the encrypted half
if not key_encr :
# self.log('!! encrypted half not given')
return
if not key_decr :
if self . passphrase :
key_decr = self . passphrase
else :
# self.log('!! decryptor half not given')
return
# need some way to regenerate the decryptor
decr_cell = self . get_cell ( key_decr )
# need the decryptor half
if not decr_cell :
# self.log('!! decryptor cell not regenerable')
return
# decrypt!
try :
# self.log(f'>> decrypting {key_encr_name} with {key_decr_name}\n({key_encr} with cell {decr_cell}')
key = decr_cell . decrypt ( key_encr )
# self.log('assembled_key built:',key)
return key
except ThemisError as e :
self . log ( ' !! decryption failed: ' , e )
return
def get_cell ( self , str_or_key_or_cell ) :
# self.log('getting decr cell for',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 = str_or_key_or_cell )
elif issubclass ( type ( str_or_key_or_cell ) , KomradeSymmetricKey ) :
return str_or_key_or_cell . cell
def assemble ( self , keychain , passphrase = None , key_types = KEYMAKER_DEFAULT_KEY_TYPES ) :
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 ]
if unencr_key_name in keychain : continue
if not decr_key_name in keychain :
if type ( key_types [ decr_key_name ] ) == KomradeSymmetricKeyWithPassphrase :
keychain [ decr_key_name ] = KomradeSymmetricKeyWithPassphrase (
passphrase if passphrase else self . passphrase
)
else :
continue
decr_key = keychain . get ( decr_key_name )
encr_key = keychain . get ( encr_key_name )
# self.log('?',decr_key,decr_key_name,encr_key_name,keychain[encr_key_name])
unencr_key = decr_key . decrypt ( encr_key )
keychain [ unencr_key_name ] = get_key_obj ( unencr_key_name , unencr_key )
return keychain
if __name__ == ' __main__ ' :