@ -10,7 +10,7 @@ import twisted
from . import compress
from . import compress
from base64 import b64encode , b64decode
from base64 import b64encode , b64decode
from cryptography import Fernet
from cryptography . fernet import Fernet
from twisted . internet import reactor , defer
from twisted . internet import reactor , defer
class Crypto ( object ) :
class Crypto ( object ) :
@ -18,16 +18,20 @@ class Crypto(object):
self . config = sessconfig
self . config = sessconfig
self . archive = self . config . archive
self . archive = self . config . archive
self . compressor = compress . Compress ( sessconfig )
self . compressor = compress . Compress ( sessconfig )
self . key = None
self . password = None
self . salt = None
def encrypt_project ( passwd ) :
def encrypt_project ( self ) :
"""
"""
Compress and encrypt the project files , deleting clear - text files afterwards
Compress and encrypt the project files , deleting clear - text files afterwards
"""
"""
# Derive the key
key = crypto_ramp_up ( passwd )
# Get the password and salt, then derive the key
self . crypto_ramp_up ( )
# Instantiate the crypto module
# Instantiate the crypto module
fern = Fernet ( key )
fern = Fernet ( self . key )
# Create project archive and crypto archive
# Create project archive and crypto archive
self . compressor . compress_project ( )
self . compressor . compress_project ( )
@ -39,24 +43,26 @@ class Crypto(object):
archive_crypt . write ( crypt_token )
archive_crypt . write ( crypt_token )
# Delete clear-text files
# Delete clear-text files
delete_clear_files ( )
# delete_clear_files( )
# Leave crypto working directory
# Leave crypto working directory
os . chdir ( ' ../ ' )
os . chdir ( ' ../ ' )
@defer . inlineCallbacks
def decrypt_project ( self ) :
def decrypt_project ( passwd ) :
"""
"""
Decrypt and decompress the project files
Decrypt and decompress the project files
"""
"""
# Get the password and salt, then derive the key
self . crypto_ramp_up ( )
# Create crypto working directory
# Create crypto working directory
crypto_path = os . path . join ( os . getcwd ( ) , pappy_config . crypt_dir )
crypto_path = os . path . join ( os . getcwd ( ) , self . config . crypt_dir )
os . mkdir ( crypto_path )
os . mkdir ( crypto_path )
if os . path . isfile ( self . config . crypt_file ) :
if os . path . isfile ( self . config . crypt_file ) :
# Derive the key
# Derive the key
key = crypto_ramp_up ( passwd )
key = self . crypto_ramp_up ( )
fern = Fernet ( key )
fern = Fernet ( key )
# Decrypt the project archive
# Decrypt the project archive
@ -71,18 +77,14 @@ class Crypto(object):
for pf in project_files :
for pf in project_files :
shutil . copy2 ( pf , crypto_path )
shutil . copy2 ( pf , crypto_path )
os . chdir ( crypto_path )
os . chdir ( crypto_path )
def crypto_ramp_up ( self ) :
def crypto_ramp_up ( passwd ) :
if not self . password :
salt = " "
self . get_password ( )
if os . path . isfile ( self . config . salt_file ) :
self . set_salt ( )
salt = get_salt ( )
self . derive_key ( )
else :
salt = create_salt_file ( )
def delete_clear_files ( self ) :
key = derive_key ( passwd , salt )
return key
def delete_clear_files ( ) :
"""
"""
Deletes all clear - text files left in the project directory .
Deletes all clear - text files left in the project directory .
"""
"""
@ -90,7 +92,7 @@ class Crypto(object):
for pf in project_files :
for pf in project_files :
os . remove ( pf )
os . remove ( pf )
def delete_crypt_files ( ) :
def delete_crypt_files ( self ) :
"""
"""
Deletes all encrypted - text files in the project directory .
Deletes all encrypted - text files in the project directory .
Forces generation of new salt after opening and closing the project .
Forces generation of new salt after opening and closing the project .
@ -99,22 +101,29 @@ class Crypto(object):
os . remove ( self . config . salt_file )
os . remove ( self . config . salt_file )
os . remove ( self . config . crypt_file )
os . remove ( self . config . crypt_file )
def create_salt_file ( ) :
def create_salt_file ( self ) :
self . config . salt = urandom ( 16 )
salt_file = open ( self . config . salt_file , ' wb ' )
salt_file = open ( self . config . salt_file , ' wb ' )
if not self . config . salt :
self . set_salt ( )
salt_file . write ( self . config . salt )
salt_file . write ( self . config . salt )
salt_file . close ( )
salt_file . close ( )
return salt
def get_salt ( ) :
def set_salt_from_file ( self ) :
try :
try :
salt_file = open ( self . config . salt_file , ' rb ' )
salt_file = open ( self . config . salt_file , ' rb ' )
salt = salt_file . readline ( )
self . config . salt = salt_file . readline ( ) . strip ( )
except :
except :
raise PappyException ( " Unable to read pappy.salt " )
raise PappyException ( " Unable to read project.salt " )
return salt
def set_salt ( self ) :
if os . path . isfile ( self . config . salt_file ) :
self . set_salt_from_file ( )
else :
self . config . salt = os . urandom ( 16 )
def get_password ( ) :
def get_password ( self ) :
"""
"""
Retrieve password from the user . Raise an exception if the
Retrieve password from the user . Raise an exception if the
password is not capable of utf - 8 encoding .
password is not capable of utf - 8 encoding .
@ -122,12 +131,11 @@ class Crypto(object):
encoded_passwd = " "
encoded_passwd = " "
try :
try :
passwd = raw_input ( " Enter a password: " )
passwd = raw_input ( " Enter a password: " )
encode_passw d = passwd . encode ( " utf-8 " )
self . passwor d = passwd . encode ( " utf-8 " )
except :
except :
raise PappyException ( " Invalid password, try again " )
raise PappyException ( " Invalid password, try again " )
return encoded_passwd
def derive_key ( passwd , salt ) :
def derive_key ( self ) :
"""
"""
Derive a key sufficient for use as a cryptographic key
Derive a key sufficient for use as a cryptographic key
used to encrypt the project ( currently : cryptography . Fernet ) .
used to encrypt the project ( currently : cryptography . Fernet ) .
@ -156,9 +164,8 @@ class Crypto(object):
- scrypt . error if scrypt failed
- scrypt . error if scrypt failed
"""
"""
derived_key = " "
try :
try :
dkey = scrypt . hash ( passwd , salt , bufflen = 32 )
if not self . key :
self . key = scrypt . hash ( self . password , self . salt , bufflen = 32 )
except e :
except e :
raise PappyException ( " Error deriving the key: " , e )
raise PappyException ( " Error deriving the key: " , e )
return derived_key