Skip to content

refactor: replace verify_interface with isinstance #467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/aws_encryption_sdk/internal/crypto/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
from cryptography.utils import InterfaceNotImplemented, verify_interface

from ...exceptions import NotSupportedError
from .elliptic_curve import (
Expand Down Expand Up @@ -47,11 +46,9 @@ def __init__(self, algorithm, key):

def _set_signature_type(self):
"""Ensures that the algorithm signature type is a known type and sets a reference value."""
try:
verify_interface(ec.EllipticCurve, self.algorithm.signing_algorithm_info)
return ec.EllipticCurve
except InterfaceNotImplemented:
if not isinstance(self.algorithm.signing_algorithm_info, type(ec.EllipticCurve)):
raise NotSupportedError("Unsupported signing algorithm info")
return ec.EllipticCurve

def _build_hasher(self):
"""Builds the hasher instance which will calculate the digest of all passed data.
Expand Down
17 changes: 7 additions & 10 deletions src/aws_encryption_sdk/internal/crypto/elliptic_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed, decode_dss_signature, encode_dss_signature
from cryptography.utils import InterfaceNotImplemented, int_to_bytes, verify_interface
from cryptography.utils import int_to_bytes

from ...exceptions import NotSupportedError
from ..str_ops import to_bytes

_LOGGER = logging.getLogger(__name__)


# Curve parameter values are included strictly as a temporary measure
# until they can be rolled into the cryptography.io library.
# Expanded values from http://www.secg.org/sec2-v2.pdf
Expand All @@ -44,10 +43,10 @@
order=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973,
),
"secp521r1": _ECCCurveParameters(
p=0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, # noqa pylint: disable=line-too-long
a=0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC, # noqa pylint: disable=line-too-long
b=0x0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00, # noqa pylint: disable=line-too-long
order=0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409, # noqa pylint: disable=line-too-long
p=0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, # noqa pylint: disable=line-too-long
a=0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC, # noqa pylint: disable=line-too-long
b=0x0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00, # noqa pylint: disable=line-too-long
order=0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409, # noqa pylint: disable=line-too-long
),
}

Expand Down Expand Up @@ -182,8 +181,6 @@ def generate_ecc_signing_key(algorithm):
:returns: Generated signing key
:raises NotSupportedError: if signing algorithm is not supported on this platform
"""
try:
verify_interface(ec.EllipticCurve, algorithm.signing_algorithm_info)
return ec.generate_private_key(curve=algorithm.signing_algorithm_info(), backend=default_backend())
except InterfaceNotImplemented:
if not isinstance(algorithm.signing_algorithm_info, type(ec.EllipticCurve)):
raise NotSupportedError("Unsupported signing algorithm info")
return ec.generate_private_key(curve=algorithm.signing_algorithm_info(), backend=default_backend())
41 changes: 31 additions & 10 deletions test/unit/test_crypto_authentication_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ def patch_default_backend(mocker):
yield aws_encryption_sdk.internal.crypto.authentication.default_backend


@pytest.fixture
def patch_ec(mocker):
mocker.patch.object(aws_encryption_sdk.internal.crypto.authentication, "ec")
yield aws_encryption_sdk.internal.crypto.authentication.ec


@pytest.fixture
def patch_serialization(mocker):
mocker.patch.object(aws_encryption_sdk.internal.crypto.authentication, "serialization")
Expand Down Expand Up @@ -71,8 +77,10 @@ def test_f_signer_key_bytes():
assert test.key_bytes() == VALUES["ecc_private_key_prime_private_bytes"]


def test_signer_from_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher):
_algorithm = MagicMock()
def test_signer_from_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec):
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)

signer = Signer.from_key_bytes(algorithm=_algorithm, key_bytes=sentinel.key_bytes)

patch_serialization.load_der_private_key.assert_called_once_with(
Expand All @@ -83,9 +91,11 @@ def test_signer_from_key_bytes(patch_default_backend, patch_serialization, patch
assert signer.key is patch_serialization.load_der_private_key.return_value


def test_signer_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher):
def test_signer_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec):
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
private_key = MagicMock()
signer = Signer(MagicMock(), key=private_key)
signer = Signer(algorithm, key=private_key)

test = signer.key_bytes()

Expand All @@ -98,30 +108,41 @@ def test_signer_key_bytes(patch_default_backend, patch_serialization, patch_buil


def test_signer_encoded_public_key(
patch_default_backend, patch_serialization, patch_build_hasher, patch_ecc_encode_compressed_point, patch_base64
patch_default_backend,
patch_serialization,
patch_build_hasher,
patch_ecc_encode_compressed_point,
patch_base64,
patch_ec
):
patch_ecc_encode_compressed_point.return_value = sentinel.compressed_point
patch_base64.b64encode.return_value = sentinel.encoded_point
private_key = MagicMock()

signer = Signer(MagicMock(), key=private_key)
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)

signer = Signer(algorithm, key=private_key)
test_key = signer.encoded_public_key()

patch_ecc_encode_compressed_point.assert_called_once_with(private_key)
patch_base64.b64encode.assert_called_once_with(sentinel.compressed_point)
assert test_key == sentinel.encoded_point


def test_signer_update(patch_default_backend, patch_serialization, patch_build_hasher):
signer = Signer(MagicMock(), key=MagicMock())
def test_signer_update(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec):
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
signer = Signer(algorithm, key=MagicMock())
signer.update(sentinel.data)
patch_build_hasher.return_value.update.assert_called_once_with(sentinel.data)


def test_signer_finalize(
patch_default_backend, patch_serialization, patch_build_hasher, patch_ecc_static_length_signature
patch_default_backend, patch_serialization, patch_build_hasher, patch_ecc_static_length_signature, patch_ec
):
algorithm = MagicMock()
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
private_key = MagicMock()

signer = Signer(algorithm, key=private_key)
Expand Down
16 changes: 10 additions & 6 deletions test/unit/test_crypto_authentication_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def test_f_verifier_key_bytes():
def test_verifier_from_encoded_point(
patch_default_backend,
patch_serialization,
patch_ec,
patch_ecc_public_numbers_from_compressed_point,
patch_base64,
patch_build_hasher,
Expand All @@ -94,21 +95,24 @@ def test_verifier_from_encoded_point(
mock_point_instance.public_key.return_value = sentinel.public_key
patch_ecc_public_numbers_from_compressed_point.return_value = mock_point_instance
patch_base64.b64decode.return_value = sentinel.compressed_point
algorithm = MagicMock()
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)

verifier = Verifier.from_encoded_point(algorithm=algorithm, encoded_point=sentinel.encoded_point)
verifier = Verifier.from_encoded_point(algorithm=mock_algorithm, encoded_point=sentinel.encoded_point)

patch_base64.b64decode.assert_called_once_with(sentinel.encoded_point)
algorithm.signing_algorithm_info.assert_called_once_with()
mock_algorithm.signing_algorithm_info.assert_called_once_with()
patch_ecc_public_numbers_from_compressed_point.assert_called_once_with(
curve=algorithm.signing_algorithm_info.return_value, compressed_point=sentinel.compressed_point
curve=mock_algorithm.signing_algorithm_info.return_value, compressed_point=sentinel.compressed_point
)
mock_point_instance.public_key.assert_called_once_with(patch_default_backend.return_value)
assert isinstance(verifier, Verifier)


def test_verifier_update(patch_default_backend, patch_serialization, patch_build_hasher):
verifier = Verifier(algorithm=MagicMock(), key=MagicMock())
def test_verifier_update(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec):
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
verifier = Verifier(algorithm=mock_algorithm, key=MagicMock())
verifier.update(sentinel.data)
verifier._hasher.update.assert_called_once_with(sentinel.data)

Expand Down
9 changes: 3 additions & 6 deletions test/unit/test_crypto_elliptic_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import pytest
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.utils import InterfaceNotImplemented
from mock import MagicMock, sentinel
from pytest_mock import mocker # noqa pylint: disable=unused-import

Expand Down Expand Up @@ -374,22 +373,20 @@ def test_ecc_public_numbers_from_compressed_point(patch_ec, patch_ecc_decode_com
assert test == sentinel.public_numbers_instance


def test_generate_ecc_signing_key_supported(patch_default_backend, patch_ec, patch_verify_interface):
def test_generate_ecc_signing_key_supported(patch_default_backend, patch_ec):
patch_ec.generate_private_key.return_value = sentinel.raw_signing_key
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info)
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)

test_signing_key = generate_ecc_signing_key(algorithm=mock_algorithm)

patch_verify_interface.assert_called_once_with(patch_ec.EllipticCurve, mock_algorithm_info)
patch_ec.generate_private_key.assert_called_once_with(
curve=sentinel.algorithm_info, backend=patch_default_backend.return_value
)
assert test_signing_key is sentinel.raw_signing_key


def test_generate_ecc_signing_key_unsupported(patch_default_backend, patch_ec, patch_verify_interface):
patch_verify_interface.side_effect = InterfaceNotImplemented
def test_generate_ecc_signing_key_unsupported(patch_default_backend, patch_ec):
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info)
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)

Expand Down
18 changes: 4 additions & 14 deletions test/unit/test_crypto_prehashing_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# language governing permissions and limitations under the License.
"""Unit test suite for ``aws_encryption_sdk.internal.crypto._PrehashingAuthenticater``."""
import pytest
from cryptography.utils import InterfaceNotImplemented
from mock import MagicMock, sentinel
from pytest_mock import mocker # noqa pylint: disable=unused-import

Expand All @@ -35,12 +34,6 @@ def patch_build_hasher(mocker):
yield _PrehashingAuthenticator._build_hasher


@pytest.fixture
def patch_cryptography_utils_verify_interface(mocker):
mocker.patch.object(aws_encryption_sdk.internal.crypto.authentication, "verify_interface")
yield aws_encryption_sdk.internal.crypto.authentication.verify_interface


@pytest.fixture
def patch_cryptography_ec(mocker):
mocker.patch.object(aws_encryption_sdk.internal.crypto.authentication, "ec")
Expand Down Expand Up @@ -71,21 +64,18 @@ def test_init(patch_set_signature_type, patch_build_hasher):


def test_set_signature_type_elliptic_curve(
patch_build_hasher, patch_cryptography_utils_verify_interface, patch_cryptography_ec
patch_build_hasher, patch_cryptography_ec
):
mock_algorithm = MagicMock()
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_cryptography_ec.EllipticCurve)
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
test = _PrehashingAuthenticator(algorithm=mock_algorithm, key=sentinel.key)

patch_cryptography_utils_verify_interface.assert_called_once_with(
patch_cryptography_ec.EllipticCurve, mock_algorithm.signing_algorithm_info
)
assert test._signature_type is patch_cryptography_ec.EllipticCurve


def test_set_signature_type_unknown(
patch_build_hasher, patch_cryptography_utils_verify_interface, patch_cryptography_ec
patch_build_hasher, patch_cryptography_ec
):
patch_cryptography_utils_verify_interface.side_effect = InterfaceNotImplemented
with pytest.raises(NotSupportedError) as excinfo:
_PrehashingAuthenticator(algorithm=MagicMock(), key=sentinel.key)

Expand Down
2 changes: 1 addition & 1 deletion test_vector_handlers/src/pylintrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[MESSAGES CONTROL]
[MESSAGE CONTROL]
# Disabling messages that we either don't care about for tests or are necessary to break for tests.
disable =
bad-continuation, # we let black handle this
Expand Down
Loading