mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
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:
parent
8d34b7aff8
commit
c58906f9c2
5 changed files with 42 additions and 38 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
15
tuf/keys.py
15
tuf/keys.py
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue