Fixed minor bugs in decrypting project

Project now decrypts properly and fails out loudly when incorrect
password is supplied. Must supply project name via command line now.
master
Onics 8 years ago
parent ff8595e8f4
commit 5ceedddd1a
  1. 70
      pappyproxy/crypto.py
  2. 23
      pappyproxy/pappy.py

@ -17,7 +17,7 @@ from twisted.internet import reactor, defer
class Crypto(object):
def __init__(self, sessconfig):
self.config = sessconfig
self.archive = self.config.archive
self.archive = sessconfig.archive
self.compressor = compress.Compress(sessconfig)
self.key = None
self.password = None
@ -31,15 +31,15 @@ class Crypto(object):
# Leave the crypto working directory
os.chdir('../')
# Get the password and salt, then derive the key
self.crypto_ramp_up()
self.compressor.compress_project()
# Create project and crypto archive
archive_file = open(self.archive, 'rb')
archive_crypt = open(self.config.crypt_file, 'wb')
# Get the password and salt, then derive the key
self.crypto_ramp_up()
# Encrypt the archive read as a bytestring
fern = Fernet(self.key)
crypt_token = fern.encrypt(archive_file.read())
@ -61,46 +61,64 @@ class Crypto(object):
"""
# If project hasn't been encrypted before, setup crypt working directory
crypt_fp = os.path.join(os.getcwd(), self.config.crypt_file)
if not os.path.isfile(crypt_fp):
if not os.path.isfile(self.config.crypt_file):
os.mkdir(self.config.crypt_dir)
project_files = self.config.get_project_files()
for pf in project_files:
shutil.copy2(pf, self.config.crypt_dir)
os.chdir(self.config.crypt_dir)
return True
# Otherwise, decrypt and decompress the project
else:
self.crypto_ramp_up()
fern = Fernet(self.key)
# Decrypt the project archive
archive_crypt = open(self.config.crypt_file, 'rb').read()
archive_file = open(self.config.archive, 'wb')
try:
archive = fern.decrypt(archive_crypt)
except InvalidToken:
raise PappyException("Problem decrypting the file, restart pappy to try again")
reactor.stop()
defer.returnValue(None)
retries = 3
while True:
try:
self.crypto_ramp_up()
fern = Fernet(self.key)
archive = fern.decrypt(archive_crypt)
break
except InvalidToken:
print "Invalid password"
retries -= 1
# Quit pappy if user doesn't retry
# or if all retries exhuasted
if not self.confirm_password_retry() or retries <= 0:
return False
else:
self.password = None
self.key = None
self.salt = None
pass
archive_file.write(archive)
archive_file.close()
self.compressor.decompress_project()
# Force generation of new salt and crypt archive
self.delete_crypt_files()
os.chdir(self.config.crypt_dir)
return True
def confirm_password_retry(self):
answer = raw_input("Would you like to re-enter your password? (y/n)").strip()
if answer[0] == "y" or answer[0] == "Y":
return True
else:
return False
def crypto_ramp_up(self):
if not self.password:
self.get_password()
self.set_salt()
self.derive_key()
def get_password(self):
"""
Retrieve password from the user. Raise an exception if the
@ -108,24 +126,24 @@ class Crypto(object):
"""
encoded_passwd = ""
try:
passwd = raw_input("Enter a password: ")
passwd = raw_input("Enter a password: ").strip()
self.password = passwd.encode("utf-8")
except:
raise PappyException("Invalid password, try again")
def set_salt(self):
if os.path.isfile(self.config.salt_file):
self.set_salt_from_file()
else:
self.salt = os.urandom(16)
def set_salt_from_file(self):
try:
salt_file = open(self.config.salt_file, 'rb')
self.salt = salt_file.readline().strip()
except:
raise PappyException("Unable to read project.salt")
def create_salt_file(self):
salt_file = open(self.config.salt_file, 'wb')

@ -65,7 +65,6 @@ class PappySession(object):
self.delete_data_on_quit = False
self.ports = None
self.crypto = crypto.Crypto(sessconfig)
self.password = None
@defer.inlineCallbacks
def start(self):
@ -155,8 +154,14 @@ class PappySession(object):
@defer.inlineCallbacks
def decrypt(self):
yield self.crypto.decrypt_project()
# Attempt to decrypt project archive
if self.crypto.decrypt_project():
yield True
# Quit pappy on failure
else:
reactor.stop()
defer.returnValue(None)
@defer.inlineCallbacks
def cleanup(self, ignored=None):
for port in self.ports:
@ -175,7 +180,12 @@ def parse_args():
parser = argparse.ArgumentParser(description='An intercepting proxy for testing web applications.')
parser.add_argument('-l', '--lite', help='Run the proxy in "lite" mode', action='store_true')
parser.add_argument('-c', '--crypt', type=str, nargs='?', help='Start pappy in "crypto" mode, optionally supply a name for the encrypted project archive [CRYPT]')
try:
parser.add_argument('-c', '--crypt', type=str, nargs=1, help='Start pappy in "crypto" mode, must supply a name for the encrypted project archive [CRYPT]')
except:
print 'Must supply a project name: pappy -c <project_name>'
reactor.stop()
defer.returnValue(None)
args = parser.parse_args(sys.argv[1:])
settings = {}
@ -186,9 +196,8 @@ def parse_args():
settings['lite'] = False
if args.crypt:
settings['crypt'] = args.crypt
elif args.crypt == "":
settings['crypt'] = 'project.crypt'
# Convert from single-item list produced by argparse `nargs=1`
settings['crypt'] = args.crypt[0].encode('utf-8')
else:
settings['crypt'] = None

Loading…
Cancel
Save