Skip to content

Commit ea306f8

Browse files
committed
chore: refactor duplicate code
1 parent e225e8c commit ea306f8

9 files changed

+57
-13
lines changed

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
boto3>=1.10.0
2-
cryptography>=2.5.0
2+
cryptography>=2.5.0,<=3.3.2
33
attrs>=17.4.0
44
wrapt>=1.10.11

src/aws_encryption_sdk/internal/crypto/authentication.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import base64
1515
import logging
1616

17+
from aws_encryption_sdk.internal.utils import verify_interface
1718
from cryptography.hazmat.backends import default_backend
1819
from cryptography.hazmat.primitives import hashes, serialization
1920
from cryptography.hazmat.primitives.asymmetric import ec
@@ -46,9 +47,8 @@ def __init__(self, algorithm, key):
4647

4748
def _set_signature_type(self):
4849
"""Ensures that the algorithm signature type is a known type and sets a reference value."""
49-
for method in ec.EllipticCurve.__abstractmethods__:
50-
if not hasattr(self.algorithm.signing_algorithm_info(), method):
51-
raise NotSupportedError("Unsupported signing algorithm info")
50+
if not verify_interface(self.algorithm):
51+
raise NotSupportedError("Unsupported signing algorithm info")
5252
return ec.EllipticCurve
5353

5454
def _build_hasher(self):

src/aws_encryption_sdk/internal/crypto/elliptic_curve.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from collections import namedtuple
1616

1717
import six
18+
from aws_encryption_sdk.internal.utils import verify_interface
1819
from cryptography.hazmat.backends import default_backend
1920
from cryptography.hazmat.primitives.asymmetric import ec
2021
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed, decode_dss_signature, encode_dss_signature
@@ -183,7 +184,6 @@ def generate_ecc_signing_key(algorithm):
183184
:returns: Generated signing key
184185
:raises NotSupportedError: if signing algorithm is not supported on this platform
185186
"""
186-
for method in ec.EllipticCurve.__abstractmethods__:
187-
if not hasattr(algorithm.signing_algorithm_info(), method):
188-
raise NotSupportedError("Unsupported signing algorithm info")
187+
if not verify_interface(algorithm):
188+
raise NotSupportedError("Unsupported signing algorithm info")
189189
return ec.generate_private_key(curve=algorithm.signing_algorithm_info(), backend=default_backend())

src/aws_encryption_sdk/internal/utils/__init__.py

+15
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from aws_encryption_sdk.identifiers import ContentAADString, ContentType
2323
from aws_encryption_sdk.internal.str_ops import to_bytes
2424
from aws_encryption_sdk.structures import EncryptedDataKey
25+
from cryptography.hazmat.primitives.asymmetric import ec
2526

2627
from .streams import InsistentReaderBytesIO
2728

@@ -161,3 +162,17 @@ def source_data_key_length_check(source_data_key, algorithm):
161162
actual=len(source_data_key.data_key), required=algorithm.kdf_input_len
162163
)
163164
)
165+
166+
167+
def verify_interface(algorithm):
168+
"""Validates that the provided EllipticCurve Algorithm is correctly implemented by
169+
checking if it implements both of the abstract methods from the EllipticCurve
170+
abstract class.
171+
172+
:param algorithm: Algorithm object which directs which Elliptic Curve will be used
173+
:type algorithm: aws_encryption_sdk.identifiers.Algorithm
174+
"""
175+
for method in ec.EllipticCurve.__abstractmethods__:
176+
if not hasattr(algorithm.signing_algorithm_info(), method):
177+
return False
178+
return True

test/unit/test_crypto_authentication_signer.py

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ def test_f_signer_key_bytes():
6868
def test_signer_from_key_bytes(patch_default_backend, patch_serialization, patch_build_hasher, patch_ec):
6969
patch_ec.EllipticCurve.__abstractmethods__ = set()
7070
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
71+
mock_algorithm_info.return_value.name = True
72+
mock_algorithm_info.return_value.key_size = True
7173
_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
7274

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

test/unit/test_crypto_authentication_verifier.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,13 @@ def test_verifier_from_encoded_point(
9898

9999
patch_ec.EllipticCurve.__abstractmethods__ = set()
100100
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
101+
mock_algorithm_info.return_value.name = True
102+
mock_algorithm_info.return_value.key_size = True
101103
algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
102104

103105
verifier = Verifier.from_encoded_point(algorithm=algorithm, encoded_point=sentinel.encoded_point)
104106

105107
patch_base64.b64decode.assert_called_once_with(sentinel.encoded_point)
106-
algorithm.signing_algorithm_info.assert_called_once_with()
107108
patch_ecc_public_numbers_from_compressed_point.assert_called_once_with(
108109
curve=algorithm.signing_algorithm_info.return_value, compressed_point=sentinel.compressed_point
109110
)

test/unit/test_crypto_elliptic_curve.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pytest_mock import mocker # noqa pylint: disable=unused-import
2020

2121
import aws_encryption_sdk.internal.crypto.elliptic_curve
22+
import aws_encryption_sdk.internal.defaults
2223
from aws_encryption_sdk.exceptions import NotSupportedError
2324
from aws_encryption_sdk.internal.crypto.elliptic_curve import (
2425
_ECC_CURVE_PARAMETERS,
@@ -369,8 +370,10 @@ def test_ecc_public_numbers_from_compressed_point(patch_ec, patch_ecc_decode_com
369370

370371
def test_generate_ecc_signing_key_supported(patch_default_backend, patch_ec):
371372
patch_ec.generate_private_key.return_value = sentinel.raw_signing_key
372-
patch_ec.EllipticCurve.__abstractmethods__ = set()
373+
patch_ec.EllipticCurve.__abstractmethods__ = {"key_size", "name"}
373374
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
375+
mock_algorithm_info.return_value.name = MagicMock(return_value=True)
376+
mock_algorithm_info.return_value.key_size = MagicMock(return_value=True)
374377
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
375378

376379
test_signing_key = generate_ecc_signing_key(algorithm=mock_algorithm)
@@ -383,8 +386,9 @@ def test_generate_ecc_signing_key_supported(patch_default_backend, patch_ec):
383386

384387
def test_generate_ecc_signing_key_unsupported(patch_default_backend, patch_ec):
385388
patch_ec.generate_private_key.return_value = sentinel.raw_signing_key
386-
patch_ec.EllipticCurve.__abstractmethods__ = set("notName")
387-
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
389+
mock_algorithm_info = MagicMock(return_value=sentinel.invalid_algorithm_info, spec=patch_ec.EllipticCurve)
390+
mock_algorithm_info.return_value.not_name = MagicMock(return_value=True)
391+
mock_algorithm_info.return_value.not_key_size = MagicMock(return_value=True)
388392
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
389393

390394
with pytest.raises(NotSupportedError) as excinfo:

test/unit/test_crypto_prehashing_authenticator.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def test_set_signature_type_elliptic_curve(
6969
patch_cryptography_ec.generate_private_key.return_value = sentinel.raw_signing_key
7070
patch_cryptography_ec.EllipticCurve.__abstractmethods__ = set()
7171
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_cryptography_ec.EllipticCurve)
72+
mock_algorithm_info.return_value.name = MagicMock(return_value=True)
73+
mock_algorithm_info.return_value.key_size = MagicMock(return_value=True)
7274
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
7375
test = _PrehashingAuthenticator(algorithm=mock_algorithm, key=sentinel.key)
7476

@@ -78,8 +80,9 @@ def test_set_signature_type_elliptic_curve(
7880
def test_set_signature_type_unknown(
7981
patch_build_hasher, patch_cryptography_ec
8082
):
81-
patch_cryptography_ec.EllipticCurve.__abstractmethods__ = set("invalidSetup")
82-
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_cryptography_ec.EllipticCurve)
83+
mock_algorithm_info = MagicMock(return_value=sentinel.not_algorithm_info, spec=patch_cryptography_ec.EllipticCurve)
84+
mock_algorithm_info.return_value.not_name = MagicMock(return_value=True)
85+
mock_algorithm_info.return_value.not_key_size = MagicMock(return_value=True)
8386
mock_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
8487
with pytest.raises(NotSupportedError) as excinfo:
8588
_PrehashingAuthenticator(algorithm=mock_algorithm, key=sentinel.key)

test/unit/test_utils.py

+19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import aws_encryption_sdk.identifiers
2121
import aws_encryption_sdk.internal.utils
22+
from aws_encryption_sdk.internal.utils import verify_interface
2223
from aws_encryption_sdk.exceptions import InvalidDataKeyError, SerializationError, UnknownIdentityError
2324
from aws_encryption_sdk.internal.defaults import MAX_FRAME_SIZE, MESSAGE_ID_LENGTH
2425
from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo, RawDataKey
@@ -29,12 +30,30 @@
2930
pytestmark = [pytest.mark.unit, pytest.mark.local]
3031

3132

33+
@pytest.yield_fixture
34+
def patch_ec(mocker):
35+
mocker.patch.object(aws_encryption_sdk.internal.crypto.authentication, "ec")
36+
yield aws_encryption_sdk.internal.crypto.authentication.ec
37+
38+
3239
def test_prep_stream_data_passthrough():
3340
test = aws_encryption_sdk.internal.utils.prep_stream_data(io.BytesIO(b"some data"))
3441

3542
assert_prepped_stream_identity(test, io.BytesIO)
3643

3744

45+
def test_verify_interface(patch_ec):
46+
patch_ec.EllipticCurve.__abstractmethods__ = set(("key_size", "name"))
47+
mock_algorithm_info = MagicMock(return_value=sentinel.algorithm_info, spec=patch_ec.EllipticCurve)
48+
mock_algorithm_info.return_value.name = True
49+
mock_algorithm_info.return_value.key_size = True
50+
_algorithm = MagicMock(signing_algorithm_info=mock_algorithm_info)
51+
52+
implemented = verify_interface(algorithm=_algorithm)
53+
54+
assert implemented is True
55+
56+
3857
@pytest.mark.parametrize("source", (u"some unicode data ловие", b"\x00\x01\x02"))
3958
def test_prep_stream_data_wrap(source):
4059
test = aws_encryption_sdk.internal.utils.prep_stream_data(source)

0 commit comments

Comments
 (0)