def test_format_output(self): v = VaultLib('ansible') v.cipher_name = "TEST" sensitive_data = "ansible" data = v._format_output(sensitive_data) lines = data.split(b'\n') assert len(lines) > 1, "failed to properly add header" header = to_unicode(lines[0]) assert header.endswith(';TEST'), "header does end with cipher name" header_parts = header.split(';') assert len(header_parts) == 3, "header has the wrong number of parts" assert header_parts[0] == '$ANSIBLE_VAULT', "header does not start with $ANSIBLE_VAULT" assert header_parts[1] == v.b_version, "header version is incorrect" assert header_parts[2] == 'TEST', "header does end with cipher name"
def test_format_output(self): v = VaultLib('ansible') v.cipher_name = "TEST" sensitive_data = b"ansible" data = v._format_output(sensitive_data) lines = data.split(b'\n') assert len(lines) > 1, "failed to properly add header" header = to_bytes(lines[0]) assert header.endswith(b';TEST'), "header does end with cipher name" header_parts = header.split(b';') assert len(header_parts) == 3, "header has the wrong number of parts" assert header_parts[0] == b'$ANSIBLE_VAULT', "header does not start with $ANSIBLE_VAULT" assert header_parts[1] == v.b_version, "header version is incorrect" assert header_parts[2] == b'TEST', "header does end with cipher name"
def test_encrypt_decrypt_aes256_bad_hmac(self): # FIXME This test isn't working quite yet. raise SkipTest if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest v = VaultLib('test-vault-password') v.cipher_name = 'AES256' # plaintext = "Setec Astronomy" enc_data = '''$ANSIBLE_VAULT;1.1;AES256 33363965326261303234626463623963633531343539616138316433353830356566396130353436 3562643163366231316662386565383735653432386435610a306664636137376132643732393835 63383038383730306639353234326630666539346233376330303938323639306661313032396437 6233623062366136310a633866373936313238333730653739323461656662303864663666653563 3138''' b_data = to_bytes(enc_data, errors='strict', encoding='utf-8') b_data = v._split_header(b_data) foo = binascii.unhexlify(b_data) lines = foo.splitlines() # line 0 is salt, line 1 is hmac, line 2+ is ciphertext b_salt = lines[0] b_hmac = lines[1] b_ciphertext_data = b'\n'.join(lines[2:]) b_ciphertext = binascii.unhexlify(b_ciphertext_data) # b_orig_ciphertext = b_ciphertext[:] # now muck with the text # b_munged_ciphertext = b_ciphertext[:10] + b'\x00' + b_ciphertext[11:] # b_munged_ciphertext = b_ciphertext # assert b_orig_ciphertext != b_munged_ciphertext b_ciphertext_data = binascii.hexlify(b_ciphertext) b_payload = b'\n'.join([b_salt, b_hmac, b_ciphertext_data]) # reformat b_invalid_ciphertext = v._format_output(b_payload) # assert we throw an error v.decrypt(b_invalid_ciphertext)
class TestVaultLib(unittest.TestCase): def setUp(self): self.v = VaultLib('test-vault-password') def test_encrypt(self): plaintext = u'Some text to encrypt in a café' b_vaulttext = self.v.encrypt(plaintext) self.assertIsInstance(b_vaulttext, six.binary_type) b_header = b'$ANSIBLE_VAULT;1.1;AES256\n' self.assertEqual(b_vaulttext[:len(b_header)], b_header) def test_encrypt_bytes(self): plaintext = to_bytes(u'Some text to encrypt in a café') b_vaulttext = self.v.encrypt(plaintext) self.assertIsInstance(b_vaulttext, six.binary_type) b_header = b'$ANSIBLE_VAULT;1.1;AES256\n' self.assertEqual(b_vaulttext[:len(b_header)], b_header) def test_is_encrypted(self): self.assertFalse( self.v.is_encrypted(b"foobar"), msg="encryption check on plaintext yielded false positive") b_data = b"$ANSIBLE_VAULT;9.9;TEST\n%s" % hexlify(b"ansible") self.assertTrue(self.v.is_encrypted(b_data), msg="encryption check on headered text failed") def test_format_output(self): self.v.cipher_name = "TEST" b_ciphertext = b"ansible" b_vaulttext = self.v._format_output(b_ciphertext) b_lines = b_vaulttext.split(b'\n') self.assertGreater(len(b_lines), 1, msg="failed to properly add header") b_header = b_lines[0] self.assertTrue(b_header.endswith(b';TEST'), msg="header does not end with cipher name") b_header_parts = b_header.split(b';') self.assertEqual(len(b_header_parts), 3, msg="header has the wrong number of parts") self.assertEqual(b_header_parts[0], b'$ANSIBLE_VAULT', msg="header does not start with $ANSIBLE_VAULT") self.assertEqual(b_header_parts[1], self.v.b_version, msg="header version is incorrect") self.assertEqual(b_header_parts[2], b'TEST', msg="header does not end with cipher name") def test_split_header(self): b_vaulttext = b"$ANSIBLE_VAULT;9.9;TEST\nansible" b_ciphertext = self.v._split_header(b_vaulttext) b_lines = b_ciphertext.split(b'\n') self.assertEqual(b_lines[0], b"ansible", msg="Payload was not properly split from the header") self.assertEqual(self.v.cipher_name, u'TEST', msg="cipher name was not properly set") self.assertEqual(self.v.b_version, b"9.9", msg="version was not properly set") def test_encrypt_decrypt_aes(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES' self.v.b_password = b'ansible' # AES encryption code has been removed, so this is old output for # AES-encrypted 'foobar' with password 'ansible'. b_vaulttext = b'''$ANSIBLE_VAULT;1.1;AES 53616c7465645f5fc107ce1ef4d7b455e038a13b053225776458052f8f8f332d554809d3f150bfa3 fe3db930508b65e0ff5947e4386b79af8ab094017629590ef6ba486814cf70f8e4ab0ed0c7d2587e 786a5a15efeb787e1958cbdd480d076c ''' b_plaintext = self.v.decrypt(b_vaulttext) self.assertEqual(b_plaintext, b"foobar", msg="decryption failed") def test_encrypt_decrypt_aes256(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES256' plaintext = u"foobar" b_vaulttext = self.v.encrypt(plaintext) b_plaintext = self.v.decrypt(b_vaulttext) self.assertNotEqual(b_vaulttext, b"foobar", msg="encryption failed") self.assertEqual(b_plaintext, b"foobar", msg="decryption failed") def test_encrypt_decrypt_aes256_existing_vault(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES256' b_orig_plaintext = b"Setec Astronomy" vaulttext = u'''$ANSIBLE_VAULT;1.1;AES256 33363965326261303234626463623963633531343539616138316433353830356566396130353436 3562643163366231316662386565383735653432386435610a306664636137376132643732393835 63383038383730306639353234326630666539346233376330303938323639306661313032396437 6233623062366136310a633866373936313238333730653739323461656662303864663666653563 3138''' b_plaintext = self.v.decrypt(vaulttext) self.assertEqual(b_plaintext, b_plaintext, msg="decryption failed") b_vaulttext = to_bytes(vaulttext, encoding='ascii', errors='strict') b_plaintext = self.v.decrypt(b_vaulttext) self.assertEqual(b_plaintext, b_orig_plaintext, msg="decryption failed") def test_encrypt_decrypt_aes256_bad_hmac(self): # FIXME This test isn't working quite yet. raise SkipTest if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = 'AES256' # plaintext = "Setec Astronomy" enc_data = '''$ANSIBLE_VAULT;1.1;AES256 33363965326261303234626463623963633531343539616138316433353830356566396130353436 3562643163366231316662386565383735653432386435610a306664636137376132643732393835 63383038383730306639353234326630666539346233376330303938323639306661313032396437 6233623062366136310a633866373936313238333730653739323461656662303864663666653563 3138''' b_data = to_bytes(enc_data, errors='strict', encoding='utf-8') b_data = self.v._split_header(b_data) foo = binascii.unhexlify(b_data) lines = foo.splitlines() # line 0 is salt, line 1 is hmac, line 2+ is ciphertext b_salt = lines[0] b_hmac = lines[1] b_ciphertext_data = b'\n'.join(lines[2:]) b_ciphertext = binascii.unhexlify(b_ciphertext_data) # b_orig_ciphertext = b_ciphertext[:] # now muck with the text # b_munged_ciphertext = b_ciphertext[:10] + b'\x00' + b_ciphertext[11:] # b_munged_ciphertext = b_ciphertext # assert b_orig_ciphertext != b_munged_ciphertext b_ciphertext_data = binascii.hexlify(b_ciphertext) b_payload = b'\n'.join([b_salt, b_hmac, b_ciphertext_data]) # reformat b_invalid_ciphertext = self.v._format_output(b_payload) # assert we throw an error self.v.decrypt(b_invalid_ciphertext) def test_encrypt_encrypted(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES' b_vaulttext = b"$ANSIBLE_VAULT;9.9;TEST\n%s" % hexlify(b"ansible") vaulttext = to_text(b_vaulttext, errors='strict') self.assertRaises(errors.AnsibleError, self.v.encrypt, b_vaulttext) self.assertRaises(errors.AnsibleError, self.v.encrypt, vaulttext) def test_decrypt_decrypted(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest plaintext = u"ansible" self.assertRaises(errors.AnsibleError, self.v.decrypt, plaintext) b_plaintext = b"ansible" self.assertRaises(errors.AnsibleError, self.v.decrypt, b_plaintext) def test_cipher_not_set(self): # not setting the cipher should default to AES256 if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest plaintext = u"ansible" self.v.encrypt(plaintext) self.assertEquals(self.v.cipher_name, "AES256")
class TestVaultLib(unittest.TestCase): def setUp(self): self.v = VaultLib('test-vault-password') def test_encrypt(self): plaintext = u'Some text to encrypt in a café' b_vaulttext = self.v.encrypt(plaintext) self.assertIsInstance(b_vaulttext, six.binary_type) b_header = b'$ANSIBLE_VAULT;1.1;AES256\n' self.assertEqual(b_vaulttext[:len(b_header)], b_header) def test_encrypt_bytes(self): plaintext = to_bytes(u'Some text to encrypt in a café') b_vaulttext = self.v.encrypt(plaintext) self.assertIsInstance(b_vaulttext, six.binary_type) b_header = b'$ANSIBLE_VAULT;1.1;AES256\n' self.assertEqual(b_vaulttext[:len(b_header)], b_header) def test_is_encrypted(self): self.assertFalse(self.v.is_encrypted(b"foobar"), msg="encryption check on plaintext yielded false positive") b_data = b"$ANSIBLE_VAULT;9.9;TEST\n%s" % hexlify(b"ansible") self.assertTrue(self.v.is_encrypted(b_data), msg="encryption check on headered text failed") def test_format_output(self): self.v.cipher_name = "TEST" b_ciphertext = b"ansible" b_vaulttext = self.v._format_output(b_ciphertext) b_lines = b_vaulttext.split(b'\n') self.assertGreater(len(b_lines), 1, msg="failed to properly add header") b_header = b_lines[0] self.assertTrue(b_header.endswith(b';TEST'), msg="header does not end with cipher name") b_header_parts = b_header.split(b';') self.assertEqual(len(b_header_parts), 3, msg="header has the wrong number of parts") self.assertEqual(b_header_parts[0], b'$ANSIBLE_VAULT', msg="header does not start with $ANSIBLE_VAULT") self.assertEqual(b_header_parts[1], self.v.b_version, msg="header version is incorrect") self.assertEqual(b_header_parts[2], b'TEST', msg="header does not end with cipher name") def test_split_header(self): b_vaulttext = b"$ANSIBLE_VAULT;9.9;TEST\nansible" b_ciphertext = self.v._split_header(b_vaulttext) b_lines = b_ciphertext.split(b'\n') self.assertEqual(b_lines[0], b"ansible", msg="Payload was not properly split from the header") self.assertEqual(self.v.cipher_name, u'TEST', msg="cipher name was not properly set") self.assertEqual(self.v.b_version, b"9.9", msg="version was not properly set") def test_encrypt_decrypt_aes(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES' self.v.b_password = b'ansible' # AES encryption code has been removed, so this is old output for # AES-encrypted 'foobar' with password 'ansible'. b_vaulttext = b'''$ANSIBLE_VAULT;1.1;AES 53616c7465645f5fc107ce1ef4d7b455e038a13b053225776458052f8f8f332d554809d3f150bfa3 fe3db930508b65e0ff5947e4386b79af8ab094017629590ef6ba486814cf70f8e4ab0ed0c7d2587e 786a5a15efeb787e1958cbdd480d076c ''' b_plaintext = self.v.decrypt(b_vaulttext) self.assertEqual(b_plaintext, b"foobar", msg="decryption failed") def test_encrypt_decrypt_aes256(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES256' plaintext = u"foobar" b_vaulttext = self.v.encrypt(plaintext) b_plaintext = self.v.decrypt(b_vaulttext) self.assertNotEqual(b_vaulttext, b"foobar", msg="encryption failed") self.assertEqual(b_plaintext, b"foobar", msg="decryption failed") def test_encrypt_decrypt_aes256_existing_vault(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES256' b_orig_plaintext = b"Setec Astronomy" vaulttext = u'''$ANSIBLE_VAULT;1.1;AES256 33363965326261303234626463623963633531343539616138316433353830356566396130353436 3562643163366231316662386565383735653432386435610a306664636137376132643732393835 63383038383730306639353234326630666539346233376330303938323639306661313032396437 6233623062366136310a633866373936313238333730653739323461656662303864663666653563 3138''' b_plaintext = self.v.decrypt(vaulttext) self.assertEqual(b_plaintext, b_plaintext, msg="decryption failed") b_vaulttext = to_bytes(vaulttext, encoding='ascii', errors='strict') b_plaintext = self.v.decrypt(b_vaulttext) self.assertEqual(b_plaintext, b_orig_plaintext, msg="decryption failed") def test_encrypt_decrypt_aes256_bad_hmac(self): # FIXME This test isn't working quite yet. raise SkipTest if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = 'AES256' # plaintext = "Setec Astronomy" enc_data = '''$ANSIBLE_VAULT;1.1;AES256 33363965326261303234626463623963633531343539616138316433353830356566396130353436 3562643163366231316662386565383735653432386435610a306664636137376132643732393835 63383038383730306639353234326630666539346233376330303938323639306661313032396437 6233623062366136310a633866373936313238333730653739323461656662303864663666653563 3138''' b_data = to_bytes(enc_data, errors='strict', encoding='utf-8') b_data = self.v._split_header(b_data) foo = binascii.unhexlify(b_data) lines = foo.splitlines() # line 0 is salt, line 1 is hmac, line 2+ is ciphertext b_salt = lines[0] b_hmac = lines[1] b_ciphertext_data = b'\n'.join(lines[2:]) b_ciphertext = binascii.unhexlify(b_ciphertext_data) # b_orig_ciphertext = b_ciphertext[:] # now muck with the text # b_munged_ciphertext = b_ciphertext[:10] + b'\x00' + b_ciphertext[11:] # b_munged_ciphertext = b_ciphertext # assert b_orig_ciphertext != b_munged_ciphertext b_ciphertext_data = binascii.hexlify(b_ciphertext) b_payload = b'\n'.join([b_salt, b_hmac, b_ciphertext_data]) # reformat b_invalid_ciphertext = self.v._format_output(b_payload) # assert we throw an error self.v.decrypt(b_invalid_ciphertext) def test_encrypt_encrypted(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest self.v.cipher_name = u'AES' b_vaulttext = b"$ANSIBLE_VAULT;9.9;TEST\n%s" % hexlify(b"ansible") vaulttext = to_text(b_vaulttext, errors='strict') self.assertRaises(errors.AnsibleError, self.v.encrypt, b_vaulttext) self.assertRaises(errors.AnsibleError, self.v.encrypt, vaulttext) def test_decrypt_decrypted(self): if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest plaintext = u"ansible" self.assertRaises(errors.AnsibleError, self.v.decrypt, plaintext) b_plaintext = b"ansible" self.assertRaises(errors.AnsibleError, self.v.decrypt, b_plaintext) def test_cipher_not_set(self): # not setting the cipher should default to AES256 if not HAS_AES or not HAS_COUNTER or not HAS_PBKDF2: raise SkipTest plaintext = u"ansible" self.v.encrypt(plaintext) self.assertEquals(self.v.cipher_name, "AES256")