def test_has_encrypted_data_nulls(self): """ Ensure correct detection of encrypted data in db (null cols). """ # By default (with default data) this will be true self.assertTrue(util.has_encrypted_data()) session = meta.Session() session.execute(model.passwords_table.update().values(password=None)) session.flush() self.assertTrue(util.has_encrypted_data()) session.execute(model.resources_table.update().values(notes=None)) session.flush() self.assertFalse(util.has_encrypted_data(), "With all password and notes field set to NULL, there should be no encrypted data in DB.")
def init_crypto(options): """ Interactive target to initialize the database with a new crypto passphrase. """ print "Initializing crypto for an empty database." if crypto_util.has_encrypted_data(): raise BuildFailure("Database has existing encrypted contents; use the 'rekey' target instead.") passphrase = raw_input("Passphrase: ") print "The database will be initialized with the passphrase between the arrows: --->%s<---" % passphrase print "The MD5 of the passphrase you entered is: %s" % hashlib.md5(passphrase).hexdigest() confirm = raw_input("Type 'YES' to confirm passphrase and MD5 are correct: ") if confirm != 'YES': raise ValueError("You must enter 'YES' to proceed.") salt = get_random_bytes(16) key = crypto_util.derive_key(passphrase=passphrase, salt=salt) crypto_util.initialize_key_metadata(key=key, salt=salt, force_overwrite=False) print "Database key metadata has been initialized. Your application is ready for use." if config.get('debug'): print "The new key is: %s%s" % (binascii.hexlify(key.encryption_key), binascii.hexlify(key.signing_key)) print "*************************************************************" print "IMPORTANT" print "Make sure your database master passphrase is stored somewhere" print "outside of Ensconce." print "" print "There is no recovery mechanism for this passphrase (or for " print "your database, should you lose it.)" print "*************************************************************"
def rekey(options): """ Interactive target to change the passphrase for the database. """ info("This is an EXTREMELY DANGEROUS activity.") info("Backup your database first.") curr_passphrase = raw_input("Current passphrase: ") crypto_util.configure_crypto_state(curr_passphrase) new_passphrase = raw_input("New passphrase: ") confirm = raw_input("MD5 of passphrase is %s (type \"YES\" to confirm): " % hashlib.md5(new_passphrase).hexdigest()) if confirm != 'YES': raise ValueError("You must enter 'YES' to proceed.") if crypto_util.has_encrypted_data(): confirm = raw_input("There is existing encrypted data in the database. Type 'REKEY' to proceed with re-encryption: ") if confirm != 'REKEY': raise ValueError("You must enter 'REKEY' to proceed.") # Use the same salt as previous key new_key = crypto_util.derive_configured_key(new_passphrase) crypto_util.replace_key(new_key=new_key, force=True) info("Re-encryption completed successfully.") if config.get('debug'): print "The new key is: %s%s" % (binascii.hexlify(new_key.encryption_key), binascii.hexlify(new_key.signing_key))
def test_replace_key(self): """ Test replacing the key (and re-encrypting the database). """ self.assertTrue(util.has_encrypted_data()) # Create a new key ekey = hashlib.sha256('new-encrypt').digest() skey = hashlib.sha256('new-sign').digest() new_key = MasterKey(encryption_key=ekey, signing_key=skey) with self.assertRaises(exc.DatabaseAlreadyEncrypted): util.replace_key(new_key) # Check existing passwords for an arbitrary user for (i,pw) in enumerate(self.data.resources['host1.example.com'].passwords.order_by('username')): self.assertEquals('password{0}'.format(i), pw.password_decrypted) util.replace_key(new_key, force=True) # The replace_key functions updates the global state, so this should work: for (i,pw) in enumerate(self.data.resources['host1.example.com'].passwords.order_by('username')): self.assertEquals('password{0}'.format(i), pw.password_decrypted) # But using the old key should, of course, now fail: for (i,pw) in enumerate(self.data.resources['host1.example.com'].passwords.order_by('username')): with self.assertRaises(exc.CryptoAuthenticationFailed): engine.decrypt(pw.password, key=self.SECRET_KEY)
def test_has_encrypted_data_basic(self): """ Ensure correct detection of encrypted data in db (basic). """ # By default (with default data) this will be true self.assertTrue(util.has_encrypted_data()) session = meta.Session() session.execute(model.passwords_table.delete()) session.flush() # Should be true still ... self.assertTrue(util.has_encrypted_data()) session.execute(model.resources_table.delete()) session.flush() # But not anymore. self.assertFalse(util.has_encrypted_data())