From e6129b8b5ada30c25e683dafbc2b64b2281b49f2 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Wed, 16 Jan 2019 23:20:41 +0100 Subject: [PATCH 01/11] Revert "Decode smessage (#504)" This reverts commit 3384aa85e0e495427402130e8dc185f66b16283b. Full discussion at https://github.com/pyca/pynacl/pull/504 --- docs/signing.rst | 131 +++--------------------------------------- src/nacl/signing.py | 8 +-- tests/test_signing.py | 37 +----------- 3 files changed, 15 insertions(+), 161 deletions(-) diff --git a/docs/signing.rst b/docs/signing.rst index a7c847e3e..92183acf0 100644 --- a/docs/signing.rst +++ b/docs/signing.rst @@ -17,16 +17,15 @@ use it to validate that your messages are actually authentic. Example ------- -Signing and verifying a message without encoding the key or message - Signer's perspective (:class:`~nacl.signing.SigningKey`) .. testcode:: - from nacl.signing import SigningKey + import nacl.encoding + import nacl.signing # Generate a new random signing key - signing_key = SigningKey.generate() + signing_key = nacl.signing.SigningKey.generate() # Sign a message with the signing key signed = signing_key.sign(b"Attack at Dawn") @@ -35,21 +34,21 @@ Signer's perspective (:class:`~nacl.signing.SigningKey`) verify_key = signing_key.verify_key # Serialize the verify key to send it to a third party - verify_key_bytes = verify_key.encode() + verify_key_hex = verify_key.encode(encoder=nacl.encoding.HexEncoder) Verifier's perspective (:class:`~nacl.signing.VerifyKey`) .. testcode:: - from nacl.signing import VerifyKey + import nacl.signing # Create a VerifyKey object from a hex serialized public key - verify_key = VerifyKey(verify_key_bytes) + verify_key = nacl.signing.VerifyKey(verify_key_hex, + encoder=nacl.encoding.HexEncoder) # Check the validity of a message's signature - # The message and the signature can either be passed together, or - # separately if the signature is decoded to raw bytes. - # These are equivalent: + # The message and the signature can either be passed separately or + # concatenated together. These are equivalent: verify_key.verify(signed) verify_key.verify(signed.message, signed.signature) @@ -66,118 +65,6 @@ Verifier's perspective (:class:`~nacl.signing.VerifyKey`) nacl.exceptions.BadSignatureError: Signature was forged or corrupt -Example -------- - -Signing and verifying a message encoded with HexEncoder - -Signer's perspective (:class:`~nacl.signing.SigningKey`) - -.. testcode:: - - from nacl.encoding import HexEncoder - from nacl.signing import SigningKey - - # Generate a new random signing key - signing_key = SigningKey.generate() - - # Sign a message with the signing key - signed_hex = signing_key.sign(b"Attack at Dawn", encoder=HexEncoder) - - # Obtain the verify key for a given signing key - verify_key = signing_key.verify_key - - # Serialize the verify key to send it to a third party - verify_key_hex = verify_key.encode(encoder=HexEncoder) - -Verifier's perspective (:class:`~nacl.signing.VerifyKey`) - -.. testcode:: - - from nacl.encoding import HexEncoder - from nacl.signing import VerifyKey - - # Create a VerifyKey object from a hex serialized public key - verify_key = VerifyKey(verify_key_hex, encoder=HexEncoder) - - # Check the validity of a message's signature - # The message and the signature can either be passed together, or - # separately if the signature is decoded to raw bytes. - # These are equivalent: - verify_key.verify(signed_hex, encoder=HexEncoder) - signature_bytes = HexEncoder.decode(signed_hex.signature) - verify_key.verify(signed_hex.message, signature_bytes, - encoder=HexEncoder) - - # Alter the signed message text - forged = signed_hex[:-1] + bytes([int(signed_hex[-1]) ^ 1]) - # Will raise nacl.exceptions.BadSignatureError, since the signature check - # is failing - verify_key.verify(forged) - -.. testoutput:: - - Traceback (most recent call last): - ... - nacl.exceptions.BadSignatureError: Signature was forged or corrupt - - -Example -------- - -Signing and verifying a message encoded with Base64Encoder - -Signer's perspective (:class:`~nacl.signing.SigningKey`) - -.. testcode:: - - from nacl.encoding import Base64Encoder - from nacl.signing import SigningKey - - # Generate a new random signing key - signing_key = SigningKey.generate() - - # Sign a message with the signing key - signed_b64 = signing_key.sign(b"Attack at Dawn", encoder=Base64Encoder) - - # Obtain the verify key for a given signing key - verify_key = signing_key.verify_key - - # Serialize the verify key to send it to a third party - verify_key_b64 = verify_key.encode(encoder=Base64Encoder) - -Verifier's perspective (:class:`~nacl.signing.VerifyKey`) - -.. testcode:: - - from nacl.encoding import Base64Encoder - from nacl.signing import VerifyKey - - # Create a VerifyKey object from a base64 serialized public key - verify_key = VerifyKey(verify_key_b64, encoder=Base64Encoder) - - # Check the validity of a message's signature - # The message and the signature can either be passed together, or - # separately if the signature is decoded to raw bytes. - # These are equivalent: - verify_key.verify(signed_b64, encoder=Base64Encoder) - signature_bytes = Base64Encoder.decode(signed_b64.signature) - verify_key.verify(signed_b64.message, signature_bytes, - encoder=Base64Encoder) - - # Alter the signed message text - forged = signed_b64[:-1] + bytes([int(signed_b64[-1]) ^ 1]) - # Will raise nacl.exceptions.BadSignatureError, since the signature check - # is failing - verify_key.verify(forged) - -.. testoutput:: - - Traceback (most recent call last): - ... - nacl.exceptions.BadSignatureError: Signature was forged or corrupt - - Reference --------- diff --git a/src/nacl/signing.py b/src/nacl/signing.py index 497fd3352..b99a99015 100644 --- a/src/nacl/signing.py +++ b/src/nacl/signing.py @@ -104,10 +104,10 @@ def verify(self, smessage, signature=None, encoder=encoding.RawEncoder): if signature is not None: # If we were given the message and signature separately, combine # them. - smessage = signature + encoder.decode(smessage) - else: - # Decode the signed message - smessage = encoder.decode(smessage) + smessage = signature + smessage + + # Decode the signed message + smessage = encoder.decode(smessage) return nacl.bindings.crypto_sign_open(smessage, self._key) diff --git a/tests/test_signing.py b/tests/test_signing.py index 4304afb92..676d11b72 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -21,7 +21,7 @@ from utils import assert_equal, assert_not_equal, read_crypto_test_vectors from nacl.bindings import crypto_sign_PUBLICKEYBYTES, crypto_sign_SEEDBYTES -from nacl.encoding import Base64Encoder, HexEncoder +from nacl.encoding import HexEncoder from nacl.exceptions import BadSignatureError from nacl.signing import SignedMessage, SigningKey, VerifyKey @@ -149,8 +149,7 @@ def test_valid_signed_message( key.verify(signed, encoder=HexEncoder), ) == message assert binascii.hexlify( - key.verify(message, HexEncoder.decode(signature), - encoder=HexEncoder), + key.verify(message, signature, encoder=HexEncoder), ) == message def test_invalid_signed_message(self): @@ -168,38 +167,6 @@ def test_invalid_signed_message(self): forged = SignedMessage(signature + message) skey.verify_key.verify(forged) - def test_base64_smessage_with_detached_sig_matches_with_attached_sig(self): - sk = SigningKey.generate() - vk = sk.verify_key - - smsg = sk.sign(b"Hello World in base64", encoder=Base64Encoder) - - msg = smsg.message - b64sig = smsg.signature - - sig = Base64Encoder.decode(b64sig) - - assert vk.verify(msg, sig, encoder=Base64Encoder) == \ - vk.verify(smsg, encoder=Base64Encoder) - - assert Base64Encoder.decode(msg) == b"Hello World in base64" - - def test_hex_smessage_with_detached_sig_matches_with_attached_sig(self): - sk = SigningKey.generate() - vk = sk.verify_key - - smsg = sk.sign(b"Hello World in hex", encoder=HexEncoder) - - msg = smsg.message - hexsig = smsg.signature - - sig = HexEncoder.decode(hexsig) - - assert vk.verify(msg, sig, encoder=HexEncoder) == \ - vk.verify(smsg, encoder=HexEncoder) - - assert HexEncoder.decode(msg) == b"Hello World in hex" - def test_key_conversion(self): keypair_seed = (b"421151a459faeade3d247115f94aedae" b"42318124095afabe4d1451a559faedee") From f9d82d854afee3699667b5507263b7fc2600240b Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 13 Apr 2019 12:47:13 +0200 Subject: [PATCH 02/11] Add a pynacl specific deprecation warning --- src/nacl/utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nacl/utils.py b/src/nacl/utils.py index 552b1edb3..cc41ffc8c 100644 --- a/src/nacl/utils.py +++ b/src/nacl/utils.py @@ -1,4 +1,4 @@ -# Copyright 2013 Donald Stufft and individual contributors +# Copyright 2013-2019 Donald Stufft and individual contributors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,6 +19,10 @@ import six +class PyNaclDeprecated(UserWarning): + pass + + class EncryptedMessage(bytes): """ A bytes subclass that holds a messaged that has been encrypted by a From f6e1b6cc94391209ef32b2a35a2d165bb5fbfa74 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 13 Apr 2019 12:49:17 +0200 Subject: [PATCH 03/11] Deprecate encoder= calling parameter --- src/nacl/signing.py | 53 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/nacl/signing.py b/src/nacl/signing.py index b99a99015..a4e2e0fa9 100644 --- a/src/nacl/signing.py +++ b/src/nacl/signing.py @@ -14,12 +14,14 @@ from __future__ import absolute_import, division, print_function +from warnings import warn + import nacl.bindings from nacl import encoding from nacl import exceptions as exc from nacl.public import (PrivateKey as _Curve25519_PrivateKey, PublicKey as _Curve25519_PublicKey) -from nacl.utils import StringFixer, random +from nacl.utils import PyNaclDeprecated, StringFixer, random class SignedMessage(bytes): @@ -59,7 +61,15 @@ class VerifyKey(encoding.Encodable, StringFixer, object): :param encoder: A class that is able to decode the `key` """ - def __init__(self, key, encoder=encoding.RawEncoder): + def __init__(self, key, **kwargs): + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs: + warn(("Implicit encoding/decoding of signing keys " + "is deprecated and will get removed in a future release. " + "Remove explicit 'encoder={}' calling parameter").format( + encoder.__class__), + PyNaclDeprecated) # Decode the key key = encoder.decode(key) if not isinstance(key, bytes): @@ -87,7 +97,7 @@ def __eq__(self, other): def __ne__(self, other): return not (self == other) - def verify(self, smessage, signature=None, encoder=encoding.RawEncoder): + def verify(self, smessage, signature=None, **kwargs): """ Verifies the signature of a signed message, returning the message if it has not been tampered with else raising @@ -101,6 +111,15 @@ def verify(self, smessage, signature=None, encoder=encoding.RawEncoder): signature. :rtype: :class:`bytes` """ + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs: + warn(("Automatic encoding/decoding of signed messages " + "is deprecated and will get removed in a future release. " + "Remove explicit 'encoder={}' calling parameter").format( + encoder.__class__), + PyNaclDeprecated) + if signature is not None: # If we were given the message and signature separately, combine # them. @@ -141,7 +160,17 @@ class SigningKey(encoding.Encodable, StringFixer, object): (i.e. public) key that corresponds with this signing key. """ - def __init__(self, seed, encoder=encoding.RawEncoder): + def __init__(self, seed, **kwargs): + + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs: + warn(("Implicit encoding/decoding of signing keys " + "is deprecated and will get removed in a future release. " + "Remove explicit 'encoder={}' calling parameter").format( + encoder.__class__), + PyNaclDeprecated) + # Decode the seed seed = encoder.decode(seed) if not isinstance(seed, bytes): @@ -182,12 +211,9 @@ def generate(cls): :rtype: :class:`~nacl.signing.SigningKey` """ - return cls( - random(nacl.bindings.crypto_sign_SEEDBYTES), - encoder=encoding.RawEncoder, - ) + return cls(random(nacl.bindings.crypto_sign_SEEDBYTES)) - def sign(self, message, encoder=encoding.RawEncoder): + def sign(self, message, **kwargs): """ Sign a message using this key. @@ -195,6 +221,15 @@ def sign(self, message, encoder=encoding.RawEncoder): :param encoder: A class that is used to encode the signed message. :rtype: :class:`~nacl.signing.SignedMessage` """ + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs: + warn(("Automatic encoding/decoding of signed messages " + "is deprecated and will get removed in a future release. " + "Remove explicit 'encoder={}' calling parameter").format( + encoder.__class__), + PyNaclDeprecated) + raw_signed = nacl.bindings.crypto_sign(message, self._signing_key) crypto_sign_BYTES = nacl.bindings.crypto_sign_BYTES From ad54d889ed887c6eb942a529fcd695b89e452da6 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 13 Apr 2019 12:52:10 +0200 Subject: [PATCH 04/11] Adapt test to deprecation of encoder= parameter --- tests/test_signing.py | 56 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/tests/test_signing.py b/tests/test_signing.py index 676d11b72..b8ef55c2e 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -24,6 +24,7 @@ from nacl.encoding import HexEncoder from nacl.exceptions import BadSignatureError from nacl.signing import SignedMessage, SigningKey, VerifyKey +from nacl.utils import PyNaclDeprecated def tohex(b): @@ -78,30 +79,37 @@ def test_different_keys_are_not_equal(self, k2): k1 = SigningKey(b"\x00" * crypto_sign_SEEDBYTES) assert_not_equal(k1, k2) - @pytest.mark.parametrize("seed", [ + @pytest.mark.parametrize("hseed", [ b"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", ]) - def test_initialization_with_seed(self, seed): - SigningKey(seed, encoder=HexEncoder) + def test_initialization_with_seed(self, hseed): + seed = binascii.unhexlify(hseed) + SigningKey(seed) @pytest.mark.parametrize( - ("seed", "_public_key", "message", "signature", "expected"), + ("hseed", "_public_key", "message", "signature", "expected"), ed25519_known_answers() ) - def test_message_signing(self, seed, _public_key, + def test_message_signing(self, hseed, _public_key, message, signature, expected): - signing_key = SigningKey( - seed, - encoder=HexEncoder, - ) + seed = binascii.unhexlify(hseed) + signing_key = SigningKey(seed) signed = signing_key.sign( binascii.unhexlify(message), - encoder=HexEncoder, ) - assert signed == expected - assert signed.message == message - assert signed.signature == signature + assert signed == binascii.unhexlify(expected) + assert signed.message == binascii.unhexlify(message) + assert signed.signature == binascii.unhexlify(signature) + + @pytest.mark.parametrize("hseed", [ + b"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + ]) + def test_initialization_with_internal_decode_of_seed(self, hseed): + with pytest.warns(PyNaclDeprecated): + SigningKey(hseed, + encoder=HexEncoder, + ) class TestVerifyKey: @@ -135,22 +143,20 @@ def test_different_keys_are_not_equal(self, k2): assert_not_equal(k1, k2) @pytest.mark.parametrize( - ("_seed", "public_key", "message", "signature", "signed"), + ("_seed", "hpublic_key", "hmessage", "hsignature", "hsigned"), ed25519_known_answers() ) def test_valid_signed_message( - self, _seed, public_key, message, signature, signed): - key = VerifyKey( - public_key, - encoder=HexEncoder, - ) + self, _seed, hpublic_key, hmessage, hsignature, hsigned): + public_key = binascii.unhexlify(hpublic_key) + key = VerifyKey(public_key) + + signed = binascii.unhexlify(hsigned) + message = binascii.unhexlify(hmessage) + signature = binascii.unhexlify(hsignature) - assert binascii.hexlify( - key.verify(signed, encoder=HexEncoder), - ) == message - assert binascii.hexlify( - key.verify(message, signature, encoder=HexEncoder), - ) == message + assert key.verify(signed) == message + assert key.verify(message, signature) == message def test_invalid_signed_message(self): skey = SigningKey.generate() From ba0cde494c1e4ff0b685c4075a6ec014e259224c Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 13 Apr 2019 13:24:33 +0200 Subject: [PATCH 05/11] Adapt example and doc to encoder-less API --- docs/signing.rst | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/docs/signing.rst b/docs/signing.rst index 92183acf0..6f6e2a446 100644 --- a/docs/signing.rst +++ b/docs/signing.rst @@ -34,7 +34,7 @@ Signer's perspective (:class:`~nacl.signing.SigningKey`) verify_key = signing_key.verify_key # Serialize the verify key to send it to a third party - verify_key_hex = verify_key.encode(encoder=nacl.encoding.HexEncoder) + verify_key_hex = nacl.encoding.HexEncoder.encode(bytes(verify_key)) Verifier's perspective (:class:`~nacl.signing.VerifyKey`) @@ -43,8 +43,8 @@ Verifier's perspective (:class:`~nacl.signing.VerifyKey`) import nacl.signing # Create a VerifyKey object from a hex serialized public key - verify_key = nacl.signing.VerifyKey(verify_key_hex, - encoder=nacl.encoding.HexEncoder) + decoded_key = nacl.encoding.HexEncoder.decode(verify_key_hex) + verify_key = nacl.signing.VerifyKey(decoded_key) # Check the validity of a message's signature # The message and the signature can either be passed separately or @@ -68,7 +68,7 @@ Verifier's perspective (:class:`~nacl.signing.VerifyKey`) Reference --------- -.. class:: SigningKey(seed, encoder) +.. class:: SigningKey(seed) Private key for producing digital signatures using the Ed25519 algorithm. @@ -81,7 +81,6 @@ Reference masquerade as you. :param bytes seed: Random 32-byte value (i.e. private key). - :param encoder: A class that is able to decode the ``seed``. .. attribute:: verify_key @@ -94,24 +93,22 @@ Reference :return: An instance of :class:`~nacl.signing.SigningKey`. - .. method:: sign(message, encoder) + .. method:: sign(message) Sign a message using this key. :param bytes message: The data to be signed. - :param encoder: A class that is able to decode the signed message. :return: An instance of :class:`~nacl.signing.SignedMessage`. -.. class:: VerifyKey(key, encoder) +.. class:: VerifyKey(key) The public key counterpart to an Ed25519 :class:`~nacl.signing.SigningKey` for producing digital signatures. :param bytes key: A serialized Ed25519 public key. - :param encoder: A class that is able to decode the ``key``. - .. method:: verify(smessage, signature, encoder) + .. method:: verify(smessage, signature) Verifies the signature of a signed message. @@ -120,8 +117,6 @@ Reference :param bytes signature: The signature of the message to verify against. If the value of ``smessage`` is the concated signature and message, this parameter can be ``None``. - :param encoder: A class that is able to decode the secret message and - signature. :return bytes: The message if successfully verified. From daef2ada6c30b2b13ff6eb393154792169351aa6 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 13 Apr 2019 14:33:40 +0200 Subject: [PATCH 06/11] Add missing tests for expected warnings --- tests/test_signing.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/test_signing.py b/tests/test_signing.py index b8ef55c2e..56cf8fba4 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -105,11 +105,16 @@ def test_message_signing(self, hseed, _public_key, @pytest.mark.parametrize("hseed", [ b"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", ]) - def test_initialization_with_internal_decode_of_seed(self, hseed): + def test_deprecation_of_encoder_parameter(self, hseed): with pytest.warns(PyNaclDeprecated): SigningKey(hseed, encoder=HexEncoder, ) + sk = SigningKey.generate() + unsigned = b"A test message!" + with pytest.warns(PyNaclDeprecated): + sk.sign(unsigned, + encoder=HexEncoder) class TestVerifyKey: @@ -188,6 +193,20 @@ def test_key_conversion(self): assert tohex(public_key) == ("f1814f0e8ff1043d8a44d25babff3ced" "cae6c22c3edaa48f857ae70de2baae50") + def test_deprecation_of_encoder_parameter(self): + sk = SigningKey.generate() + unsigned = b"A test message!" + signed = sk.sign(unsigned) + hsigned = HexEncoder.encode(signed) + hpub = HexEncoder.encode(bytes(sk.verify_key)) + with pytest.warns(PyNaclDeprecated): + VerifyKey(hpub, + encoder=HexEncoder, + ) + with pytest.warns(PyNaclDeprecated): + sk.verify_key.verify(hsigned, + encoder=HexEncoder) + def check_type_error(expected, f, *args): with pytest.raises(TypeError) as e: From 0d117ac80a4daf9f21c8ff0602bbf1b19bee23e0 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Mon, 15 Apr 2019 09:41:46 +0200 Subject: [PATCH 07/11] Also deal with encoder passed-in as a argument --- src/nacl/signing.py | 50 +++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/nacl/signing.py b/src/nacl/signing.py index a4e2e0fa9..ef13d09e1 100644 --- a/src/nacl/signing.py +++ b/src/nacl/signing.py @@ -61,10 +61,15 @@ class VerifyKey(encoding.Encodable, StringFixer, object): :param encoder: A class that is able to decode the `key` """ - def __init__(self, key, **kwargs): - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs: + def __init__(self, key, *args, **kwargs): + if len(args) == 1: + encoder = args[0] + elif len(args) > 1: + raise TypeError("Too many arguments") + else: + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs or len(args) > 0: warn(("Implicit encoding/decoding of signing keys " "is deprecated and will get removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( @@ -97,7 +102,7 @@ def __eq__(self, other): def __ne__(self, other): return not (self == other) - def verify(self, smessage, signature=None, **kwargs): + def verify(self, smessage, signature=None, *args, **kwargs): """ Verifies the signature of a signed message, returning the message if it has not been tampered with else raising @@ -111,9 +116,14 @@ def verify(self, smessage, signature=None, **kwargs): signature. :rtype: :class:`bytes` """ - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs: + if len(args) == 1: + encoder = args[0] + elif len(args) > 1: + raise TypeError("Too many arguments") + else: + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs or len(args) > 0: warn(("Automatic encoding/decoding of signed messages " "is deprecated and will get removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( @@ -160,11 +170,16 @@ class SigningKey(encoding.Encodable, StringFixer, object): (i.e. public) key that corresponds with this signing key. """ - def __init__(self, seed, **kwargs): + def __init__(self, seed, *args, **kwargs): - encoder = kwargs.get('encoder', encoding.RawEncoder) + if len(args) == 1: + encoder = args[0] + elif len(args) > 1: + raise TypeError("Too many arguments") + else: + encoder = kwargs.get('encoder', encoding.RawEncoder) - if 'encoder' in kwargs: + if 'encoder' in kwargs or len(args) > 0: warn(("Implicit encoding/decoding of signing keys " "is deprecated and will get removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( @@ -213,7 +228,7 @@ def generate(cls): """ return cls(random(nacl.bindings.crypto_sign_SEEDBYTES)) - def sign(self, message, **kwargs): + def sign(self, message, *args, **kwargs): """ Sign a message using this key. @@ -221,9 +236,14 @@ def sign(self, message, **kwargs): :param encoder: A class that is used to encode the signed message. :rtype: :class:`~nacl.signing.SignedMessage` """ - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs: + if len(args) == 1: + encoder = args[0] + elif len(args) > 1: + raise TypeError("Too many arguments") + else: + encoder = kwargs.get('encoder', encoding.RawEncoder) + + if 'encoder' in kwargs or len(args) > 0: warn(("Automatic encoding/decoding of signed messages " "is deprecated and will get removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( From 8d16324898c971bba85dd9ea32177ba1daaa788e Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Mon, 15 Apr 2019 09:43:33 +0200 Subject: [PATCH 08/11] Add tests for encoder as argument. --- tests/test_signing.py | 52 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/tests/test_signing.py b/tests/test_signing.py index 56cf8fba4..d77e5270d 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -110,11 +110,34 @@ def test_deprecation_of_encoder_parameter(self, hseed): SigningKey(hseed, encoder=HexEncoder, ) + with pytest.warns(PyNaclDeprecated): + SigningKey(hseed, + HexEncoder, + ) sk = SigningKey.generate() unsigned = b"A test message!" with pytest.warns(PyNaclDeprecated): sk.sign(unsigned, encoder=HexEncoder) + with pytest.warns(PyNaclDeprecated): + sk.sign(unsigned, + HexEncoder) + + @pytest.mark.parametrize("hseed", [ + b"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + ]) + def test_raising_on_excess_encoder_parameter(self, hseed): + with pytest.raises(TypeError): + SigningKey(hseed, + HexEncoder, + HexEncoder, + ) + sk = SigningKey.generate() + unsigned = b"A test message!" + with pytest.raises(TypeError): + sk.sign(unsigned, + HexEncoder, + HexEncoder) class TestVerifyKey: @@ -196,16 +219,41 @@ def test_key_conversion(self): def test_deprecation_of_encoder_parameter(self): sk = SigningKey.generate() unsigned = b"A test message!" - signed = sk.sign(unsigned) - hsigned = HexEncoder.encode(signed) + with pytest.warns(PyNaclDeprecated): + hsigned = sk.sign(unsigned, encoder=HexEncoder) hpub = HexEncoder.encode(bytes(sk.verify_key)) with pytest.warns(PyNaclDeprecated): VerifyKey(hpub, encoder=HexEncoder, ) + with pytest.warns(PyNaclDeprecated): + VerifyKey(hpub, + HexEncoder, + ) with pytest.warns(PyNaclDeprecated): sk.verify_key.verify(hsigned, encoder=HexEncoder) + with pytest.warns(PyNaclDeprecated): + sk.verify_key.verify(hsigned.message, + hsigned.signature, + HexEncoder) + + def test_raising_on_excess_encoder_parameter(self): + sk = SigningKey.generate() + unsigned = b"A test message!" + with pytest.warns(PyNaclDeprecated): + hsigned = sk.sign(unsigned, encoder=HexEncoder) + hpub = HexEncoder.encode(bytes(sk.verify_key)) + with pytest.raises(TypeError): + VerifyKey(hpub, + HexEncoder, + HexEncoder, + ) + with pytest.raises(TypeError): + sk.verify_key.verify(hsigned.message, + hsigned.signature, + HexEncoder, + HexEncoder) def check_type_error(expected, f, *args): From 7652934908e665625dee8797d274e30d0ee6dae3 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 18 May 2019 17:29:53 +0200 Subject: [PATCH 09/11] Fix docstring grammar --- src/nacl/signing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nacl/signing.py b/src/nacl/signing.py index ef13d09e1..a2e1d3b43 100644 --- a/src/nacl/signing.py +++ b/src/nacl/signing.py @@ -71,7 +71,7 @@ def __init__(self, key, *args, **kwargs): if 'encoder' in kwargs or len(args) > 0: warn(("Implicit encoding/decoding of signing keys " - "is deprecated and will get removed in a future release. " + "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( encoder.__class__), PyNaclDeprecated) @@ -125,7 +125,7 @@ def verify(self, smessage, signature=None, *args, **kwargs): if 'encoder' in kwargs or len(args) > 0: warn(("Automatic encoding/decoding of signed messages " - "is deprecated and will get removed in a future release. " + "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( encoder.__class__), PyNaclDeprecated) @@ -181,7 +181,7 @@ def __init__(self, seed, *args, **kwargs): if 'encoder' in kwargs or len(args) > 0: warn(("Implicit encoding/decoding of signing keys " - "is deprecated and will get removed in a future release. " + "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( encoder.__class__), PyNaclDeprecated) @@ -245,7 +245,7 @@ def sign(self, message, *args, **kwargs): if 'encoder' in kwargs or len(args) > 0: warn(("Automatic encoding/decoding of signed messages " - "is deprecated and will get removed in a future release. " + "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( encoder.__class__), PyNaclDeprecated) From a75cb45f35d17529ebc316dc72f8691fa360a537 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sat, 18 May 2019 18:23:02 +0200 Subject: [PATCH 10/11] Simplified deprecation for encoder= parameter --- src/nacl/signing.py | 56 +++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/nacl/signing.py b/src/nacl/signing.py index a2e1d3b43..1ace5fdf3 100644 --- a/src/nacl/signing.py +++ b/src/nacl/signing.py @@ -58,18 +58,13 @@ class VerifyKey(encoding.Encodable, StringFixer, object): signatures. :param key: [:class:`bytes`] Serialized Ed25519 public key - :param encoder: A class that is able to decode the `key` + :param encoder: (Deprecated) A class that is able to decode the `key` """ - def __init__(self, key, *args, **kwargs): - if len(args) == 1: - encoder = args[0] - elif len(args) > 1: - raise TypeError("Too many arguments") + def __init__(self, key, encoder=None): + if encoder is None: + encoder = encoding.RawEncoder else: - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs or len(args) > 0: warn(("Implicit encoding/decoding of signing keys " "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( @@ -102,7 +97,7 @@ def __eq__(self, other): def __ne__(self, other): return not (self == other) - def verify(self, smessage, signature=None, *args, **kwargs): + def verify(self, smessage, signature=None, encoder=None): """ Verifies the signature of a signed message, returning the message if it has not been tampered with else raising @@ -112,18 +107,13 @@ def verify(self, smessage, signature=None, *args, **kwargs): signature and message concated together. :param signature: [:class:`bytes`] If an unsigned message is given for smessage then the detached signature must be provided. - :param encoder: A class that is able to decode the secret message and - signature. + :param encoder: (Deprecated) A class that is able to decode the secret + message and signature. :rtype: :class:`bytes` """ - if len(args) == 1: - encoder = args[0] - elif len(args) > 1: - raise TypeError("Too many arguments") + if encoder is None: + encoder = encoding.RawEncoder else: - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs or len(args) > 0: warn(("Automatic encoding/decoding of signed messages " "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( @@ -164,22 +154,16 @@ class SigningKey(encoding.Encodable, StringFixer, object): masquerade as you. :param seed: [:class:`bytes`] Random 32-byte value (i.e. private key) - :param encoder: A class that is able to decode the seed + :param encoder: (Deprecated) A class that is able to decode the seed :ivar: verify_key: [:class:`~nacl.signing.VerifyKey`] The verify (i.e. public) key that corresponds with this signing key. """ - def __init__(self, seed, *args, **kwargs): - - if len(args) == 1: - encoder = args[0] - elif len(args) > 1: - raise TypeError("Too many arguments") + def __init__(self, seed, encoder=None): + if encoder is None: + encoder = encoding.RawEncoder else: - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs or len(args) > 0: warn(("Implicit encoding/decoding of signing keys " "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( @@ -228,22 +212,18 @@ def generate(cls): """ return cls(random(nacl.bindings.crypto_sign_SEEDBYTES)) - def sign(self, message, *args, **kwargs): + def sign(self, message, encoder=None): """ Sign a message using this key. :param message: [:class:`bytes`] The data to be signed. - :param encoder: A class that is used to encode the signed message. + :param encoder: (Deprecated) A class that is used to encode + the signed message. :rtype: :class:`~nacl.signing.SignedMessage` """ - if len(args) == 1: - encoder = args[0] - elif len(args) > 1: - raise TypeError("Too many arguments") + if encoder is None: + encoder = encoding.RawEncoder else: - encoder = kwargs.get('encoder', encoding.RawEncoder) - - if 'encoder' in kwargs or len(args) > 0: warn(("Automatic encoding/decoding of signed messages " "is deprecated and will be removed in a future release. " "Remove explicit 'encoder={}' calling parameter").format( From 627ae1af74d353325e74f8542d3617d451e220c1 Mon Sep 17 00:00:00 2001 From: "Lorenzo M. Catucci" Date: Sun, 19 May 2019 00:04:41 +0200 Subject: [PATCH 11/11] Revert "Add tests for encoder as argument." 8d1632 Since, after a75cb45f35d17529ebc316dc72f8691fa360a537, those test are redundant. --- tests/test_signing.py | 52 ++----------------------------------------- 1 file changed, 2 insertions(+), 50 deletions(-) diff --git a/tests/test_signing.py b/tests/test_signing.py index d77e5270d..56cf8fba4 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -110,34 +110,11 @@ def test_deprecation_of_encoder_parameter(self, hseed): SigningKey(hseed, encoder=HexEncoder, ) - with pytest.warns(PyNaclDeprecated): - SigningKey(hseed, - HexEncoder, - ) sk = SigningKey.generate() unsigned = b"A test message!" with pytest.warns(PyNaclDeprecated): sk.sign(unsigned, encoder=HexEncoder) - with pytest.warns(PyNaclDeprecated): - sk.sign(unsigned, - HexEncoder) - - @pytest.mark.parametrize("hseed", [ - b"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", - ]) - def test_raising_on_excess_encoder_parameter(self, hseed): - with pytest.raises(TypeError): - SigningKey(hseed, - HexEncoder, - HexEncoder, - ) - sk = SigningKey.generate() - unsigned = b"A test message!" - with pytest.raises(TypeError): - sk.sign(unsigned, - HexEncoder, - HexEncoder) class TestVerifyKey: @@ -219,41 +196,16 @@ def test_key_conversion(self): def test_deprecation_of_encoder_parameter(self): sk = SigningKey.generate() unsigned = b"A test message!" - with pytest.warns(PyNaclDeprecated): - hsigned = sk.sign(unsigned, encoder=HexEncoder) + signed = sk.sign(unsigned) + hsigned = HexEncoder.encode(signed) hpub = HexEncoder.encode(bytes(sk.verify_key)) with pytest.warns(PyNaclDeprecated): VerifyKey(hpub, encoder=HexEncoder, ) - with pytest.warns(PyNaclDeprecated): - VerifyKey(hpub, - HexEncoder, - ) with pytest.warns(PyNaclDeprecated): sk.verify_key.verify(hsigned, encoder=HexEncoder) - with pytest.warns(PyNaclDeprecated): - sk.verify_key.verify(hsigned.message, - hsigned.signature, - HexEncoder) - - def test_raising_on_excess_encoder_parameter(self): - sk = SigningKey.generate() - unsigned = b"A test message!" - with pytest.warns(PyNaclDeprecated): - hsigned = sk.sign(unsigned, encoder=HexEncoder) - hpub = HexEncoder.encode(bytes(sk.verify_key)) - with pytest.raises(TypeError): - VerifyKey(hpub, - HexEncoder, - HexEncoder, - ) - with pytest.raises(TypeError): - sk.verify_key.verify(hsigned.message, - hsigned.signature, - HexEncoder, - HexEncoder) def check_type_error(expected, f, *args):