diff --git a/tuf/keys.py b/tuf/keys.py index e0be882f..61d94083 100755 --- a/tuf/keys.py +++ b/tuf/keys.py @@ -104,10 +104,12 @@ def generate_rsa_key(bits=_DEFAULT_RSA_KEY_BITS): >>> rsa_key = generate_rsa_key(bits=2048) >>> tuf.formats.RSAKEY_SCHEMA.matches(rsa_key) True - >>> len(rsa_key['keyval']['public']) - 64 - >>> len(rsa_key['keyval']['private']) - 64 + >>> public = rsa_key['keyval']['public'] + >>> private = rsa_key['keyval']['private'] + >>> tuf.formats.PEMRSA_SCHEMA.matches(public) + True + >>> tuf.formats.PEMRSA_SCHEMA.matches(private) + True bits: @@ -237,9 +239,11 @@ def generate_ed25519_key(): # or not a multiple of 256, although a 2048-bit minimum is enforced by # tuf.formats.RSAKEYBITS_SCHEMA.check_match(). if 'ed25519-pynacl' in _available_crypto_libraries: - public, private = tuf.ed25519_keys.generate_public_and_private(use_pynacl=True) + public, private = \ + tuf.ed25519_keys.generate_public_and_private(use_pynacl=True) elif 'ed25519-python' in _available_crypto_libraries: - public, private = tuf.ed25519_keys.generate_public_and_private(use_pynacl=False) + public, private = \ + tuf.ed25519_keys.generate_public_and_private(use_pynacl=False) else: message = 'A supported method of generating ed25519 keys not available\n'+\ 'Available crypto libraries: '+repr(_available_crypto_libraries)+'.' @@ -290,7 +294,8 @@ def create_in_metadata_format(keytype, key_value, private=False): >>> ed25519_key = generate_ed25519_key() >>> key_val = ed25519_key['keyval'] >>> keytype = ed25519_key['keytype'] - >>> ed25519_metadata = create_in_metadata_format(keytype, key_val, private=True) + >>> ed25519_metadata = \ + create_in_metadata_format(keytype, key_val, private=True) >>> tuf.formats.KEY_SCHEMA.matches(ed25519_metadata) True @@ -362,7 +367,8 @@ def create_from_metadata_format(key_metadata): >>> ed25519_key = generate_ed25519_key() >>> key_val = ed25519_key['keyval'] >>> keytype = ed25519_key['keytype'] - >>> ed25519_metadata = create_in_metadata_format(keytype, key_val, private=True) + >>> ed25519_metadata = \ + create_in_metadata_format(keytype, key_val, private=True) >>> ed25519_key_2 = create_from_metadata_format(ed25519_metadata) >>> tuf.formats.ED25519KEY_SCHEMA.matches(ed25519_key_2) True @@ -473,16 +479,16 @@ def create_signature(key_dict, data): RFC3447 - RSASSA-PSS http://www.ietf.org/rfc/rfc3447. - >>> ed25519_key_dict = generate_ed25519_key() - >>> data = 'The quick brown fox jumps over the lazy dog.' - >>> signature = create_signature(ed25519_key_dict, data) + >>> ed25519_key = generate_ed25519_key() + >>> data = 'The quick brown fox jumps over the lazy dog' + >>> signature = create_signature(ed25519_key, data) >>> tuf.formats.SIGNATURE_SCHEMA.matches(signature) True >>> len(signature['sig']) 128 - >>> rsa_key_dict = generate_rsa_key() - >>> data = 'The quick brown fox jumps over the lazy dog.' - >>> signature = create_signature(rsa_key_dict, data) + >>> rsa_key = generate_rsa_key() + >>> data = 'The quick brown fox jumps over the lazy dog' + >>> signature = create_signature(rsa_key, data) >>> tuf.formats.SIGNATURE_SCHEMA.matches(signature) True @@ -537,9 +543,13 @@ def create_signature(key_dict, data): sig, method = tuf.pycrypto_keys.create_signature(private, data) elif keytype == 'ed25519': if 'ed25519-pynacl' in _available_crypto_libraries: - sig, method = tuf.ed25519_keys.create_signature(public, private, data, use_pynacl=True) + public = binascii.unhexlify(public) + private = binascii.unhexlify(private) + sig, method = tuf.ed25519_keys.create_signature(public, private, + data, use_pynacl=True) else: - sig, method = tuf.ed25519_keys.create_signature(public, private, data, use_pynacl=False) + sig, method = tuf.ed25519_keys.create_signature(public, private, + data, use_pynacl=False) else: raise TypeError('Invalid key type.') @@ -623,12 +633,17 @@ def verify_signature(key_dict, signature, data): if key_type == 'rsa': if _CRYPTO_LIBRARY == 'pycrypto': - valid_signature = tuf.pycrypto_keys.verify_signature(sig, method, public, data) + valid_signature = tuf.pycrypto_keys.verify_signature(sig, method, + public, data) elif key_type == 'ed25519': if 'ed25519-pynacl' in _available_crypto_libraries: - valid_signature = tuf.ed25519_keys.verify_signature(public, method, sig, data, use_pynacl=True) + valid_signature = tuf.ed25519_keys.verify_signature(public, + method, sig, data, + use_pynacl=True) else: - valid_signature = tuf.ed25519_keys.verify_signature(public, method, sig, data, use_pynacl=False) + valid_signature = tuf.ed25519_keys.verify_signature(public, + method, sig, data, + use_pynacl=False) else: raise TypeError('Unsupported key type.') diff --git a/tuf/pycrypto_keys.py b/tuf/pycrypto_keys.py index 09ce75bb..5d1e1bc6 100755 --- a/tuf/pycrypto_keys.py +++ b/tuf/pycrypto_keys.py @@ -78,7 +78,13 @@ def generate_rsa_public_and_private(bits=_DEFAULT_RSA_KEY_BITS): generate() enforces a minimum key size of 2048 bits. If 'bits' is unspecified, a 3072-bit RSA key is generated, which is the key size recommended by TUF. - + + >>> public, private = generate_rsa_public_and_private(2048) + >>> tuf.formats.PEMRSA_SCHEMA.matches(public) + True + >>> tuf.formats.PEMRSA_SCHEMA.matches(private) + True + bits: The key size, or key length, of the RSA key. 'bits' must be 2048, or @@ -137,6 +143,16 @@ def create_signature(private_key, data): RFC3447 - RSASSA-PSS http://www.ietf.org/rfc/rfc3447.txt + + >>> public, private = generate_rsa_public_and_private(2048) + >>> data = 'The quick brown fox jumps over the lazy dog' + >>> signature, method = create_signature(private, data) + >>> tuf.formats.NAME_SCHEMA.matches(method) + True + >>> method == 'PyCrypto-PKCS#1 PSS' + True + >>> signature is not None + True private_key: @@ -162,7 +178,6 @@ def create_signature(private_key, data): # Signing the 'data' object requires a private key. # The 'PyCrypto-PKCS#1 PSS' (i.e., PyCrypto module) signing method is the # only method currently supported. - private = private_key method = 'PyCrypto-PKCS#1 PSS' signature = None @@ -177,7 +192,7 @@ def create_signature(private_key, data): rsa_key_object = Crypto.PublicKey.RSA.importKey(private_key) sha256_object = Crypto.Hash.SHA256.new(data) pkcs1_pss_signer = Crypto.Signature.PKCS1_PSS.new(rsa_key_object) - sig = pkcs1_pss_signer.sign(sha256_object) + signature = pkcs1_pss_signer.sign(sha256_object) except (ValueError, IndexError, TypeError), e: message = 'An RSA signature could not be generated.' raise tuf.CryptoError(message) @@ -198,6 +213,14 @@ def verify_signature(signature, signature_method, public_key, data): 'rsakey_dict', the 'method' and 'sig' objects contained in 'signature', and 'data' to complete the verification. Type-checking performed on both 'rsakey_dict' and 'signature'. + + >>> public, private = generate_rsa_public_and_private(2048) + >>> data = 'The quick brown fox jumps over the lazy dog' + >>> signature, method = create_signature(private, data) + >>> verify_signature(signature, method, public, data) + True + >>> verify_signature(signature, method, public, 'bad_data') + False signature: @@ -271,6 +294,12 @@ def create_rsa_encrypted_pem(private_key, passphrase): https://en.wikipedia.org/wiki/Triple_DES https://en.wikipedia.org/wiki/PBKDF2 + >>> public, private = generate_rsa_public_and_private(2048) + >>> passphrase = 'secret' + >>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase) + >>> tuf.formats.PEMRSA_SCHEMA.matches(encrypted_pem) + True + private_key: The public and private keys are in PEM format and stored as strings. @@ -297,7 +326,7 @@ def create_rsa_encrypted_pem(private_key, passphrase): # This check will ensure 'rsakey_dict' has the appropriate number # of objects and object types, and that all dict keys are properly named. # Raise 'tuf.FormatError' if the check fails. - tuf.formats.RSAKEY_SCHEMA.check_match(rsakey_dict) + tuf.formats.PEMRSA_SCHEMA.check_match(private_key) # Does 'signature' have the correct format? tuf.formats.PASSWORD_SCHEMA.check_match(passphrase) @@ -321,7 +350,7 @@ def create_rsa_encrypted_pem(private_key, passphrase): -def create_rsa_from_encrypted_pem(encrypted_pem, passphrase): +def create_rsa_public_and_private_from_encrypted_pem(encrypted_pem, passphrase): """ Return an RSA key in 'tuf.formats.RSAKEY_SCHEMA' format, which has the @@ -338,6 +367,20 @@ def create_rsa_from_encrypted_pem(encrypted_pem, passphrase): Alternatively, key data may be encrypted with AES-CTR-Mode and the passphrase strengthened with PBKDF2+SHA256. See 'keystore.py'. + >>> public, private = generate_rsa_public_and_private(2048) + >>> passphrase = 'secret' + >>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase) + >>> returned_public, returned_private = \ + create_rsa_public_and_private_from_encrypted_pem(encrypted_pem, passphrase) + >>> tuf.formats.PEMRSA_SCHEMA.matches(returned_public) + True + >>> tuf.formats.PEMRSA_SCHEMA.matches(returned_private) + True + >>> public == returned_public + True + >>> private == returned_private + True + encrypted_pem: A byte string in PEM format, where the private key is encrypted. It has