Skip to content
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
22 changes: 22 additions & 0 deletions docs/x509.rst
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,23 @@ X.509 Extensions
[u'www.cryptography.io', u'cryptography.io']


.. class:: IssuerAlternativeName

.. versionadded:: 1.0

Issuer alternative name is an X.509 extension that provides a list of
:ref:`general name <general_name_classes>` instances that provide a set
of identities for the certificate issuer. The object is iterable to
get every element.

.. method:: get_values_for_type(type)

:param type: A :class:`GeneralName` provider. This is one of the
:ref:`general name classes <general_name_classes>`.

:returns: A list of values extracted from the matched general names.


.. class:: AuthorityInformationAccess

.. versionadded:: 0.9
Expand Down Expand Up @@ -1342,6 +1359,11 @@ Extension OIDs
Corresponds to the dotted string ``"2.5.29.17"``. The identifier for the
:class:`SubjectAlternativeName` extension type.

.. data:: OID_ISSUER_ALTERNATIVE_NAME

Corresponds to the dotted string ``"2.5.29.18"``. The identifier for the
:class:`IssuerAlternativeName` extension type.

.. data:: OID_SUBJECT_KEY_IDENTIFIER

Corresponds to the dotted string ``"2.5.29.14"``. The identifier for the
Expand Down
26 changes: 26 additions & 0 deletions src/cryptography/x509.py
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,32 @@ def __ne__(self, other):
return not self == other


class IssuerAlternativeName(object):
def __init__(self, general_names):
self._general_names = GeneralNames(general_names)

def __iter__(self):
return iter(self._general_names)

def __len__(self):
return len(self._general_names)

def get_values_for_type(self, type):
return self._general_names.get_values_for_type(type)

def __repr__(self):
return "<IssuerAlternativeName({0})>".format(self._general_names)

def __eq__(self, other):
if not isinstance(other, IssuerAlternativeName):
return NotImplemented

return self._general_names == other._general_names

def __ne__(self, other):
return not self == other


class AuthorityKeyIdentifier(object):
def __init__(self, key_identifier, authority_cert_issuer,
authority_cert_serial_number):
Expand Down
56 changes: 56 additions & 0 deletions tests/test_x509_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,62 @@ def test_ne(self):
assert gns != object()


class TestIssuerAlternativeName(object):
def test_get_values_for_type(self):
san = x509.IssuerAlternativeName(
[x509.DNSName(u"cryptography.io")]
)
names = san.get_values_for_type(x509.DNSName)
assert names == [u"cryptography.io"]

def test_iter_names(self):
san = x509.IssuerAlternativeName([
x509.DNSName(u"cryptography.io"),
x509.DNSName(u"crypto.local"),
])
assert len(san) == 2
assert list(san) == [
x509.DNSName(u"cryptography.io"),
x509.DNSName(u"crypto.local"),
]

def test_invalid_general_names(self):
with pytest.raises(TypeError):
x509.IssuerAlternativeName(
[x509.DNSName(u"cryptography.io"), "invalid"]
)

def test_repr(self):
san = x509.IssuerAlternativeName(
[
x509.DNSName(u"cryptography.io")
]
)
assert repr(san) == (
"<IssuerAlternativeName("
"<GeneralNames([<DNSName(value=cryptography.io)>])>)>"
)

def test_eq(self):
san = x509.IssuerAlternativeName(
[x509.DNSName(u"cryptography.io")]
)
san2 = x509.IssuerAlternativeName(
[x509.DNSName(u"cryptography.io")]
)
assert san == san2

def test_ne(self):
san = x509.IssuerAlternativeName(
[x509.DNSName(u"cryptography.io")]
)
san2 = x509.IssuerAlternativeName(
[x509.RFC822Name(u"admin@cryptography.io")]
)
assert san != san2
assert san != object()


class TestSubjectAlternativeName(object):
def test_get_values_for_type(self):
san = x509.SubjectAlternativeName(
Expand Down