def test_01_encrypt_decrypt(self): """ Test basic encryption and decryption functionality using a random master key. """ plaintext = "FooBar123" secret_key = generate_master_key() s = Secret(plaintext=plaintext) s.encrypt(secret_key) # Ensure plaintext is deleted upon encryption self.assertIsNone(s.plaintext, "Plaintext must be None after encrypting.") # Enforce minimum ciphertext length self.assertGreaterEqual(len(s.ciphertext), 80, "Ciphertext must be at least 80 bytes (16B IV + 64B+ ciphertext") # Ensure proper hashing algorithm is used hasher, iterations, salt, sha256 = s.hash.split('$') self.assertEqual(hasher, 'pbkdf2_sha256', "Hashing algorithm has been modified to: {}".format(hasher)) self.assertGreaterEqual(int(iterations), SecretValidationHasher.iterations, "Insufficient iteration count ({}) for hash".format(iterations)) self.assertGreaterEqual(len(salt), 12, "Hash salt is too short ({} chars)".format(len(salt))) # Test hash validation self.assertTrue(s.validate(plaintext), "Plaintext does not validate against the generated hash") self.assertFalse(s.validate(""), "Empty plaintext validated against hash") self.assertFalse(s.validate("Invalid plaintext"), "Invalid plaintext validated against hash") # Test decryption s.decrypt(secret_key) self.assertEqual(plaintext, s.plaintext, "Decrypting Secret returned incorrect plaintext")
def test_04_master_key_retrieval(self): """ Test the decryption of a master key using the user's private key. """ master_key = generate_master_key() alice_uk = UserKey(user=User.objects.get(username='******'), public_key=self.TEST_KEYS['alice_public']) alice_uk.activate(master_key) retrieved_master_key = alice_uk.get_master_key(self.TEST_KEYS['alice_private']) self.assertEqual(master_key, retrieved_master_key, "Master key retrieval failed with correct private key")
def test_02_activate(self): """ Validate the activation of a UserKey. """ master_key = generate_master_key() alice_uk = UserKey(user=User.objects.get(username='******'), public_key=self.TEST_KEYS['alice_public']) self.assertFalse(alice_uk.is_active(), "Inactive UserKey is_active() did not return False") alice_uk.activate(master_key) self.assertTrue(alice_uk.is_active(), "ActiveUserKey is_active() did not return True")
def test_05_invalid_private_key(self): """ Ensure that an exception is raised when attempting to retrieve a secret key using an invalid private key. """ secret_key = generate_master_key() secret_key_cipher = encrypt_master_key(secret_key, self.TEST_KEYS['alice_public']) try: decrypted_secret_key = decrypt_master_key(secret_key_cipher, self.TEST_KEYS['bob_private']) self.fail("Decrypting secret key from Alice's UserKey using Bob's private key did not fail") except ValueError: pass
def test_04_master_key_retrieval(self): """ Test the decryption of a master key using the user's private key. """ master_key = generate_master_key() alice_uk = UserKey(user=User.objects.get(username='******'), public_key=self.TEST_KEYS['alice_public']) alice_uk.activate(master_key) retrieved_master_key = alice_uk.get_master_key( self.TEST_KEYS['alice_private']) self.assertEqual( master_key, retrieved_master_key, "Master key retrieval failed with correct private key")
def test_05_invalid_private_key(self): """ Ensure that an exception is raised when attempting to retrieve a secret key using an invalid private key. """ secret_key = generate_master_key() secret_key_cipher = encrypt_master_key(secret_key, self.TEST_KEYS['alice_public']) try: decrypted_secret_key = decrypt_master_key( secret_key_cipher, self.TEST_KEYS['bob_private']) self.fail( "Decrypting secret key from Alice's UserKey using Bob's private key did not fail" ) except ValueError: pass
def test_02_ciphertext_uniqueness(self): """ Generate 50 Secrets using the same plaintext and check for duplicate IVs or payloads. """ plaintext = "1234567890abcdef" secret_key = generate_master_key() ivs = [] ciphertexts = [] for i in range(1, 51): s = Secret(plaintext=plaintext) s.encrypt(secret_key) ivs.append(s.ciphertext[0:16]) ciphertexts.append(s.ciphertext[16:32]) duplicate_ivs = [i for i, x in enumerate(ivs) if ivs.count(x) > 1] self.assertEqual(duplicate_ivs, [], "One or more duplicate IVs found!") duplicate_ciphertexts = [i for i, x in enumerate(ciphertexts) if ciphertexts.count(x) > 1] self.assertEqual(duplicate_ciphertexts, [], "One or more duplicate ciphertexts (first blocks) found!")
def test_01_encrypt_decrypt(self): """ Test basic encryption and decryption functionality using a random master key. """ plaintext = "FooBar123" secret_key = generate_master_key() s = Secret(plaintext=plaintext) s.encrypt(secret_key) # Ensure plaintext is deleted upon encryption self.assertIsNone(s.plaintext, "Plaintext must be None after encrypting.") # Enforce minimum ciphertext length self.assertGreaterEqual( len(s.ciphertext), 80, "Ciphertext must be at least 80 bytes (16B IV + 64B+ ciphertext") # Ensure proper hashing algorithm is used hasher, iterations, salt, sha256 = s.hash.split('$') self.assertEqual( hasher, 'pbkdf2_sha256', "Hashing algorithm has been modified to: {}".format(hasher)) self.assertGreaterEqual( int(iterations), SecretValidationHasher.iterations, "Insufficient iteration count ({}) for hash".format(iterations)) self.assertGreaterEqual( len(salt), 12, "Hash salt is too short ({} chars)".format(len(salt))) # Test hash validation self.assertTrue( s.validate(plaintext), "Plaintext does not validate against the generated hash") self.assertFalse(s.validate(""), "Empty plaintext validated against hash") self.assertFalse(s.validate("Invalid plaintext"), "Invalid plaintext validated against hash") # Test decryption s.decrypt(secret_key) self.assertEqual(plaintext, s.plaintext, "Decrypting Secret returned incorrect plaintext")
def test_02_ciphertext_uniqueness(self): """ Generate 50 Secrets using the same plaintext and check for duplicate IVs or payloads. """ plaintext = "1234567890abcdef" secret_key = generate_master_key() ivs = [] ciphertexts = [] for i in range(1, 51): s = Secret(plaintext=plaintext) s.encrypt(secret_key) ivs.append(s.ciphertext[0:16]) ciphertexts.append(s.ciphertext[16:32]) duplicate_ivs = [i for i, x in enumerate(ivs) if ivs.count(x) > 1] self.assertEqual(duplicate_ivs, [], "One or more duplicate IVs found!") duplicate_ciphertexts = [ i for i, x in enumerate(ciphertexts) if ciphertexts.count(x) > 1 ] self.assertEqual( duplicate_ciphertexts, [], "One or more duplicate ciphertexts (first blocks) found!")