def test_empty(self): """ Test encrypt/decrypt behavior when using empty/None values. """ self.assertNotEquals("", engine.encrypt(""), "Expected empty strings to actually be encryptable.") self.assertIs(None, engine.encrypt(None)) self.assertEquals(None, engine.decrypt("")) self.assertIs(None, engine.decrypt(None))
def create_key_validation_payload(key=None): """ Utility function to create the encrypted payload that we will late use for key validation. TODO: Consider replacing with something smarter. HMAC? """ some_bytes = get_random_bytes(256) return engine.encrypt(some_bytes, key=key)
def test_encrypt_decrypt(self): """ Basic encryption/decryption tests. """ # 012345678901234567890123456789012345678901234567890123456789 # 1 2 3 4 5 6 a = "The slow dog jumped over." b = "The slow dog jumped over the brown fox." c = "The slow dog jumped over the brown fox and the roosters too." a_c = engine.encrypt(a) self.assertIsInstance(a_c, str) self.assertEquals(a, engine.decrypt(a_c)) b_c = engine.encrypt(b) self.assertEquals(b, engine.decrypt(b_c)) c_c = engine.encrypt(c) self.assertEquals(c, engine.decrypt(c_c))
def replace_key(new_key, force=False): """ Replaces the database key. If there are encrypted contents in the database, you must specify force=True which will *reencrypt* the database contents with the new key. This is dangerous. !!!! BACKUP FIRST !!!! !!!! STOP WEB SERVER !!!! :param new_key: The new encryption key. :raise ensconce.exc.CryptoNotInitialized: If the engine has not been initialized (with the correct current key). :raise ensconce.exc.MissingKeyMetadata: If the metadata row does not exist yet. :raise ensconce.exc.MultipleKeyMetadata: If there are multiple metadata rows. :raise ensconce.exc.UnconfiguredModel: If we can't create an SA session. :raise ensconce.exc.DatabaseAlreadyEncrypted: If database has encrypted data and `force` param is not `True`. """ assert isinstance(new_key, MasterKey) if not state.initialized: raise exc.CryptoNotInitialized() if meta.Session is None: raise exc.UnconfiguredModel() if has_encrypted_data() and not force: raise exc.DatabaseAlreadyEncrypted( "Database has existing encrypted data (must specify force to reencrypt existing data)." ) session = meta.Session() assert session.autocommit == False with state.key_lock: try: key_info = session.query(model.KeyMetadata).one() pass_t = model.passwords_table # Re-encrypt all of the passwords with the new key. for pw in session.query(model.Password).filter(and_(pass_t.c.password != None, pass_t.c.password != "")): # Important: set the *encrypted* password here (not password_decrypted) pw.password = engine.encrypt(pw.password_decrypted, key=new_key) session.flush() ph_t = model.password_history_table for pwh in session.query(model.PasswordHistory).filter( and_(ph_t.c.password != None, ph_t.c.password != "") ): # Important: set the *encrypted* password here (not password_decrypted) pwh.password = engine.encrypt(pwh.password_decrypted, key=new_key) session.flush() # Re-encrypt all of the notes fields for resources resources_t = model.resources_table for rsc in session.query(model.Resource).filter( and_(resources_t.c.notes != None, resources_t.c.notes != "") ): # Important: set the *encrypted* password here (not password_decrypted) rsc.notes = engine.encrypt(rsc.notes_decrypted, key=new_key) session.flush() key_info.validation = create_key_validation_payload(key=new_key) session.flush() state.secret_key = new_key except NoResultFound: raise exc.MissingKeyMetadata("No key metadata found; initialize key metadata before replacing key.") except MultipleResultsFound: raise exc.CryptoError("Multiple key metadata rows are not supported.") except: session.rollback() log.exception("Error replacing key; rolling back transaction.") raise else: session.commit()
def test_binary(self): """ Test encrypt/decrypt of non-ascii data. """ data = os.urandom(100) # 100 bytes of binary data data_c = engine.encrypt(data) self.assertEquals(data, engine.decrypt(data_c))
def notes_decrypted(self, cleartext): self.notes = engine.encrypt(cleartext)
def password_decrypted(self, cleartext): self.password = engine.encrypt(cleartext)