From 890cb7f13a85af1cb9f510c9f231ba3a3110b3e4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 10 Aug 2015 21:05:34 -0500 Subject: move AKI, SKI --- src/cryptography/x509/__init__.py | 7 +- src/cryptography/x509/base.py | 129 -------------------------------- src/cryptography/x509/extensions.py | 144 ++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 131 deletions(-) create mode 100644 src/cryptography/x509/extensions.py (limited to 'src') diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 3e6420e7..389d737b 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -5,7 +5,7 @@ from __future__ import absolute_import, division, print_function from cryptography.x509.base import ( - AccessDescription, AuthorityInformationAccess, AuthorityKeyIdentifier, + AccessDescription, AuthorityInformationAccess, BasicConstraints, CRLDistributionPoints, Certificate, CertificateBuilder, CertificatePolicies, CertificateRevocationList, CertificateSigningRequest, CertificateSigningRequestBuilder, DistributionPoint, @@ -14,10 +14,13 @@ from cryptography.x509.base import ( InvalidVersion, IssuerAlternativeName, KeyUsage, NameConstraints, NoticeReference, OCSPNoCheck, ObjectIdentifier, PolicyInformation, ReasonFlags, - RevokedCertificate, SubjectAlternativeName, SubjectKeyIdentifier, + RevokedCertificate, SubjectAlternativeName, UnsupportedExtension, UserNotice, Version, load_der_x509_certificate, load_der_x509_csr, load_pem_x509_certificate, load_pem_x509_csr, ) +from cryptography.x509.extensions import ( + AuthorityKeyIdentifier, SubjectKeyIdentifier +) from cryptography.x509.general_name import ( DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name, RegisteredID, UniformResourceIdentifier, UnsupportedGeneralNameType, diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 4f0d11ef..b906c7a8 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -6,17 +6,12 @@ from __future__ import absolute_import, division, print_function import abc import datetime -import hashlib import ipaddress from enum import Enum -from pyasn1.codec.der import decoder -from pyasn1.type import namedtype, univ - import six from cryptography import utils -from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa from cryptography.x509.general_name import GeneralName, IPAddress, OtherName from cryptography.x509.name import Name @@ -25,34 +20,6 @@ from cryptography.x509.oid import ( ) -class _SubjectPublicKeyInfo(univ.Sequence): - componentType = namedtype.NamedTypes( - namedtype.NamedType('algorithm', univ.Sequence()), - namedtype.NamedType('subjectPublicKey', univ.BitString()) - ) - - -def _key_identifier_from_public_key(public_key): - # This is a very slow way to do this. - serialized = public_key.public_bytes( - serialization.Encoding.DER, - serialization.PublicFormat.SubjectPublicKeyInfo - ) - spki, remaining = decoder.decode( - serialized, asn1Spec=_SubjectPublicKeyInfo() - ) - assert not remaining - # the univ.BitString object is a tuple of bits. We need bytes and - # pyasn1 really doesn't want to give them to us. To get it we'll - # build an integer and convert that to bytes. - bits = 0 - for bit in spki.getComponentByName("subjectPublicKey"): - bits = bits << 1 | bit - - data = utils.int_to_bytes(bits) - return hashlib.sha1(data).digest() - - _UNIX_EPOCH = datetime.datetime(1970, 1, 1) @@ -533,34 +500,6 @@ class NoticeReference(object): notice_numbers = utils.read_only_property("_notice_numbers") -@utils.register_interface(ExtensionType) -class SubjectKeyIdentifier(object): - oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER - - def __init__(self, digest): - self._digest = digest - - @classmethod - def from_public_key(cls, public_key): - return cls(_key_identifier_from_public_key(public_key)) - - digest = utils.read_only_property("_digest") - - def __repr__(self): - return "".format(self.digest) - - def __eq__(self, other): - if not isinstance(other, SubjectKeyIdentifier): - return NotImplemented - - return ( - self.digest == other.digest - ) - - def __ne__(self, other): - return not self == other - - @utils.register_interface(ExtensionType) class NameConstraints(object): oid = ExtensionOID.NAME_CONSTRAINTS @@ -876,74 +815,6 @@ class IssuerAlternativeName(object): return not self == other -@utils.register_interface(ExtensionType) -class AuthorityKeyIdentifier(object): - oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER - - def __init__(self, key_identifier, authority_cert_issuer, - authority_cert_serial_number): - if authority_cert_issuer or authority_cert_serial_number: - if not authority_cert_issuer or not authority_cert_serial_number: - raise ValueError( - "authority_cert_issuer and authority_cert_serial_number " - "must both be present or both None" - ) - - if not all( - isinstance(x, GeneralName) for x in authority_cert_issuer - ): - raise TypeError( - "authority_cert_issuer must be a list of GeneralName " - "objects" - ) - - if not isinstance(authority_cert_serial_number, six.integer_types): - raise TypeError( - "authority_cert_serial_number must be an integer" - ) - - self._key_identifier = key_identifier - self._authority_cert_issuer = authority_cert_issuer - self._authority_cert_serial_number = authority_cert_serial_number - - @classmethod - def from_issuer_public_key(cls, public_key): - digest = _key_identifier_from_public_key(public_key) - return cls( - key_identifier=digest, - authority_cert_issuer=None, - authority_cert_serial_number=None - ) - - def __repr__(self): - return ( - "".format(self) - ) - - def __eq__(self, other): - if not isinstance(other, AuthorityKeyIdentifier): - return NotImplemented - - return ( - self.key_identifier == other.key_identifier and - self.authority_cert_issuer == other.authority_cert_issuer and - self.authority_cert_serial_number == - other.authority_cert_serial_number - ) - - def __ne__(self, other): - return not self == other - - key_identifier = utils.read_only_property("_key_identifier") - authority_cert_issuer = utils.read_only_property("_authority_cert_issuer") - authority_cert_serial_number = utils.read_only_property( - "_authority_cert_serial_number" - ) - - @six.add_metaclass(abc.ABCMeta) class Certificate(object): @abc.abstractmethod diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py new file mode 100644 index 00000000..38175531 --- /dev/null +++ b/src/cryptography/x509/extensions.py @@ -0,0 +1,144 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import hashlib + +from pyasn1.codec.der import decoder +from pyasn1.type import namedtype, univ + +import six + +from cryptography import utils +from cryptography.hazmat.primitives import serialization +from cryptography.x509.base import ExtensionType +from cryptography.x509.general_name import GeneralName +from cryptography.x509.oid import ( + ExtensionOID +) + + +class _SubjectPublicKeyInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('algorithm', univ.Sequence()), + namedtype.NamedType('subjectPublicKey', univ.BitString()) + ) + + +def _key_identifier_from_public_key(public_key): + # This is a very slow way to do this. + serialized = public_key.public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.SubjectPublicKeyInfo + ) + spki, remaining = decoder.decode( + serialized, asn1Spec=_SubjectPublicKeyInfo() + ) + assert not remaining + # the univ.BitString object is a tuple of bits. We need bytes and + # pyasn1 really doesn't want to give them to us. To get it we'll + # build an integer and convert that to bytes. + bits = 0 + for bit in spki.getComponentByName("subjectPublicKey"): + bits = bits << 1 | bit + + data = utils.int_to_bytes(bits) + return hashlib.sha1(data).digest() + + +@utils.register_interface(ExtensionType) +class AuthorityKeyIdentifier(object): + oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER + + def __init__(self, key_identifier, authority_cert_issuer, + authority_cert_serial_number): + if authority_cert_issuer or authority_cert_serial_number: + if not authority_cert_issuer or not authority_cert_serial_number: + raise ValueError( + "authority_cert_issuer and authority_cert_serial_number " + "must both be present or both None" + ) + + if not all( + isinstance(x, GeneralName) for x in authority_cert_issuer + ): + raise TypeError( + "authority_cert_issuer must be a list of GeneralName " + "objects" + ) + + if not isinstance(authority_cert_serial_number, six.integer_types): + raise TypeError( + "authority_cert_serial_number must be an integer" + ) + + self._key_identifier = key_identifier + self._authority_cert_issuer = authority_cert_issuer + self._authority_cert_serial_number = authority_cert_serial_number + + @classmethod + def from_issuer_public_key(cls, public_key): + digest = _key_identifier_from_public_key(public_key) + return cls( + key_identifier=digest, + authority_cert_issuer=None, + authority_cert_serial_number=None + ) + + def __repr__(self): + return ( + "".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, AuthorityKeyIdentifier): + return NotImplemented + + return ( + self.key_identifier == other.key_identifier and + self.authority_cert_issuer == other.authority_cert_issuer and + self.authority_cert_serial_number == + other.authority_cert_serial_number + ) + + def __ne__(self, other): + return not self == other + + key_identifier = utils.read_only_property("_key_identifier") + authority_cert_issuer = utils.read_only_property("_authority_cert_issuer") + authority_cert_serial_number = utils.read_only_property( + "_authority_cert_serial_number" + ) + + +@utils.register_interface(ExtensionType) +class SubjectKeyIdentifier(object): + oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER + + def __init__(self, digest): + self._digest = digest + + @classmethod + def from_public_key(cls, public_key): + return cls(_key_identifier_from_public_key(public_key)) + + digest = utils.read_only_property("_digest") + + def __repr__(self): + return "".format(self.digest) + + def __eq__(self, other): + if not isinstance(other, SubjectKeyIdentifier): + return NotImplemented + + return ( + self.digest == other.digest + ) + + def __ne__(self, other): + return not self == other -- cgit v1.2.3