python-tuf/tests/test_keys.py
vladdd 3fd6839c2b Add test case for keys.formats_rsakey_from_pem()
Add test_formats_rsakey_from_pem() test case and test conditions for improperly formatted PEM.
Add test condition to verify trailing whitespace is removed and matches the expected PEM format generated
internally.  Public PEMs generated externally (with the expected trailing newline) was not previously considered.
2014-07-18 15:24:10 -04:00

287 lines
9.8 KiB
Python
Executable file

#!/usr/bin/env python
"""
<Program Name>
test_keys.py
<Author>
Vladimir Diaz
<Started>
October 10, 2013.
<Copyright>
See LICENSE for licensing information.
<Purpose>
Test cases for test_keys.py.
TODO: test case for ed25519 key generation and refactor.
"""
# Help with Python 3 compatibility, where the print statement is a function, an
# implicit relative import is invalid, and the '/' operator performs true
# division. Example: print 'hello world' raises a 'SyntaxError' exception.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import unittest
import logging
import tuf
import tuf.log
import tuf.formats
import tuf.keys
logger = logging.getLogger('tuf.test_keys')
KEYS = tuf.keys
FORMAT_ERROR_MSG = 'tuf.FormatError was raised! Check object\'s format.'
DATA = 'SOME DATA REQUIRING AUTHENTICITY.'
class TestKeys(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.rsakey_dict = KEYS.generate_rsa_key()
cls.ed25519key_dict = KEYS.generate_ed25519_key()
def test_generate_rsa_key(self):
_rsakey_dict = KEYS.generate_rsa_key()
# Check if the format of the object returned by generate() corresponds
# to RSAKEY_SCHEMA format.
self.assertEqual(None, tuf.formats.RSAKEY_SCHEMA.check_match(_rsakey_dict),
FORMAT_ERROR_MSG)
# Passing a bit value that is <2048 to generate() - should raise
# 'tuf.FormatError'.
self.assertRaises(tuf.FormatError, KEYS.generate_rsa_key, 555)
# Passing a string instead of integer for a bit value.
self.assertRaises(tuf.FormatError, KEYS.generate_rsa_key, 'bits')
# NOTE if random bit value >=2048 (not 4096) is passed generate(bits)
# does not raise any errors and returns a valid key.
self.assertTrue(tuf.formats.RSAKEY_SCHEMA.matches(KEYS.generate_rsa_key(2048)))
self.assertTrue(tuf.formats.RSAKEY_SCHEMA.matches(KEYS.generate_rsa_key(4096)))
def test_format_keyval_to_metadata(self):
keyvalue = self.rsakey_dict['keyval']
keytype = self.rsakey_dict['keytype']
key_meta = KEYS.format_keyval_to_metadata(keytype, keyvalue)
# Check if the format of the object returned by this function corresponds
# to KEY_SCHEMA format.
self.assertEqual(None,
tuf.formats.KEY_SCHEMA.check_match(key_meta),
FORMAT_ERROR_MSG)
key_meta = KEYS.format_keyval_to_metadata(keytype, keyvalue, private=True)
# Check if the format of the object returned by this function corresponds
# to KEY_SCHEMA format.
self.assertEqual(None, tuf.formats.KEY_SCHEMA.check_match(key_meta),
FORMAT_ERROR_MSG)
# Supplying a 'bad' keyvalue.
self.assertRaises(tuf.FormatError, KEYS.format_keyval_to_metadata,
'bad_keytype', keyvalue)
public = keyvalue['public']
del keyvalue['public']
self.assertRaises(tuf.FormatError, KEYS.format_keyval_to_metadata,
keytype, keyvalue)
keyvalue['public'] = public
def test_format_rsakey_from_pem(self):
pem = self.rsakey_dict['keyval']['public']
rsa_key = KEYS.format_rsakey_from_pem(pem)
# Check if the format of the object returned by this function corresponds
# to 'tuf.formats.RSAKEY_SCHEMA' format.
self.assertTrue(tuf.formats.RSAKEY_SCHEMA.matches(rsa_key))
# Verify whitespace is stripped.
self.assertEqual(rsa_key, KEYS.format_rsakey_from_pem(pem + '\n'))
# Supplying a 'bad_pem' argument.
self.assertRaises(tuf.FormatError, KEYS.format_rsakey_from_pem, 'bad_pem')
# Supplying an improperly formatted PEM.
# Strip the PEM header and footer.
pem_header = '-----BEGIN PUBLIC KEY-----'
pem_footer= '-----END PUBLIC KEY-----'
self.assertRaises(tuf.FormatError, KEYS.format_rsakey_from_pem,
pem[:len(pem_footer)])
self.assertRaises(tuf.FormatError, KEYS.format_rsakey_from_pem,
pem[len(pem_header):])
def test_format_metadata_to_key(self):
# Reconfiguring rsakey_dict to conform to KEY_SCHEMA
# i.e. {keytype: 'rsa', keyval: {public: pub_key, private: priv_key}}
keyid = self.rsakey_dict['keyid']
del self.rsakey_dict['keyid']
rsakey_dict_from_meta = KEYS.format_metadata_to_key(self.rsakey_dict)
# Check if the format of the object returned by this function corresponds
# to RSAKEY_SCHEMA format.
self.assertEqual(None,
tuf.formats.RSAKEY_SCHEMA.check_match(rsakey_dict_from_meta),
FORMAT_ERROR_MSG)
self.rsakey_dict['keyid'] = keyid
# Supplying a wrong number of arguments.
self.assertRaises(TypeError, KEYS.format_metadata_to_key)
args = (self.rsakey_dict, self.rsakey_dict)
self.assertRaises(TypeError, KEYS.format_metadata_to_key, *args)
# Supplying a malformed argument to the function - should get FormatError
keyval = self.rsakey_dict['keyval']
del self.rsakey_dict['keyval']
self.assertRaises(tuf.FormatError, KEYS.format_metadata_to_key,
self.rsakey_dict)
self.rsakey_dict['keyval'] = keyval
def test_helper_get_keyid(self):
keytype = self.rsakey_dict['keytype']
keyvalue = self.rsakey_dict['keyval']
# Check format of 'keytype'.
self.assertEqual(None, tuf.formats.KEYTYPE_SCHEMA.check_match(keytype),
FORMAT_ERROR_MSG)
# Check format of 'keyvalue'.
self.assertEqual(None, tuf.formats.KEYVAL_SCHEMA.check_match(keyvalue),
FORMAT_ERROR_MSG)
keyid = KEYS._get_keyid(keytype, keyvalue)
# Check format of 'keyid' - the output of '_get_keyid()' function.
self.assertEqual(None, tuf.formats.KEYID_SCHEMA.check_match(keyid),
FORMAT_ERROR_MSG)
def test_create_signature(self):
# Creating a signature for 'DATA'.
rsa_signature = KEYS.create_signature(self.rsakey_dict, DATA)
ed25519_signature = KEYS.create_signature(self.ed25519key_dict, DATA)
# Check format of output.
self.assertEqual(None,
tuf.formats.SIGNATURE_SCHEMA.check_match(rsa_signature),
FORMAT_ERROR_MSG)
self.assertEqual(None,
tuf.formats.SIGNATURE_SCHEMA.check_match(ed25519_signature),
FORMAT_ERROR_MSG)
# Removing private key from 'rsakey_dict' - should raise a TypeError.
private = self.rsakey_dict['keyval']['private']
self.rsakey_dict['keyval']['private'] = ''
args = (self.rsakey_dict, DATA)
self.assertRaises(TypeError, KEYS.create_signature, *args)
# Supplying an incorrect number of arguments.
self.assertRaises(TypeError, KEYS.create_signature)
self.rsakey_dict['keyval']['private'] = private
def test_verify_signature(self):
# Creating a signature of 'DATA' to be verified.
rsa_signature = KEYS.create_signature(self.rsakey_dict, DATA)
ed25519_signature = KEYS.create_signature(self.ed25519key_dict, DATA)
# Verifying the 'signature' of 'DATA'.
verified = KEYS.verify_signature(self.rsakey_dict, rsa_signature, DATA)
self.assertTrue(verified, "Incorrect signature.")
# Verifying the 'ed25519_signature' of 'DATA'.
verified = KEYS.verify_signature(self.ed25519key_dict, ed25519_signature, DATA)
self.assertTrue(verified, "Incorrect signature.")
# Testing an invalid 'rsa_signature'. Same 'rsa_signature' is passed, with
# 'DATA' different than the original 'DATA' that was used
# in creating the 'rsa_signature'. Function should return 'False'.
# Modifying 'DATA'.
_DATA = '1111' + DATA + '1111'
# Verifying the 'signature' of modified '_DATA'.
verified = KEYS.verify_signature(self.rsakey_dict, rsa_signature, _DATA)
self.assertFalse(verified,
'Returned \'True\' on an incorrect signature.')
# Modifying 'signature' to pass an incorrect method since only
# 'PyCrypto-PKCS#1 PSS' is accepted.
rsa_signature['method'] = 'Biff'
args = (self.rsakey_dict, rsa_signature, DATA)
self.assertRaises(tuf.UnknownMethodError, KEYS.verify_signature, *args)
# Passing incorrect number of arguments.
self.assertRaises(TypeError, KEYS.verify_signature)
def test_create_rsa_encrypted_pem(self):
# Test valid arguments.
private = self.rsakey_dict['keyval']['private']
passphrase = 'secret'
encrypted_pem = KEYS.create_rsa_encrypted_pem(private, passphrase)
self.assertTrue(tuf.formats.PEMRSA_SCHEMA.matches(encrypted_pem))
# Test improperly formatted arguments.
self.assertRaises(tuf.FormatError, KEYS.create_rsa_encrypted_pem,
8, passphrase)
self.assertRaises(tuf.FormatError, KEYS.create_rsa_encrypted_pem,
private, 8)
# Test for missing required library.
KEYS._RSA_CRYPTO_LIBRARY = 'invalid'
self.assertRaises(tuf.UnsupportedLibraryError, KEYS.create_rsa_encrypted_pem,
private, passphrase)
KEYS._RSA_CRYPTO_LIBRARY = 'pycrypto'
def test_decrypt_key(self):
# Test valid arguments.
passphrase = 'secret'
encrypted_key = KEYS.encrypt_key(self.rsakey_dict, passphrase).encode('utf-8')
decrypted_key = KEYS.decrypt_key(encrypted_key, passphrase)
self.assertTrue(tuf.formats.ANYKEY_SCHEMA.matches(decrypted_key))
# Test improperly formatted arguments.
self.assertRaises(tuf.FormatError, KEYS.decrypt_key,
8, passphrase)
self.assertRaises(tuf.FormatError, KEYS.decrypt_key,
encrypted_key, 8)
# Test for missing required library.
KEYS._GENERAL_CRYPTO_LIBRARY = 'invalid'
self.assertRaises(tuf.UnsupportedLibraryError, KEYS.decrypt_key,
encrypted_key, passphrase)
KEYS._GENERAL_CRYPTO_LIBRARY = 'pycrypto'
# Run the unit tests.
if __name__ == '__main__':
unittest.main()