Skip to content

_set_signature_type returning "Unsupported signing algorithm info" due to isinstance check #793

@jvan1997

Description

@jvan1997

Security issue notifications

If you discover a potential security issue in the AWS Encryption SDK we ask that you notify AWS Security via our vulnerability reporting page. Please do not create a public GitHub issue.

Problem:

aws-encryption-sdk version 4.x introduced a regression in _set_signature_type() via PR #467 (specific line) that replaced a verify_interface call with a bare isinstance check:

def _set_signature_type(self):
    if not isinstance(self.algorithm.signing_algorithm_info, type(ec.EllipticCurve)):
        raise NotSupportedError("Unsupported signing algorithm info")
    return ec.EllipticCurve

type(ec.EllipticCurve) evaluates to ABCMeta. This worked when cryptography implemented EC curve classes as pure Python ABCs, where isinstance(ec.SECP384R1, ABCMeta) returned True because the class itself is an instance of its metaclass.

However, in newer versions of cryptography, ec.SECP384R1 is backed by Rust internals via rust_openssl, and its metaclass is type, not ABCMeta. This causes both of the following to return False at runtime:

isinstance(ec.SECP384R1, type(ec.EllipticCurve))  # False — metaclass is 'type', not ABCMeta
isinstance(ec.SECP384R1, ec.EllipticCurve)         # False — it's a class, not an instance

This raises NotSupportedError("Unsupported signing algorithm info") when decrypting with AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, which is used by clients such as the Odin encryption client.

ec.SECP384R1 is a valid subclass of ec.EllipticCurve as defined here. The existing issue #625 notes that cryptography>=3.4.6 is required, but the root cause is the metaclass check — not the cryptography version itself.

Solution:

Replace the metaclass-based isinstance check with issubclass, which correctly handles both pure Python ABCs and Rust-backed types:

def _set_signature_type(self):
    try:
        if not issubclass(self.algorithm.signing_algorithm_info, ec.EllipticCurve):
            raise NotSupportedError(
                f"Unsupported signing algorithm info: {self.algorithm.signing_algorithm_info}"
            )
    except TypeError:
        raise NotSupportedError(
            f"Unsupported signing algorithm info: {self.algorithm.signing_algorithm_info}"
        )
    return ec.EllipticCurve

issubclass returns True for any class that is a subclass of ec.EllipticCurve regardless of metaclass, and raises TypeError if the argument is not a class at all, which is caught and re-raised as NotSupportedError.

Additionally, the README/docs should clarify that the cryptography>=3.4.6 minimum exists specifically because of this metaclass behavior change, so consumers understand why the floor exists.

Out of scope:

Does not address any other algorithm suite compatibility issues or cryptography version pinning recommendations beyond _set_signature_type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions