Fix for issue #153

Update the key modules and their unit tests so that only the signature scheme is included in the signature label.

PyCrypto-PKCS#1 PSS -> RSASSA-PSS
ed25519-python and ed25519-pynacl -> ed25519
This commit is contained in:
Vladimir Diaz 2013-11-27 12:11:16 -05:00
parent 8d34b7aff8
commit c58906f9c2
5 changed files with 42 additions and 38 deletions

View file

@ -60,7 +60,7 @@ def test_create_signature(self):
tuf.formats.ED25519SIGNATURE_SCHEMA.matches(signature))
self.assertEqual(True, tuf.formats.NAME_SCHEMA.matches(method))
self.assertEqual('ed25519-python', method)
self.assertEqual('ed25519', method)
# Check for improperly formatted argument.
self.assertRaises(tuf.FormatError,

View file

@ -63,7 +63,7 @@ def test_create_rsa_signature(self):
self.assertNotEqual(None, signature)
self.assertEqual(None, tuf.formats.NAME_SCHEMA.check_match(method),
FORMAT_ERROR_MSG)
self.assertEqual('PyCrypto-PKCS#1 PSS', method)
self.assertEqual('RSASSA-PSS', method)
# Check for improperly formatted argument.
self.assertRaises(tuf.FormatError,

View file

@ -69,11 +69,15 @@
#
# PyNaCl's 'cffi' dependency may thrown an 'IOError' exception when
# importing 'nacl.signing'.
"""
try:
import nacl.signing
import nacl.encoding
except (ImportError, IOError):
pass
"""
import nacl.signing
import nacl.encoding
# The optimized pure Python implementation of ed25519 provided by TUF. If
# PyNaCl cannot be imported and an attempt to use is made in this module, a
@ -88,10 +92,12 @@
# Perform object format-checking.
import tuf.formats
# Supported ed25519 signing methods. 'ed25519-python' is the pure Python
# implementation signing method. 'ed25519-pynacl' (i.e., 'nacl' module) is the
# (libsodium+Python bindings) implementation signing method.
_SUPPORTED_ED25519_SIGNING_METHODS = ['ed25519-python', 'ed25519-pynacl']
# Supported ed25519 signing method: 'ed25519'. The pure Python
# implementation (i.e., 'ed25519.ed25519') and PyNaCl
# (i.e., 'nacl', libsodium+Python bindgs) modules are currently supported in
# the creationg of 'ed25519' signatures. Previously, a distinction was made
# between signatures made by the pure Python implementation and PyNaCl.
_SUPPORTED_ED25519_SIGNING_METHODS = ['ed25519',]
def generate_public_and_private(use_pynacl=False):
@ -178,11 +184,10 @@ def generate_public_and_private(use_pynacl=False):
def create_signature(public_key, private_key, data, use_pynacl=False):
"""
<Purpose>
Return a (signature, method) tuple, where the method is either:
'ed25519-python' if the signature is generated by the pure python
implemenation, or 'ed25519-pynacl' if generated by 'nacl'.
signature conforms to 'tuf.formats.ED25519SIGNATURE_SCHEMA', and has the
form:
Return a (signature, method) tuple, where the method is 'ed25519' and
generated by either the pure python implemenation, or by PyNaCl
(i.e., 'nacl'). The signature returns conforms to
'tuf.formats.ED25519SIGNATURE_SCHEMA', and has the form:
'\xae\xd7\x9f\xaf\x95{bP\x9e\xa8YO Z\x86\x9d...'
@ -194,13 +199,13 @@ def create_signature(public_key, private_key, data, use_pynacl=False):
create_signature(public, private, data, use_pynacl=False)
>>> tuf.formats.ED25519SIGNATURE_SCHEMA.matches(signature)
True
>>> method == 'ed25519-python'
>>> method == 'ed25519'
True
>>> signature, method = \
create_signature(public, private, data, use_pynacl=True)
>>> tuf.formats.ED25519SIGNATURE_SCHEMA.matches(signature)
True
>>> method == 'ed25519-pynacl'
>>> method == 'ed25519'
True
<Arguments>
@ -258,7 +263,7 @@ def create_signature(public_key, private_key, data, use_pynacl=False):
# The private and public keys have been validated above by 'tuf.formats' and
# should be 32-byte strings.
if use_pynacl:
method = 'ed25519-pynacl'
method = 'ed25519'
try:
nacl_key = nacl.signing.SigningKey(private)
nacl_sig = nacl_key.sign(data)
@ -269,20 +274,20 @@ def create_signature(public_key, private_key, data, use_pynacl=False):
raise tuf.UnsupportedLibraryError(message)
except (ValueError, nacl.signing.CryptoError):
message = 'An "ed25519-pynacl" signature could not be created.'
message = 'An "ed25519" signature could not be created with PyNaCl.'
raise tuf.CryptoError(message)
# Generate an "ed25519-python" (i.e., pure python implementation) signature.
# Generate an "ed25519" signature with the pure python implementation.
else:
# ed25519.ed25519.signature() requires both the seed and public keys.
# It calculates the SHA512 of the seed key, which is 32 bytes.
method = 'ed25519-python'
method = 'ed25519'
try:
signature = ed25519.ed25519.signature(data, private, public)
# 'Exception' raised by ed25519.py for any exception that may occur.
except Exception, e:
message = 'An "ed25519-python" signature could not be generated.'
message = 'An "ed25519" signature could not be generated in pure Python.'
raise tuf.CryptoError(message)
return signature, method
@ -317,8 +322,8 @@ def verify_signature(public_key, method, signature, data, use_pynacl=False):
The public key is a 32-byte string.
method:
'ed25519-python' if the signature was generated by the pure python
implementation and 'ed25519-pynacl' if generated by 'nacl'.
'ed25519' signature method generated by either the pure python
implementation (i.e., 'ed25519.ed25519.py') or PyNacl(i.e., 'nacl').
signature:
The signature is a 64-byte string.
@ -362,7 +367,7 @@ def verify_signature(public_key, method, signature, data, use_pynacl=False):
tuf.formats.BOOLEAN_SCHEMA.check_match(use_pynacl)
# Verify 'signature'. Before returning the Boolean result,
# ensure 'ed25519-python' or 'ed25519-pynacl' was used as the signing method.
# ensure 'ed25519' was used as the signing method.
# Raise 'tuf.UnsupportedLibraryError' if 'use_pynacl' is True but 'nacl' is
# unavailable.
public = public_key
@ -381,7 +386,7 @@ def verify_signature(public_key, method, signature, data, use_pynacl=False):
except nacl.signing.BadSignatureError:
pass
# Verify signature with 'ed25519-python' (i.e., pure Python implementation).
# Verify 'ed25519' signature with pure Python implementation.
else:
try:
ed25519.ed25519.checkvalid(signature, data, public)

View file

@ -221,7 +221,7 @@ def generate_ed25519_key():
Generate public and private ED25519 keys, both of length 32-bytes, although
they are hexlified to 64 bytes.
In addition, a keyid identifier generated for the returned ED25519 object.
The object returned conforms to 'tuf.formats.ED25519KEY_SCHEMA' and as the
The object returned conforms to 'tuf.formats.ED25519KEY_SCHEMA' and has the
form:
{'keytype': 'ed25519',
'keyid': 'f30a0870d026980100c0573bd557394f8c1bbd6...',
@ -526,11 +526,11 @@ def create_signature(key_dict, data):
The following signature methods are supported:
'PyCrypto-PKCS#1 PSS'
'RSASSA-PSS'
RFC3447 - RSASSA-PSS
http://www.ietf.org/rfc/rfc3447.
'ed25519-python or 'ed25519-pynacl'
'ed25519'
ed25519 - high-speed high security signatures
http://ed25519.cr.yp.to/
@ -594,10 +594,9 @@ def create_signature(key_dict, data):
_check_crypto_libraries()
# Signing the 'data' object requires a private key.
# The 'PyCrypto-PKCS#1 PSS' (i.e., PyCrypto module),
# 'ed25519-pynacl' (i.e., 'nacl'), and 'ed25519-python (i.e., optimized pure
# python implementation of ed25519) are the only signing methods currently
# supported.
# The 'RSASSA-PSS' (i.e., PyCrypto module) and 'ed25519' (i.e., PyNaCl and the
# optimized pure Python implementation of ed25519) are the only signing
# methods currently supported.
signature = {}
keytype = key_dict['keytype']
public = key_dict['keyval']['public']
@ -784,7 +783,7 @@ def import_rsakey_from_encrypted_pem(encrypted_pem, password):
>>> private = rsa_key['keyval']['private']
>>> passphrase = 'secret'
>>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase)
>>> rsa_key2 = import_key_from_encrypted_pem(encrypted_pem, passphrase)
>>> rsa_key2 = import_rsakey_from_encrypted_pem(encrypted_pem, passphrase)
>>> rsa_key == rsa_key2
True

View file

@ -42,7 +42,7 @@
# PKCS#1 v1.5 is available for compatibility with existing applications, but
# RSASSA-PSS is encouraged for newer applications. RSASSA-PSS generates
# a random salt to ensure the signature generated is probabilistic rather than
# deterministic, like PKCS#1 v1.5.
# deterministic (e.g., PKCS#1 v1.5).
# http://en.wikipedia.org/wiki/RSA-PSS#Schemes
# https://tools.ietf.org/html/rfc3447#section-8.1
import Crypto.Signature.PKCS1_PSS
@ -149,7 +149,7 @@ def create_rsa_signature(private_key, data):
>>> signature, method = create_rsa_signature(private, data)
>>> tuf.formats.NAME_SCHEMA.matches(method)
True
>>> method == 'PyCrypto-PKCS#1 PSS'
>>> method == 'RSASSA-PSS'
True
>>> tuf.formats.PYCRYPTOSIGNATURE_SCHEMA.matches(method)
True
@ -173,7 +173,7 @@ def create_rsa_signature(private_key, data):
<Returns>
A (signature, method) tuple, where the signature is a string and the method
is 'PyCrypto-PKCS#1 PSS'.
is 'RSASSA-PSS'.
"""
# Does 'private_key' have the correct format?
@ -182,9 +182,9 @@ def create_rsa_signature(private_key, data):
tuf.formats.PEMRSA_SCHEMA.check_match(private_key)
# Signing the 'data' object requires a private key.
# The 'PyCrypto-PKCS#1 PSS' (i.e., PyCrypto module) signing method is the
# The 'RSASSA-PSS' (i.e., PyCrypto module) signing method is the
# only method currently supported.
method = 'PyCrypto-PKCS#1 PSS'
method = 'RSASSA-PSS'
signature = None
# Verify the signature, but only if the private key has been set. The private
@ -233,7 +233,7 @@ def verify_rsa_signature(signature, signature_method, public_key, data):
signature_method:
A string that indicates the signature algorithm used to generate
'signature'. 'PyCrypto-PKCS#1 PSS' is currently supported.
'signature'. 'RSASSA-PSS' is currently supported.
public_key:
The RSA public key, a string in PEM format.
@ -268,7 +268,7 @@ def verify_rsa_signature(signature, signature_method, public_key, data):
tuf.formats.PYCRYPTOSIGNATURE_SCHEMA.check_match(signature)
# Verify whether the private key of 'public_key' produced the signature.
# Before returning the Boolean result, ensure 'PyCrypto-PKCS#1 PSS' was used
# Before returning the Boolean result, ensure 'RSASSA-PSS' was used
# as the signing method.
signature = signature
method = signature_method
@ -277,7 +277,7 @@ def verify_rsa_signature(signature, signature_method, public_key, data):
# Verify the signature with PyCrypto if the signature method is valid, else
# raise 'tuf.UnknownMethodError'.
if method == 'PyCrypto-PKCS#1 PSS':
if method == 'RSASSA-PSS':
try:
rsa_key_object = Crypto.PublicKey.RSA.importKey(public_key)
pkcs1_pss_verifier = Crypto.Signature.PKCS1_PSS.new(rsa_key_object)