Skip to content

Commit

Permalink
Merge pull request #267 from joshuagl/joshuagl/ecdsa-issue-239
Browse files Browse the repository at this point in the history
Better distinguish between keytype and scheme for ECDSA keys
  • Loading branch information
lukpueh authored Aug 20, 2020
2 parents 708e992 + 3cd47e7 commit 876772c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 33 deletions.
5 changes: 3 additions & 2 deletions securesystemslib/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@

# Supported securesystemslib key types.
KEYTYPE_SCHEMA = SCHEMA.OneOf(
[SCHEMA.String('rsa'), SCHEMA.String('ed25519'),
[SCHEMA.String('rsa'), SCHEMA.String('ed25519'), SCHEMA.String('ecdsa'),
SCHEMA.RegularExpression(r'ecdsa-sha2-nistp(256|384)')])

# A generic securesystemslib key. All securesystemslib keys should be saved to
Expand Down Expand Up @@ -253,7 +253,8 @@
# An ECDSA securesystemslib key.
ECDSAKEY_SCHEMA = SCHEMA.Object(
object_name = 'ECDSAKEY_SCHEMA',
keytype = SCHEMA.RegularExpression(r'ecdsa-sha2-nistp(256|384)'),
keytype = SCHEMA.OneOf([SCHEMA.String('ecdsa'),
SCHEMA.RegularExpression(r'ecdsa-sha2-nistp(256|384)')]),
scheme = ECDSA_SCHEME_SCHEMA,
keyid = KEYID_SCHEMA,
keyid_hash_algorithms = SCHEMA.Optional(HASHALGORITHMS_SCHEMA),
Expand Down
16 changes: 7 additions & 9 deletions securesystemslib/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,13 +848,6 @@ def import_ecdsa_publickey_from_file(filepath):
ecdsa_key, junk = \
securesystemslib.keys.format_metadata_to_key(ecdsa_key_metadata)

# Raise an exception if an unexpected key type is imported. Redundant
# validation of 'keytype'. 'securesystemslib.keys.format_metadata_to_key()'
# should have fully validated 'ecdsa_key_metadata'.
if ecdsa_key['keytype'] != 'ecdsa-sha2-nistp256': # pragma: no cover
message = 'Invalid key type loaded: ' + repr(ecdsa_key['keytype'])
raise securesystemslib.exceptions.FormatError(message)

return ecdsa_key


Expand Down Expand Up @@ -888,7 +881,7 @@ def import_ecdsa_privatekey_from_file(filepath, password=None,
<Exceptions>
securesystemslib.exceptions.FormatError, if the arguments are improperly
formatted or the imported key object contains an invalid key type (i.e.,
not 'ecdsa-sha2-nistp256').
not 'ecdsa').
securesystemslib.exceptions.CryptoError, if 'filepath' cannot be decrypted.
Expand Down Expand Up @@ -938,7 +931,12 @@ def import_ecdsa_privatekey_from_file(filepath, password=None,
password)

# Raise an exception if an unexpected key type is imported.
if key_object['keytype'] != 'ecdsa-sha2-nistp256':
# NOTE: we support keytype's of ecdsa-sha2-nistp256 and ecdsa-sha2-nistp384
# in order to support key files generated with older versions of
# securesystemslib. At some point this backwards compatibility should be
# removed.
if key_object['keytype'] not in['ecdsa', 'ecdsa-sha2-nistp256',
'ecdsa-sha2-nistp384']:
message = 'Invalid key type loaded: ' + repr(key_object['keytype'])
raise securesystemslib.exceptions.FormatError(message)

Expand Down
25 changes: 14 additions & 11 deletions securesystemslib/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def generate_ecdsa_key(scheme='ecdsa-sha2-nistp256'):
ECDSA key is generated. The object returned conforms to
'securesystemslib.formats.ECDSAKEY_SCHEMA' and has the form:
{'keytype': 'ecdsa-sha2-nistp256',
{'keytype': 'ecdsa',
'scheme', 'ecdsa-sha2-nistp256',
'keyid': keyid,
'keyval': {'public': '',
Expand Down Expand Up @@ -260,7 +260,7 @@ def generate_ecdsa_key(scheme='ecdsa-sha2-nistp256'):

# Begin building the ECDSA key dictionary.
ecdsa_key = {}
keytype = 'ecdsa-sha2-nistp256'
keytype = 'ecdsa'
public = None
private = None

Expand Down Expand Up @@ -687,8 +687,9 @@ def create_signature(key_dict, data):
securesystemslib.formats.ANYKEY_SCHEMA.check_match(key_dict)

# Signing the 'data' object requires a private key. Signing schemes that are
# currently supported are: 'ed25519', 'ecdsa-sha2-nistp256', and rsa schemes
# defined in `securesystemslib.keys.RSA_SIGNATURE_SCHEMES`.
# currently supported are: 'ed25519', 'ecdsa-sha2-nistp256',
# 'ecdsa-sha2-nistp384' and rsa schemes defined in
# `securesystemslib.keys.RSA_SIGNATURE_SCHEMES`.
# RSASSA-PSS and RSA-PKCS1v15 keys and signatures can be generated and
# verified by rsa_keys.py, and Ed25519 keys by PyNaCl and PyCA's
# optimized, pure python implementation of Ed25519.
Expand Down Expand Up @@ -716,7 +717,9 @@ def create_signature(key_dict, data):
sig, scheme = securesystemslib.ed25519_keys.create_signature(
public, private, data, scheme)

elif keytype == 'ecdsa-sha2-nistp256':
# Continue to support keytypes of ecdsa-sha2-nistp256 and ecdsa-sha2-nistp384
# for backwards compatibility with older securesystemslib releases
elif keytype in ['ecdsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384']:
sig, scheme = securesystemslib.ecdsa_keys.create_signature(
public, private, data, scheme)

Expand Down Expand Up @@ -860,7 +863,7 @@ def verify_signature(key_dict, signature, data):
raise securesystemslib.exceptions.UnsupportedAlgorithmError('Unsupported'
' signature scheme is specified: ' + repr(scheme))

elif keytype in ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384']:
elif keytype in ['ecdsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384']:
if scheme in ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384']:
valid_signature = securesystemslib.ecdsa_keys.verify_signature(public,
scheme, sig, data)
Expand Down Expand Up @@ -1637,7 +1640,7 @@ def import_ecdsakey_from_private_pem(pem, scheme='ecdsa-sha2-nistp256', password
a keyid identifier for the ECDSA key is generated. The object returned
conforms to:
{'keytype': 'ecdsa-sha2-nistp256',
{'keytype': 'ecdsa',
'scheme': 'ecdsa-sha2-nistp256',
'keyid': keyid,
'keyval': {'public': '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----',
Expand Down Expand Up @@ -1696,7 +1699,7 @@ def import_ecdsakey_from_private_pem(pem, scheme='ecdsa-sha2-nistp256', password

# Begin building the ECDSA key dictionary.
ecdsakey_dict = {}
keytype = 'ecdsa-sha2-nistp256'
keytype = 'ecdsa'
public = None
private = None

Expand Down Expand Up @@ -1740,7 +1743,7 @@ def import_ecdsakey_from_public_pem(pem, scheme='ecdsa-sha2-nistp256'):
for the ECDSA key is generated. The object returned conforms to
'securesystemslib.formats.ECDSAKEY_SCHEMA' and has the form:
{'keytype': 'ecdsa-sha2-nistp256',
{'keytype': 'ecdsa',
'scheme': 'ecdsa-sha2-nistp256',
'keyid': keyid,
'keyval': {'public': '-----BEGIN PUBLIC KEY----- ...',
Expand Down Expand Up @@ -1801,7 +1804,7 @@ def import_ecdsakey_from_public_pem(pem, scheme='ecdsa-sha2-nistp256'):

# Begin building the ECDSA key dictionary.
ecdsakey_dict = {}
keytype = 'ecdsa-sha2-nistp256'
keytype = 'ecdsa'

# Generate the keyid of the ECDSA key. 'key_value' corresponds to the
# 'keyval' entry of the 'ECDSAKEY_SCHEMA' dictionary. The private key
Expand Down Expand Up @@ -1882,7 +1885,7 @@ def import_ecdsakey_from_pem(pem, scheme='ecdsa-sha2-nistp256'):

# Begin building the ECDSA key dictionary.
ecdsakey_dict = {}
keytype = 'ecdsa-sha2-nistp256'
keytype = 'ecdsa'

# Generate the keyid of the ECDSA key. 'key_value' corresponds to the
# 'keyval' entry of the 'ECDSAKEY_SCHEMA' dictionary. The private key
Expand Down
4 changes: 2 additions & 2 deletions tests/check_public_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def test_keys(self):
securesystemslib.exceptions.UnsupportedLibraryError):
securesystemslib.keys.create_signature(keydict, data)

keydict['keytype'] = 'ecdsa-sha2-nistp256'
keydict['keytype'] = 'ecdsa'
keydict['scheme'] = 'ecdsa-sha2-nistp256'
with self.assertRaises(
securesystemslib.exceptions.UnsupportedLibraryError):
Expand All @@ -137,7 +137,7 @@ def test_keys(self):
securesystemslib.exceptions.UnsupportedLibraryError):
securesystemslib.keys.create_signature(keydict, data)

keydict['keytype'] = 'ecdsa-sha2-nistp256'
keydict['keytype'] = 'ecdsa'
keydict['scheme'] = 'ecdsa-sha2-nistp256'
sig = {'keyid': 'f00',
'sig': 'cfbce8e23eef478975a4339036de2335002d57c7b1632dd01e526a3bc52a5b261508ad50b9e25f1b819d61017e7347e912db1af019bf47ee298cc58bbdef9703'}
Expand Down
14 changes: 5 additions & 9 deletions tests/test_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,11 @@ def test_create_signature(self):

# Creating a signature for 'DATA'.
ecdsa_signature = KEYS.create_signature(self.ecdsakey_dict, DATA)
ecdsa_signature = KEYS.create_signature(self.ecdsakey_dict, DATA)

# Check format of output.
self.assertEqual(None,
securesystemslib.formats.SIGNATURE_SCHEMA.check_match(ecdsa_signature),
FORMAT_ERROR_MSG)
self.assertEqual(None,
securesystemslib.formats.SIGNATURE_SCHEMA.check_match(ecdsa_signature),
FORMAT_ERROR_MSG)

# Removing private key from 'ecdsakey_dict' - should raise a TypeError.
private = self.ecdsakey_dict['keyval']['private']
Expand All @@ -304,8 +300,6 @@ 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)
ecdsa_signature = None

ecdsa_signature = KEYS.create_signature(self.ecdsakey_dict, DATA)

# Verifying the 'signature' of 'DATA'.
Expand All @@ -324,12 +318,14 @@ def test_verify_signature(self):
KEYS.verify_signature, self.ed25519key_dict, ed25519_signature, DATA)
self.ed25519key_dict['scheme'] = valid_scheme

# Verifying the 'ecdsa_signature' of 'DATA'.
verified = KEYS.verify_signature(self.ecdsakey_dict, ecdsa_signature, DATA)
self.assertTrue(verified, "Incorrect signature.")

# Verifying the 'ecdsa_signature' of 'DATA'.
verified = KEYS.verify_signature(self.ecdsakey_dict, ecdsa_signature,
DATA)
# Verifying the 'ecdsa_signature' of 'DATA' with an old-style key dict
old_key_dict = self.ecdsakey_dict.copy()
old_key_dict['keytype'] = 'ecdsa-sha2-nistp256'
verified = KEYS.verify_signature(old_key_dict, ecdsa_signature, DATA)
self.assertTrue(verified, "Incorrect signature.")

# Test for an invalid ecdsa signature scheme.
Expand Down

0 comments on commit 876772c

Please sign in to comment.