diff --git a/tests/test_keys.py b/tests/test_keys.py index 5e8b1c12..e4a6cb0e 100755 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -98,6 +98,31 @@ def test_format_keyval_to_metadata(self): 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):]) diff --git a/tuf/keys.py b/tuf/keys.py index c3af4d66..acc44247 100755 --- a/tuf/keys.py +++ b/tuf/keys.py @@ -977,7 +977,7 @@ def format_rsakey_from_pem(pem): {'keytype': 'rsa', 'keyid': keyid, - 'keyval': {'public': '-----BEGIN RSA PUBLIC KEY----- ...', + 'keyval': {'public': '-----BEGIN PUBLIC KEY----- ...', 'private': ''}} The public portion of the RSA key is a string in PEM format. @@ -997,7 +997,9 @@ def format_rsakey_from_pem(pem): tuf.FormatError, if 'pem' is improperly formatted. - None. + Only the public portion of the PEM is extracted. Leading or trailing + whitespace is not included in the PEM string stored in the rsakey object + returned. A dictionary containing the RSA keys and other identifying information. @@ -1010,16 +1012,43 @@ def format_rsakey_from_pem(pem): # Raise 'tuf.FormatError' if the check fails. tuf.formats.PEMRSA_SCHEMA.check_match(pem) - # Ensure the PEM string starts with the required number of dashes. Although - # a simple validation of 'pem' is performed here, a fully valid PEM string is - # needed to successfully verify signatures. - if not pem.startswith('-----'): - raise tuf.FormatError('The PEM string argument is improperly formatted.') + # Ensure the PEM string has a valid header and footer. Although a simple + # validation of 'pem' is performed here, a fully valid PEM string is + # needed to later successfully verify signatures. + pem_header = '-----BEGIN PUBLIC KEY-----' + pem_footer = '-----END PUBLIC KEY-----' + header_start = 0 + footer_start = 0 + + # Raise error message if the expected header or footer is not found in 'pem'. + try: + header_start = pem.index(pem_header) + except ValueError: + message = \ + 'Required PEM header ' + repr(pem_header) + '\n not found in PEM' + \ + ' string: ' + repr(pem) + raise tuf.FormatError(message) + + try: + # Search for 'pem_footer' after the PEM header. + footer_start = pem.index(pem_footer, header_start + len(pem_header)) + + except ValueError: + message = \ + 'Required PEM footer ' + repr(pem_footer) + '\n not found in PEM' + \ + ' string ' + repr(pem) + raise tuf.FormatError(message) + + # Extract only the public portion of 'pem'. Leading or trailing whitespace + # is not included. + public_pem = pem[header_start:footer_start + len(pem_footer)] + + # Begin building the RSA key dictionary. rsakey_dict = {} keytype = 'rsa' - public = pem + public = public_pem # Generate the keyid of the RSA key. 'key_value' corresponds to the # 'keyval' entry of the 'RSAKEY_SCHEMA' dictionary. The private key