Skip to content

Commit

Permalink
Add minor style/clean-up fixes in spx related code
Browse files Browse the repository at this point in the history
- Remove trailing whitespace
- Remove redundant try/except blocks in functions, where
  - the exception is already handled by earlier function code
    (schema check)
  - the exception should be handled on module level (ImportError
    for optional PySPX)
- De-clutter (e.g. remove some obvious code comments, superfluous
  variable null value instantiations, redundant checks)
- Fix typos
- Enhance line wrapping
  • Loading branch information
lukpueh committed Jun 18, 2019
1 parent a67a6b3 commit 44db3df
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 88 deletions.
11 changes: 5 additions & 6 deletions securesystemslib/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1053,13 +1053,12 @@ def import_spx_publickey_from_file(filepath):
# SPX key objects are saved in json and metadata format. Return the
# loaded key object in securesystemslib.formats.SPXKEY_SCHEMA' format that
# also includes the keyid.
spx_key_metadata = securesystemslib.util.load_json_file(filepath)
spx_key, junk = \
securesystemslib.keys.format_metadata_to_key(spx_key_metadata)
spx_key_data = securesystemslib.util.load_json_file(filepath)
spx_key, junk = securesystemslib.keys.format_metadata_to_key(spx_key_data)

# Raise an exception if an unexpected key type is imported. Redundant
# validation of 'keytype'. 'securesystemslib.keys.format_metadata_to_key()'
# should have fully validated 'spx_key_metadata'.
# should have fully validated 'spx_key_data'.
if spx_key['keytype'] != 'spx': # pragma: no cover
message = 'Invalid key type loaded: ' + repr(spx_key['keytype'])
raise securesystemslib.exceptions.FormatError(message)
Expand Down Expand Up @@ -1149,8 +1148,8 @@ def import_spx_privatekey_from_file(filepath, password=None, prompt=False):
# Otherwise, load it straight from the disk.
with open(filepath, 'rb') as file_object:
json_str = file_object.read()
return securesystemslib.keys.\
import_spxkey_from_private_json(json_str, password=password)
return securesystemslib.keys.import_spxkey_from_private_json(
json_str, password=password)



Expand Down
23 changes: 14 additions & 9 deletions securesystemslib/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ def generate_ed25519_key(scheme='ed25519'):
def generate_spx_key(scheme='spx'):
"""
<Purpose>
Generate public and private SPX keys, In addition, a keyid identifier generated
for the returned SPX object. The object returned conforms to
Generate public and private SPX keys, In addition, a keyid identifier
generated for the returned SPX object. The object returned conforms to
'securesystemslib.formats.SPXKEY_SCHEMA' and has the form:
{'keytype': 'spx',
Expand Down Expand Up @@ -443,12 +443,9 @@ def generate_spx_key(scheme='spx'):
# Begin building the SPX key dictionary.
spx_key = {}
keytype = 'spx'
public = None
private = None

# Generate the public and private SPX key with the 'pyspx' library.
public, private = \
securesystemslib.spx_keys.generate_public_and_private()
public, private = securesystemslib.spx_keys.generate_public_and_private()

# Generate the keyid of the SPX key. 'key_value' corresponds to the
# 'keyval' entry of the 'SPXKEY_SCHEMA' dictionary. The private key
Expand All @@ -457,8 +454,8 @@ def generate_spx_key(scheme='spx'):
'private': ''}
keyid = _get_keyid(keytype, scheme, key_value)

# Build the 'spx_key' dictionary. Update 'key_value' with the SPX
# private key prior to adding 'key_value' to 'spx_key'.
# Build the 'spx_key' dictionary. Update 'key_value' with the SPX private
# key prior to adding 'key_value' to 'spx_key'.
key_value['private'] = binascii.hexlify(private).decode()

spx_key['keytype'] = keytype
Expand Down Expand Up @@ -705,6 +702,12 @@ def create_signature(key_dict, data):
ed25519 - high-speed high security signatures
http://ed25519.cr.yp.to/
'spx'
Sphinx+-Shake256
https://sphincs.org/
'ecdsa-sha2-nistp256'
Which signature to generate is determined by the key type of 'key_dict'
and the available cryptography library specified in 'settings'.
Expand Down Expand Up @@ -948,7 +951,9 @@ def verify_signature(key_dict, signature, data):
elif keytype == 'spx':
if scheme == 'spx':
public = binascii.unhexlify(public.encode('utf-8'))
valid_signature = securesystemslib.spx_keys.verify_signature(public, scheme, sig, data)
valid_signature = securesystemslib.spx_keys.verify_signature(public,
scheme, sig, data)

else:
raise securesystemslib.exceptions.UnsupportedAlgorithmError('Unsupported'
' signature scheme is specified: ' + repr(scheme))
Expand Down
82 changes: 13 additions & 69 deletions securesystemslib/spx_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
See LICENSE for licensing information.
<Purpose>
The goal of this module is to support SPINCS+ ("SPX") signatures. SPHINCS+ is an
a framework for creating stateless hash-based signatures.
The goal of this module is to support SPINCS+ ("SPX") signatures. SPHINCS+ is
a framework for creating stateless hash-based signatures.
The concrete instantiation of this framework used here is the "shake256-192s"
parameter set as defined in the SPHINCS+ submission to NIST; see
http://sphincs.org/resources.html
Expand Down Expand Up @@ -49,9 +49,6 @@
import securesystemslib.exceptions
import securesystemslib.schema as SCHEMA

# Supported spx signing schemes: 'spx'.
_SUPPORTED_SPX_SIGNING_SCHEMES = ['spx']

# Define lengths of SPX keys and signature bytes
# NOTE: Define module scope schemas here to avoid conditional imports of
# optional 'pyspx' package in 'formats' module. ImportError and IOError should
Expand Down Expand Up @@ -79,9 +76,6 @@ def generate_public_and_private():
None.
<Exceptions>
securesystemslib.exceptions.UnsupportedLibraryError, if the pyspx
module is unavailable.
NotImplementedError, if a randomness source is not found by 'os.urandom'.
<Side Effects>
Expand All @@ -98,15 +92,9 @@ def generate_public_and_private():
# returned should be suitable for cryptographic use and is OS-specific.
# Raise 'NotImplementedError' if a randomness source is not found.
seed = os.urandom(pyspx.crypto_sign_SEEDBYTES)
public = None

# Generate the public key. pyspx performs the actual key generation.
try:
public, private = pyspx.generate_keypair(seed)

except NameError: # pragma: no cover
raise securesystemslib.exceptions.UnsupportedLibraryError('The pyspx'
' library and/or its dependencies unavailable.')
public, private = pyspx.generate_keypair(seed)

return public, private

Expand Down Expand Up @@ -157,37 +145,20 @@ def create_signature(private_key, data, scheme):
spx.signing.SigningKey.sign() called to generate the actual signature.
<Returns>
A signature dictionary conformat to 'securesystemslib.format.SIGNATURE_SCHEMA'.
A signature dictionary conformant to
'securesystemslib.format.SIGNATURE_SCHEMA'.
"""
# Validate arguments
SPX_PRIVATE_BYTES_SCHEMA.check_match(private_key)
securesystemslib.formats.SPX_SIG_SCHEMA.check_match(scheme)

private = private_key

signature = None

# An if-clause is not strictly needed here, since 'spx' is the only
# currently supported scheme. Nevertheless, include the conditional
# statement to accommodate schemes that might be added in the future.
if scheme == 'spx':
try:
signature = pyspx.sign(data, private)

# The unit tests expect required libraries to be installed.
except NameError: # pragma: no cover
raise securesystemslib.exceptions.UnsupportedLibraryError('The pyspx'
' library and/or its dependencies unavailable.')

except (ValueError, TypeError) as e:
raise securesystemslib.exceptions.CryptoError('An "spx" signature'
' could not be created with pyspx.' + str(e))
try:
signature = pyspx.sign(data, private_key)

# This is a defensive check for a valid 'scheme', which should have already
# been validated in the check_match() above.
else: #pragma: no cover
raise securesystemslib.exceptions.UnsupportedAlgorithmError('Unsupported'
' signature scheme is specified: ' + repr(scheme))
except (ValueError, TypeError) as e:
raise securesystemslib.exceptions.CryptoError('An "spx" signature'
' could not be created with pyspx.' + str(e))

return signature, scheme

Expand Down Expand Up @@ -230,10 +201,6 @@ def verify_signature(public_key, scheme, signature, data):
generate 'signature'. 'data' is needed here to verify the signature.
<Exceptions>
securesystemslib.exceptions.UnsupportedAlgorithmError. Raised if the
signature scheme 'scheme' is not one supported by
securesystemslib.spx_keys.create_signature().
securesystemslib.exceptions.FormatError. Raised if the arguments are
improperly formatted.
Expand All @@ -248,31 +215,8 @@ def verify_signature(public_key, scheme, signature, data):
SPX_SIG_BYTES_SCHEMA.check_match(signature)
securesystemslib.formats.SPX_SIG_SCHEMA.check_match(scheme)


# Verify 'signature'. Before returning the Boolean result, ensure 'spx'
# was used as the signature scheme. Raise
# 'securesystemslib.exceptions.UnsupportedLibraryError' if 'pyspx' is unavailable.
public = public_key
valid_signature = False

if scheme in _SUPPORTED_SPX_SIGNING_SCHEMES:
try:
valid_signature = pyspx.verify(data, signature, public)

# The unit tests expect PyNaCl to be installed.
except NameError: # pragma: no cover
raise securesystemslib.exceptions.UnsupportedLibraryError('The pyspx'
' library and/or its dependencies unavailable.')


# This is a defensive check for a valid 'scheme', which should have already
# been validated in the SPX_SIG_SCHEMA.check_match(scheme) above.
else: #pragma: no cover
message = 'Unsupported spx signature scheme: ' + repr(scheme) + '.\n' + \
'Supported schemes: ' + repr(_SUPPORTED_SPX_SIGNING_SCHEMES) + '.'
raise securesystemslib.exceptions.UnsupportedAlgorithmError(message)

return valid_signature
# Return boolean signature verification result
return pyspx.verify(data, signature, public_key)



Expand Down
4 changes: 2 additions & 2 deletions tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def test_generate_and_write_ed25519_keypair(self):
password='pw',
prompt=True)

# Fail importing encrypted key passing an empty string for passwd
# Fail importing encrypted key passing an empty string for passwd
with self.assertRaises(ValueError):
interface.import_ed25519_privatekey_from_file(test_keypath,
password='')
Expand Down Expand Up @@ -512,7 +512,7 @@ def test_generate_and_write_spx_keypair(self):
password='pw',
prompt=True)

# Fail importing encrypted key passing an empty string for passwd
# Fail importing encrypted key passing an empty string for passwd
with self.assertRaises(ValueError):
interface.import_spx_privatekey_from_file(test_keypath,
password='')
Expand Down
2 changes: 0 additions & 2 deletions tests/test_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,6 @@ def test_verify_signature(self):
rsa_signature = KEYS.create_signature(self.rsakey_dict, DATA)
ed25519_signature = KEYS.create_signature(self.ed25519key_dict, DATA)
spx_signature = KEYS.create_signature(self.spxkey_dict, DATA)
ecdsa_signature = None

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

# Verifying the 'signature' of 'DATA'.
Expand Down

0 comments on commit 44db3df

Please sign in to comment.