You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1655 lines
50 KiB

  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. from __future__ import absolute_import, division, print_function
  5. import abc
  6. import datetime
  7. import hashlib
  8. import ipaddress
  9. import warnings
  10. from enum import Enum
  11. from asn1crypto.keys import PublicKeyInfo
  12. import six
  13. from cryptography import utils
  14. from cryptography.hazmat.primitives import constant_time, serialization
  15. from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
  16. from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
  17. from cryptography.x509.certificate_transparency import (
  18. SignedCertificateTimestamp
  19. )
  20. from cryptography.x509.general_name import GeneralName, IPAddress, OtherName
  21. from cryptography.x509.name import RelativeDistinguishedName
  22. from cryptography.x509.oid import (
  23. CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ObjectIdentifier,
  24. )
  25. def _key_identifier_from_public_key(public_key):
  26. if isinstance(public_key, RSAPublicKey):
  27. data = public_key.public_bytes(
  28. serialization.Encoding.DER,
  29. serialization.PublicFormat.PKCS1,
  30. )
  31. elif isinstance(public_key, EllipticCurvePublicKey):
  32. data = public_key.public_bytes(
  33. serialization.Encoding.X962,
  34. serialization.PublicFormat.UncompressedPoint
  35. )
  36. else:
  37. # This is a very slow way to do this.
  38. serialized = public_key.public_bytes(
  39. serialization.Encoding.DER,
  40. serialization.PublicFormat.SubjectPublicKeyInfo
  41. )
  42. data = bytes(PublicKeyInfo.load(serialized)['public_key'])
  43. return hashlib.sha1(data).digest()
  44. class DuplicateExtension(Exception):
  45. def __init__(self, msg, oid):
  46. super(DuplicateExtension, self).__init__(msg)
  47. self.oid = oid
  48. class ExtensionNotFound(Exception):
  49. def __init__(self, msg, oid):
  50. super(ExtensionNotFound, self).__init__(msg)
  51. self.oid = oid
  52. @six.add_metaclass(abc.ABCMeta)
  53. class ExtensionType(object):
  54. @abc.abstractproperty
  55. def oid(self):
  56. """
  57. Returns the oid associated with the given extension type.
  58. """
  59. class Extensions(object):
  60. def __init__(self, extensions):
  61. self._extensions = extensions
  62. def get_extension_for_oid(self, oid):
  63. for ext in self:
  64. if ext.oid == oid:
  65. return ext
  66. raise ExtensionNotFound("No {} extension was found".format(oid), oid)
  67. def get_extension_for_class(self, extclass):
  68. if extclass is UnrecognizedExtension:
  69. raise TypeError(
  70. "UnrecognizedExtension can't be used with "
  71. "get_extension_for_class because more than one instance of the"
  72. " class may be present."
  73. )
  74. for ext in self:
  75. if isinstance(ext.value, extclass):
  76. return ext
  77. raise ExtensionNotFound(
  78. "No {} extension was found".format(extclass), extclass.oid
  79. )
  80. def __iter__(self):
  81. return iter(self._extensions)
  82. def __len__(self):
  83. return len(self._extensions)
  84. def __getitem__(self, idx):
  85. return self._extensions[idx]
  86. def __repr__(self):
  87. return (
  88. "<Extensions({})>".format(self._extensions)
  89. )
  90. @utils.register_interface(ExtensionType)
  91. class CRLNumber(object):
  92. oid = ExtensionOID.CRL_NUMBER
  93. def __init__(self, crl_number):
  94. if not isinstance(crl_number, six.integer_types):
  95. raise TypeError("crl_number must be an integer")
  96. self._crl_number = crl_number
  97. def __eq__(self, other):
  98. if not isinstance(other, CRLNumber):
  99. return NotImplemented
  100. return self.crl_number == other.crl_number
  101. def __ne__(self, other):
  102. return not self == other
  103. def __hash__(self):
  104. return hash(self.crl_number)
  105. def __repr__(self):
  106. return "<CRLNumber({})>".format(self.crl_number)
  107. crl_number = utils.read_only_property("_crl_number")
  108. @utils.register_interface(ExtensionType)
  109. class AuthorityKeyIdentifier(object):
  110. oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
  111. def __init__(self, key_identifier, authority_cert_issuer,
  112. authority_cert_serial_number):
  113. if (authority_cert_issuer is None) != (
  114. authority_cert_serial_number is None
  115. ):
  116. raise ValueError(
  117. "authority_cert_issuer and authority_cert_serial_number "
  118. "must both be present or both None"
  119. )
  120. if authority_cert_issuer is not None:
  121. authority_cert_issuer = list(authority_cert_issuer)
  122. if not all(
  123. isinstance(x, GeneralName) for x in authority_cert_issuer
  124. ):
  125. raise TypeError(
  126. "authority_cert_issuer must be a list of GeneralName "
  127. "objects"
  128. )
  129. if authority_cert_serial_number is not None and not isinstance(
  130. authority_cert_serial_number, six.integer_types
  131. ):
  132. raise TypeError(
  133. "authority_cert_serial_number must be an integer"
  134. )
  135. self._key_identifier = key_identifier
  136. self._authority_cert_issuer = authority_cert_issuer
  137. self._authority_cert_serial_number = authority_cert_serial_number
  138. @classmethod
  139. def from_issuer_public_key(cls, public_key):
  140. digest = _key_identifier_from_public_key(public_key)
  141. return cls(
  142. key_identifier=digest,
  143. authority_cert_issuer=None,
  144. authority_cert_serial_number=None
  145. )
  146. @classmethod
  147. def from_issuer_subject_key_identifier(cls, ski):
  148. if isinstance(ski, SubjectKeyIdentifier):
  149. digest = ski.digest
  150. else:
  151. digest = ski.value.digest
  152. warnings.warn(
  153. "Extension objects are deprecated as arguments to "
  154. "from_issuer_subject_key_identifier and support will be "
  155. "removed soon. Please migrate to passing a "
  156. "SubjectKeyIdentifier directly.",
  157. utils.DeprecatedIn27,
  158. stacklevel=2,
  159. )
  160. return cls(
  161. key_identifier=digest,
  162. authority_cert_issuer=None,
  163. authority_cert_serial_number=None
  164. )
  165. def __repr__(self):
  166. return (
  167. "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
  168. "authority_cert_issuer={0.authority_cert_issuer}, "
  169. "authority_cert_serial_number={0.authority_cert_serial_number}"
  170. ")>".format(self)
  171. )
  172. def __eq__(self, other):
  173. if not isinstance(other, AuthorityKeyIdentifier):
  174. return NotImplemented
  175. return (
  176. self.key_identifier == other.key_identifier and
  177. self.authority_cert_issuer == other.authority_cert_issuer and
  178. self.authority_cert_serial_number ==
  179. other.authority_cert_serial_number
  180. )
  181. def __ne__(self, other):
  182. return not self == other
  183. def __hash__(self):
  184. if self.authority_cert_issuer is None:
  185. aci = None
  186. else:
  187. aci = tuple(self.authority_cert_issuer)
  188. return hash((
  189. self.key_identifier, aci, self.authority_cert_serial_number
  190. ))
  191. key_identifier = utils.read_only_property("_key_identifier")
  192. authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
  193. authority_cert_serial_number = utils.read_only_property(
  194. "_authority_cert_serial_number"
  195. )
  196. @utils.register_interface(ExtensionType)
  197. class SubjectKeyIdentifier(object):
  198. oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER
  199. def __init__(self, digest):
  200. self._digest = digest
  201. @classmethod
  202. def from_public_key(cls, public_key):
  203. return cls(_key_identifier_from_public_key(public_key))
  204. digest = utils.read_only_property("_digest")
  205. def __repr__(self):
  206. return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
  207. def __eq__(self, other):
  208. if not isinstance(other, SubjectKeyIdentifier):
  209. return NotImplemented
  210. return constant_time.bytes_eq(self.digest, other.digest)
  211. def __ne__(self, other):
  212. return not self == other
  213. def __hash__(self):
  214. return hash(self.digest)
  215. @utils.register_interface(ExtensionType)
  216. class AuthorityInformationAccess(object):
  217. oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
  218. def __init__(self, descriptions):
  219. descriptions = list(descriptions)
  220. if not all(isinstance(x, AccessDescription) for x in descriptions):
  221. raise TypeError(
  222. "Every item in the descriptions list must be an "
  223. "AccessDescription"
  224. )
  225. self._descriptions = descriptions
  226. def __iter__(self):
  227. return iter(self._descriptions)
  228. def __len__(self):
  229. return len(self._descriptions)
  230. def __repr__(self):
  231. return "<AuthorityInformationAccess({})>".format(self._descriptions)
  232. def __eq__(self, other):
  233. if not isinstance(other, AuthorityInformationAccess):
  234. return NotImplemented
  235. return self._descriptions == other._descriptions
  236. def __ne__(self, other):
  237. return not self == other
  238. def __getitem__(self, idx):
  239. return self._descriptions[idx]
  240. def __hash__(self):
  241. return hash(tuple(self._descriptions))
  242. class AccessDescription(object):
  243. def __init__(self, access_method, access_location):
  244. if not isinstance(access_method, ObjectIdentifier):
  245. raise TypeError("access_method must be an ObjectIdentifier")
  246. if not isinstance(access_location, GeneralName):
  247. raise TypeError("access_location must be a GeneralName")
  248. self._access_method = access_method
  249. self._access_location = access_location
  250. def __repr__(self):
  251. return (
  252. "<AccessDescription(access_method={0.access_method}, access_locati"
  253. "on={0.access_location})>".format(self)
  254. )
  255. def __eq__(self, other):
  256. if not isinstance(other, AccessDescription):
  257. return NotImplemented
  258. return (
  259. self.access_method == other.access_method and
  260. self.access_location == other.access_location
  261. )
  262. def __ne__(self, other):
  263. return not self == other
  264. def __hash__(self):
  265. return hash((self.access_method, self.access_location))
  266. access_method = utils.read_only_property("_access_method")
  267. access_location = utils.read_only_property("_access_location")
  268. @utils.register_interface(ExtensionType)
  269. class BasicConstraints(object):
  270. oid = ExtensionOID.BASIC_CONSTRAINTS
  271. def __init__(self, ca, path_length):
  272. if not isinstance(ca, bool):
  273. raise TypeError("ca must be a boolean value")
  274. if path_length is not None and not ca:
  275. raise ValueError("path_length must be None when ca is False")
  276. if (
  277. path_length is not None and
  278. (not isinstance(path_length, six.integer_types) or path_length < 0)
  279. ):
  280. raise TypeError(
  281. "path_length must be a non-negative integer or None"
  282. )
  283. self._ca = ca
  284. self._path_length = path_length
  285. ca = utils.read_only_property("_ca")
  286. path_length = utils.read_only_property("_path_length")
  287. def __repr__(self):
  288. return ("<BasicConstraints(ca={0.ca}, "
  289. "path_length={0.path_length})>").format(self)
  290. def __eq__(self, other):
  291. if not isinstance(other, BasicConstraints):
  292. return NotImplemented
  293. return self.ca == other.ca and self.path_length == other.path_length
  294. def __ne__(self, other):
  295. return not self == other
  296. def __hash__(self):
  297. return hash((self.ca, self.path_length))
  298. @utils.register_interface(ExtensionType)
  299. class DeltaCRLIndicator(object):
  300. oid = ExtensionOID.DELTA_CRL_INDICATOR
  301. def __init__(self, crl_number):
  302. if not isinstance(crl_number, six.integer_types):
  303. raise TypeError("crl_number must be an integer")
  304. self._crl_number = crl_number
  305. crl_number = utils.read_only_property("_crl_number")
  306. def __eq__(self, other):
  307. if not isinstance(other, DeltaCRLIndicator):
  308. return NotImplemented
  309. return self.crl_number == other.crl_number
  310. def __ne__(self, other):
  311. return not self == other
  312. def __hash__(self):
  313. return hash(self.crl_number)
  314. def __repr__(self):
  315. return "<DeltaCRLIndicator(crl_number={0.crl_number})>".format(self)
  316. @utils.register_interface(ExtensionType)
  317. class CRLDistributionPoints(object):
  318. oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
  319. def __init__(self, distribution_points):
  320. distribution_points = list(distribution_points)
  321. if not all(
  322. isinstance(x, DistributionPoint) for x in distribution_points
  323. ):
  324. raise TypeError(
  325. "distribution_points must be a list of DistributionPoint "
  326. "objects"
  327. )
  328. self._distribution_points = distribution_points
  329. def __iter__(self):
  330. return iter(self._distribution_points)
  331. def __len__(self):
  332. return len(self._distribution_points)
  333. def __repr__(self):
  334. return "<CRLDistributionPoints({})>".format(self._distribution_points)
  335. def __eq__(self, other):
  336. if not isinstance(other, CRLDistributionPoints):
  337. return NotImplemented
  338. return self._distribution_points == other._distribution_points
  339. def __ne__(self, other):
  340. return not self == other
  341. def __getitem__(self, idx):
  342. return self._distribution_points[idx]
  343. def __hash__(self):
  344. return hash(tuple(self._distribution_points))
  345. @utils.register_interface(ExtensionType)
  346. class FreshestCRL(object):
  347. oid = ExtensionOID.FRESHEST_CRL
  348. def __init__(self, distribution_points):
  349. distribution_points = list(distribution_points)
  350. if not all(
  351. isinstance(x, DistributionPoint) for x in distribution_points
  352. ):
  353. raise TypeError(
  354. "distribution_points must be a list of DistributionPoint "
  355. "objects"
  356. )
  357. self._distribution_points = distribution_points
  358. def __iter__(self):
  359. return iter(self._distribution_points)
  360. def __len__(self):
  361. return len(self._distribution_points)
  362. def __repr__(self):
  363. return "<FreshestCRL({})>".format(self._distribution_points)
  364. def __eq__(self, other):
  365. if not isinstance(other, FreshestCRL):
  366. return NotImplemented
  367. return self._distribution_points == other._distribution_points
  368. def __ne__(self, other):
  369. return not self == other
  370. def __getitem__(self, idx):
  371. return self._distribution_points[idx]
  372. def __hash__(self):
  373. return hash(tuple(self._distribution_points))
  374. class DistributionPoint(object):
  375. def __init__(self, full_name, relative_name, reasons, crl_issuer):
  376. if full_name and relative_name:
  377. raise ValueError(
  378. "You cannot provide both full_name and relative_name, at "
  379. "least one must be None."
  380. )
  381. if full_name:
  382. full_name = list(full_name)
  383. if not all(isinstance(x, GeneralName) for x in full_name):
  384. raise TypeError(
  385. "full_name must be a list of GeneralName objects"
  386. )
  387. if relative_name:
  388. if not isinstance(relative_name, RelativeDistinguishedName):
  389. raise TypeError(
  390. "relative_name must be a RelativeDistinguishedName"
  391. )
  392. if crl_issuer:
  393. crl_issuer = list(crl_issuer)
  394. if not all(isinstance(x, GeneralName) for x in crl_issuer):
  395. raise TypeError(
  396. "crl_issuer must be None or a list of general names"
  397. )
  398. if reasons and (not isinstance(reasons, frozenset) or not all(
  399. isinstance(x, ReasonFlags) for x in reasons
  400. )):
  401. raise TypeError("reasons must be None or frozenset of ReasonFlags")
  402. if reasons and (
  403. ReasonFlags.unspecified in reasons or
  404. ReasonFlags.remove_from_crl in reasons
  405. ):
  406. raise ValueError(
  407. "unspecified and remove_from_crl are not valid reasons in a "
  408. "DistributionPoint"
  409. )
  410. if reasons and not crl_issuer and not (full_name or relative_name):
  411. raise ValueError(
  412. "You must supply crl_issuer, full_name, or relative_name when "
  413. "reasons is not None"
  414. )
  415. self._full_name = full_name
  416. self._relative_name = relative_name
  417. self._reasons = reasons
  418. self._crl_issuer = crl_issuer
  419. def __repr__(self):
  420. return (
  421. "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
  422. "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_issuer})>"
  423. .format(self)
  424. )
  425. def __eq__(self, other):
  426. if not isinstance(other, DistributionPoint):
  427. return NotImplemented
  428. return (
  429. self.full_name == other.full_name and
  430. self.relative_name == other.relative_name and
  431. self.reasons == other.reasons and
  432. self.crl_issuer == other.crl_issuer
  433. )
  434. def __ne__(self, other):
  435. return not self == other
  436. def __hash__(self):
  437. if self.full_name is not None:
  438. fn = tuple(self.full_name)
  439. else:
  440. fn = None
  441. if self.crl_issuer is not None:
  442. crl_issuer = tuple(self.crl_issuer)
  443. else:
  444. crl_issuer = None
  445. return hash((fn, self.relative_name, self.reasons, crl_issuer))
  446. full_name = utils.read_only_property("_full_name")
  447. relative_name = utils.read_only_property("_relative_name")
  448. reasons = utils.read_only_property("_reasons")
  449. crl_issuer = utils.read_only_property("_crl_issuer")
  450. class ReasonFlags(Enum):
  451. unspecified = "unspecified"
  452. key_compromise = "keyCompromise"
  453. ca_compromise = "cACompromise"
  454. affiliation_changed = "affiliationChanged"
  455. superseded = "superseded"
  456. cessation_of_operation = "cessationOfOperation"
  457. certificate_hold = "certificateHold"
  458. privilege_withdrawn = "privilegeWithdrawn"
  459. aa_compromise = "aACompromise"
  460. remove_from_crl = "removeFromCRL"
  461. @utils.register_interface(ExtensionType)
  462. class PolicyConstraints(object):
  463. oid = ExtensionOID.POLICY_CONSTRAINTS
  464. def __init__(self, require_explicit_policy, inhibit_policy_mapping):
  465. if require_explicit_policy is not None and not isinstance(
  466. require_explicit_policy, six.integer_types
  467. ):
  468. raise TypeError(
  469. "require_explicit_policy must be a non-negative integer or "
  470. "None"
  471. )
  472. if inhibit_policy_mapping is not None and not isinstance(
  473. inhibit_policy_mapping, six.integer_types
  474. ):
  475. raise TypeError(
  476. "inhibit_policy_mapping must be a non-negative integer or None"
  477. )
  478. if inhibit_policy_mapping is None and require_explicit_policy is None:
  479. raise ValueError(
  480. "At least one of require_explicit_policy and "
  481. "inhibit_policy_mapping must not be None"
  482. )
  483. self._require_explicit_policy = require_explicit_policy
  484. self._inhibit_policy_mapping = inhibit_policy_mapping
  485. def __repr__(self):
  486. return (
  487. u"<PolicyConstraints(require_explicit_policy={0.require_explicit"
  488. u"_policy}, inhibit_policy_mapping={0.inhibit_policy_"
  489. u"mapping})>".format(self)
  490. )
  491. def __eq__(self, other):
  492. if not isinstance(other, PolicyConstraints):
  493. return NotImplemented
  494. return (
  495. self.require_explicit_policy == other.require_explicit_policy and
  496. self.inhibit_policy_mapping == other.inhibit_policy_mapping
  497. )
  498. def __ne__(self, other):
  499. return not self == other
  500. def __hash__(self):
  501. return hash(
  502. (self.require_explicit_policy, self.inhibit_policy_mapping)
  503. )
  504. require_explicit_policy = utils.read_only_property(
  505. "_require_explicit_policy"
  506. )
  507. inhibit_policy_mapping = utils.read_only_property(
  508. "_inhibit_policy_mapping"
  509. )
  510. @utils.register_interface(ExtensionType)
  511. class CertificatePolicies(object):
  512. oid = ExtensionOID.CERTIFICATE_POLICIES
  513. def __init__(self, policies):
  514. policies = list(policies)
  515. if not all(isinstance(x, PolicyInformation) for x in policies):
  516. raise TypeError(
  517. "Every item in the policies list must be a "
  518. "PolicyInformation"
  519. )
  520. self._policies = policies
  521. def __iter__(self):
  522. return iter(self._policies)
  523. def __len__(self):
  524. return len(self._policies)
  525. def __repr__(self):
  526. return "<CertificatePolicies({})>".format(self._policies)
  527. def __eq__(self, other):
  528. if not isinstance(other, CertificatePolicies):
  529. return NotImplemented
  530. return self._policies == other._policies
  531. def __ne__(self, other):
  532. return not self == other
  533. def __getitem__(self, idx):
  534. return self._policies[idx]
  535. def __hash__(self):
  536. return hash(tuple(self._policies))
  537. class PolicyInformation(object):
  538. def __init__(self, policy_identifier, policy_qualifiers):
  539. if not isinstance(policy_identifier, ObjectIdentifier):
  540. raise TypeError("policy_identifier must be an ObjectIdentifier")
  541. self._policy_identifier = policy_identifier
  542. if policy_qualifiers:
  543. policy_qualifiers = list(policy_qualifiers)
  544. if not all(
  545. isinstance(x, (six.text_type, UserNotice))
  546. for x in policy_qualifiers
  547. ):
  548. raise TypeError(
  549. "policy_qualifiers must be a list of strings and/or "
  550. "UserNotice objects or None"
  551. )
  552. self._policy_qualifiers = policy_qualifiers
  553. def __repr__(self):
  554. return (
  555. "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
  556. "y_qualifiers={0.policy_qualifiers})>".format(self)
  557. )
  558. def __eq__(self, other):
  559. if not isinstance(other, PolicyInformation):
  560. return NotImplemented
  561. return (
  562. self.policy_identifier == other.policy_identifier and
  563. self.policy_qualifiers == other.policy_qualifiers
  564. )
  565. def __ne__(self, other):
  566. return not self == other
  567. def __hash__(self):
  568. if self.policy_qualifiers is not None:
  569. pq = tuple(self.policy_qualifiers)
  570. else:
  571. pq = None
  572. return hash((self.policy_identifier, pq))
  573. policy_identifier = utils.read_only_property("_policy_identifier")
  574. policy_qualifiers = utils.read_only_property("_policy_qualifiers")
  575. class UserNotice(object):
  576. def __init__(self, notice_reference, explicit_text):
  577. if notice_reference and not isinstance(
  578. notice_reference, NoticeReference
  579. ):
  580. raise TypeError(
  581. "notice_reference must be None or a NoticeReference"
  582. )
  583. self._notice_reference = notice_reference
  584. self._explicit_text = explicit_text
  585. def __repr__(self):
  586. return (
  587. "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
  588. "{0.explicit_text!r})>".format(self)
  589. )
  590. def __eq__(self, other):
  591. if not isinstance(other, UserNotice):
  592. return NotImplemented
  593. return (
  594. self.notice_reference == other.notice_reference and
  595. self.explicit_text == other.explicit_text
  596. )
  597. def __ne__(self, other):
  598. return not self == other
  599. def __hash__(self):
  600. return hash((self.notice_reference, self.explicit_text))
  601. notice_reference = utils.read_only_property("_notice_reference")
  602. explicit_text = utils.read_only_property("_explicit_text")
  603. class NoticeReference(object):
  604. def __init__(self, organization, notice_numbers):
  605. self._organization = organization
  606. notice_numbers = list(notice_numbers)
  607. if not all(isinstance(x, int) for x in notice_numbers):
  608. raise TypeError(
  609. "notice_numbers must be a list of integers"
  610. )
  611. self._notice_numbers = notice_numbers
  612. def __repr__(self):
  613. return (
  614. "<NoticeReference(organization={0.organization!r}, notice_numbers="
  615. "{0.notice_numbers})>".format(self)
  616. )
  617. def __eq__(self, other):
  618. if not isinstance(other, NoticeReference):
  619. return NotImplemented
  620. return (
  621. self.organization == other.organization and
  622. self.notice_numbers == other.notice_numbers
  623. )
  624. def __ne__(self, other):
  625. return not self == other
  626. def __hash__(self):
  627. return hash((self.organization, tuple(self.notice_numbers)))
  628. organization = utils.read_only_property("_organization")
  629. notice_numbers = utils.read_only_property("_notice_numbers")
  630. @utils.register_interface(ExtensionType)
  631. class ExtendedKeyUsage(object):
  632. oid = ExtensionOID.EXTENDED_KEY_USAGE
  633. def __init__(self, usages):
  634. usages = list(usages)
  635. if not all(isinstance(x, ObjectIdentifier) for x in usages):
  636. raise TypeError(
  637. "Every item in the usages list must be an ObjectIdentifier"
  638. )
  639. self._usages = usages
  640. def __iter__(self):
  641. return iter(self._usages)
  642. def __len__(self):
  643. return len(self._usages)
  644. def __repr__(self):
  645. return "<ExtendedKeyUsage({})>".format(self._usages)
  646. def __eq__(self, other):
  647. if not isinstance(other, ExtendedKeyUsage):
  648. return NotImplemented
  649. return self._usages == other._usages
  650. def __ne__(self, other):
  651. return not self == other
  652. def __hash__(self):
  653. return hash(tuple(self._usages))
  654. @utils.register_interface(ExtensionType)
  655. class OCSPNoCheck(object):
  656. oid = ExtensionOID.OCSP_NO_CHECK
  657. def __eq__(self, other):
  658. if not isinstance(other, OCSPNoCheck):
  659. return NotImplemented
  660. return True
  661. def __ne__(self, other):
  662. return not self == other
  663. def __hash__(self):
  664. return hash(OCSPNoCheck)
  665. def __repr__(self):
  666. return "<OCSPNoCheck()>"
  667. @utils.register_interface(ExtensionType)
  668. class PrecertPoison(object):
  669. oid = ExtensionOID.PRECERT_POISON
  670. def __eq__(self, other):
  671. if not isinstance(other, PrecertPoison):
  672. return NotImplemented
  673. return True
  674. def __ne__(self, other):
  675. return not self == other
  676. def __hash__(self):
  677. return hash(PrecertPoison)
  678. def __repr__(self):
  679. return "<PrecertPoison()>"
  680. @utils.register_interface(ExtensionType)
  681. class TLSFeature(object):
  682. oid = ExtensionOID.TLS_FEATURE
  683. def __init__(self, features):
  684. features = list(features)
  685. if (
  686. not all(isinstance(x, TLSFeatureType) for x in features) or
  687. len(features) == 0
  688. ):
  689. raise TypeError(
  690. "features must be a list of elements from the TLSFeatureType "
  691. "enum"
  692. )
  693. self._features = features
  694. def __iter__(self):
  695. return iter(self._features)
  696. def __len__(self):
  697. return len(self._features)
  698. def __repr__(self):
  699. return "<TLSFeature(features={0._features})>".format(self)
  700. def __eq__(self, other):
  701. if not isinstance(other, TLSFeature):
  702. return NotImplemented
  703. return self._features == other._features
  704. def __getitem__(self, idx):
  705. return self._features[idx]
  706. def __ne__(self, other):
  707. return not self == other
  708. def __hash__(self):
  709. return hash(tuple(self._features))
  710. class TLSFeatureType(Enum):
  711. # status_request is defined in RFC 6066 and is used for what is commonly
  712. # called OCSP Must-Staple when present in the TLS Feature extension in an
  713. # X.509 certificate.
  714. status_request = 5
  715. # status_request_v2 is defined in RFC 6961 and allows multiple OCSP
  716. # responses to be provided. It is not currently in use by clients or
  717. # servers.
  718. status_request_v2 = 17
  719. _TLS_FEATURE_TYPE_TO_ENUM = dict((x.value, x) for x in TLSFeatureType)
  720. @utils.register_interface(ExtensionType)
  721. class InhibitAnyPolicy(object):
  722. oid = ExtensionOID.INHIBIT_ANY_POLICY
  723. def __init__(self, skip_certs):
  724. if not isinstance(skip_certs, six.integer_types):
  725. raise TypeError("skip_certs must be an integer")
  726. if skip_certs < 0:
  727. raise ValueError("skip_certs must be a non-negative integer")
  728. self._skip_certs = skip_certs
  729. def __repr__(self):
  730. return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
  731. def __eq__(self, other):
  732. if not isinstance(other, InhibitAnyPolicy):
  733. return NotImplemented
  734. return self.skip_certs == other.skip_certs
  735. def __ne__(self, other):
  736. return not self == other
  737. def __hash__(self):
  738. return hash(self.skip_certs)
  739. skip_certs = utils.read_only_property("_skip_certs")
  740. @utils.register_interface(ExtensionType)
  741. class KeyUsage(object):
  742. oid = ExtensionOID.KEY_USAGE
  743. def __init__(self, digital_signature, content_commitment, key_encipherment,
  744. data_encipherment, key_agreement, key_cert_sign, crl_sign,
  745. encipher_only, decipher_only):
  746. if not key_agreement and (encipher_only or decipher_only):
  747. raise ValueError(
  748. "encipher_only and decipher_only can only be true when "
  749. "key_agreement is true"
  750. )
  751. self._digital_signature = digital_signature
  752. self._content_commitment = content_commitment
  753. self._key_encipherment = key_encipherment
  754. self._data_encipherment = data_encipherment
  755. self._key_agreement = key_agreement
  756. self._key_cert_sign = key_cert_sign
  757. self._crl_sign = crl_sign
  758. self._encipher_only = encipher_only
  759. self._decipher_only = decipher_only
  760. digital_signature = utils.read_only_property("_digital_signature")
  761. content_commitment = utils.read_only_property("_content_commitment")
  762. key_encipherment = utils.read_only_property("_key_encipherment")
  763. data_encipherment = utils.read_only_property("_data_encipherment")
  764. key_agreement = utils.read_only_property("_key_agreement")
  765. key_cert_sign = utils.read_only_property("_key_cert_sign")
  766. crl_sign = utils.read_only_property("_crl_sign")
  767. @property
  768. def encipher_only(self):
  769. if not self.key_agreement:
  770. raise ValueError(
  771. "encipher_only is undefined unless key_agreement is true"
  772. )
  773. else:
  774. return self._encipher_only
  775. @property
  776. def decipher_only(self):
  777. if not self.key_agreement:
  778. raise ValueError(
  779. "decipher_only is undefined unless key_agreement is true"
  780. )
  781. else:
  782. return self._decipher_only
  783. def __repr__(self):
  784. try:
  785. encipher_only = self.encipher_only
  786. decipher_only = self.decipher_only
  787. except ValueError:
  788. encipher_only = None
  789. decipher_only = None
  790. return ("<KeyUsage(digital_signature={0.digital_signature}, "
  791. "content_commitment={0.content_commitment}, "
  792. "key_encipherment={0.key_encipherment}, "
  793. "data_encipherment={0.data_encipherment}, "
  794. "key_agreement={0.key_agreement}, "
  795. "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
  796. "encipher_only={1}, decipher_only={2})>").format(
  797. self, encipher_only, decipher_only)
  798. def __eq__(self, other):
  799. if not isinstance(other, KeyUsage):
  800. return NotImplemented
  801. return (
  802. self.digital_signature == other.digital_signature and
  803. self.content_commitment == other.content_commitment and
  804. self.key_encipherment == other.key_encipherment and
  805. self.data_encipherment == other.data_encipherment and
  806. self.key_agreement == other.key_agreement and
  807. self.key_cert_sign == other.key_cert_sign and
  808. self.crl_sign == other.crl_sign and
  809. self._encipher_only == other._encipher_only and
  810. self._decipher_only == other._decipher_only
  811. )
  812. def __ne__(self, other):
  813. return not self == other
  814. def __hash__(self):
  815. return hash((
  816. self.digital_signature, self.content_commitment,
  817. self.key_encipherment, self.data_encipherment,
  818. self.key_agreement, self.key_cert_sign,
  819. self.crl_sign, self._encipher_only,
  820. self._decipher_only
  821. ))
  822. @utils.register_interface(ExtensionType)
  823. class NameConstraints(object):
  824. oid = ExtensionOID.NAME_CONSTRAINTS
  825. def __init__(self, permitted_subtrees, excluded_subtrees):
  826. if permitted_subtrees is not None:
  827. permitted_subtrees = list(permitted_subtrees)
  828. if not all(
  829. isinstance(x, GeneralName) for x in permitted_subtrees
  830. ):
  831. raise TypeError(
  832. "permitted_subtrees must be a list of GeneralName objects "
  833. "or None"
  834. )
  835. self._validate_ip_name(permitted_subtrees)
  836. if excluded_subtrees is not None:
  837. excluded_subtrees = list(excluded_subtrees)
  838. if not all(
  839. isinstance(x, GeneralName) for x in excluded_subtrees
  840. ):
  841. raise TypeError(
  842. "excluded_subtrees must be a list of GeneralName objects "
  843. "or None"
  844. )
  845. self._validate_ip_name(excluded_subtrees)
  846. if permitted_subtrees is None and excluded_subtrees is None:
  847. raise ValueError(
  848. "At least one of permitted_subtrees and excluded_subtrees "
  849. "must not be None"
  850. )
  851. self._permitted_subtrees = permitted_subtrees
  852. self._excluded_subtrees = excluded_subtrees
  853. def __eq__(self, other):
  854. if not isinstance(other, NameConstraints):
  855. return NotImplemented
  856. return (
  857. self.excluded_subtrees == other.excluded_subtrees and
  858. self.permitted_subtrees == other.permitted_subtrees
  859. )
  860. def __ne__(self, other):
  861. return not self == other
  862. def _validate_ip_name(self, tree):
  863. if any(isinstance(name, IPAddress) and not isinstance(
  864. name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
  865. ) for name in tree):
  866. raise TypeError(
  867. "IPAddress name constraints must be an IPv4Network or"
  868. " IPv6Network object"
  869. )
  870. def __repr__(self):
  871. return (
  872. u"<NameConstraints(permitted_subtrees={0.permitted_subtrees}, "
  873. u"excluded_subtrees={0.excluded_subtrees})>".format(self)
  874. )
  875. def __hash__(self):
  876. if self.permitted_subtrees is not None:
  877. ps = tuple(self.permitted_subtrees)
  878. else:
  879. ps = None
  880. if self.excluded_subtrees is not None:
  881. es = tuple(self.excluded_subtrees)
  882. else:
  883. es = None
  884. return hash((ps, es))
  885. permitted_subtrees = utils.read_only_property("_permitted_subtrees")
  886. excluded_subtrees = utils.read_only_property("_excluded_subtrees")
  887. class Extension(object):
  888. def __init__(self, oid, critical, value):
  889. if not isinstance(oid, ObjectIdentifier):
  890. raise TypeError(
  891. "oid argument must be an ObjectIdentifier instance."
  892. )
  893. if not isinstance(critical, bool):
  894. raise TypeError("critical must be a boolean value")
  895. self._oid = oid
  896. self._critical = critical
  897. self._value = value
  898. oid = utils.read_only_property("_oid")
  899. critical = utils.read_only_property("_critical")
  900. value = utils.read_only_property("_value")
  901. def __repr__(self):
  902. return ("<Extension(oid={0.oid}, critical={0.critical}, "
  903. "value={0.value})>").format(self)
  904. def __eq__(self, other):
  905. if not isinstance(other, Extension):
  906. return NotImplemented
  907. return (
  908. self.oid == other.oid and
  909. self.critical == other.critical and
  910. self.value == other.value
  911. )
  912. def __ne__(self, other):
  913. return not self == other
  914. def __hash__(self):
  915. return hash((self.oid, self.critical, self.value))
  916. class GeneralNames(object):
  917. def __init__(self, general_names):
  918. general_names = list(general_names)
  919. if not all(isinstance(x, GeneralName) for x in general_names):
  920. raise TypeError(
  921. "Every item in the general_names list must be an "
  922. "object conforming to the GeneralName interface"
  923. )
  924. self._general_names = general_names
  925. def __iter__(self):
  926. return iter(self._general_names)
  927. def __len__(self):
  928. return len(self._general_names)
  929. def get_values_for_type(self, type):
  930. # Return the value of each GeneralName, except for OtherName instances
  931. # which we return directly because it has two important properties not
  932. # just one value.
  933. objs = (i for i in self if isinstance(i, type))
  934. if type != OtherName:
  935. objs = (i.value for i in objs)
  936. return list(objs)
  937. def __repr__(self):
  938. return "<GeneralNames({})>".format(self._general_names)
  939. def __eq__(self, other):
  940. if not isinstance(other, GeneralNames):
  941. return NotImplemented
  942. return self._general_names == other._general_names
  943. def __ne__(self, other):
  944. return not self == other
  945. def __getitem__(self, idx):
  946. return self._general_names[idx]
  947. def __hash__(self):
  948. return hash(tuple(self._general_names))
  949. @utils.register_interface(ExtensionType)
  950. class SubjectAlternativeName(object):
  951. oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME
  952. def __init__(self, general_names):
  953. self._general_names = GeneralNames(general_names)
  954. def __iter__(self):
  955. return iter(self._general_names)
  956. def __len__(self):
  957. return len(self._general_names)
  958. def get_values_for_type(self, type):
  959. return self._general_names.get_values_for_type(type)
  960. def __repr__(self):
  961. return "<SubjectAlternativeName({})>".format(self._general_names)
  962. def __eq__(self, other):
  963. if not isinstance(other, SubjectAlternativeName):
  964. return NotImplemented
  965. return self._general_names == other._general_names
  966. def __getitem__(self, idx):
  967. return self._general_names[idx]
  968. def __ne__(self, other):
  969. return not self == other
  970. def __hash__(self):
  971. return hash(self._general_names)
  972. @utils.register_interface(ExtensionType)
  973. class IssuerAlternativeName(object):
  974. oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME
  975. def __init__(self, general_names):
  976. self._general_names = GeneralNames(general_names)
  977. def __iter__(self):
  978. return iter(self._general_names)
  979. def __len__(self):
  980. return len(self._general_names)
  981. def get_values_for_type(self, type):
  982. return self._general_names.get_values_for_type(type)
  983. def __repr__(self):
  984. return "<IssuerAlternativeName({})>".format(self._general_names)
  985. def __eq__(self, other):
  986. if not isinstance(other, IssuerAlternativeName):
  987. return NotImplemented
  988. return self._general_names == other._general_names
  989. def __ne__(self, other):
  990. return not self == other
  991. def __getitem__(self, idx):
  992. return self._general_names[idx]
  993. def __hash__(self):
  994. return hash(self._general_names)
  995. @utils.register_interface(ExtensionType)
  996. class CertificateIssuer(object):
  997. oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER
  998. def __init__(self, general_names):
  999. self._general_names = GeneralNames(general_names)
  1000. def __iter__(self):
  1001. return iter(self._general_names)
  1002. def __len__(self):
  1003. return len(self._general_names)
  1004. def get_values_for_type(self, type):
  1005. return self._general_names.get_values_for_type(type)
  1006. def __repr__(self):
  1007. return "<CertificateIssuer({})>".format(self._general_names)
  1008. def __eq__(self, other):
  1009. if not isinstance(other, CertificateIssuer):
  1010. return NotImplemented
  1011. return self._general_names == other._general_names
  1012. def __ne__(self, other):
  1013. return not self == other
  1014. def __getitem__(self, idx):
  1015. return self._general_names[idx]
  1016. def __hash__(self):
  1017. return hash(self._general_names)
  1018. @utils.register_interface(ExtensionType)
  1019. class CRLReason(object):
  1020. oid = CRLEntryExtensionOID.CRL_REASON
  1021. def __init__(self, reason):
  1022. if not isinstance(reason, ReasonFlags):
  1023. raise TypeError("reason must be an element from ReasonFlags")
  1024. self._reason = reason
  1025. def __repr__(self):
  1026. return "<CRLReason(reason={})>".format(self._reason)
  1027. def __eq__(self, other):
  1028. if not isinstance(other, CRLReason):
  1029. return NotImplemented
  1030. return self.reason == other.reason
  1031. def __ne__(self, other):
  1032. return not self == other
  1033. def __hash__(self):
  1034. return hash(self.reason)
  1035. reason = utils.read_only_property("_reason")
  1036. @utils.register_interface(ExtensionType)
  1037. class InvalidityDate(object):
  1038. oid = CRLEntryExtensionOID.INVALIDITY_DATE
  1039. def __init__(self, invalidity_date):
  1040. if not isinstance(invalidity_date, datetime.datetime):
  1041. raise TypeError("invalidity_date must be a datetime.datetime")
  1042. self._invalidity_date = invalidity_date
  1043. def __repr__(self):
  1044. return "<InvalidityDate(invalidity_date={})>".format(
  1045. self._invalidity_date
  1046. )
  1047. def __eq__(self, other):
  1048. if not isinstance(other, InvalidityDate):
  1049. return NotImplemented
  1050. return self.invalidity_date == other.invalidity_date
  1051. def __ne__(self, other):
  1052. return not self == other
  1053. def __hash__(self):
  1054. return hash(self.invalidity_date)
  1055. invalidity_date = utils.read_only_property("_invalidity_date")
  1056. @utils.register_interface(ExtensionType)
  1057. class PrecertificateSignedCertificateTimestamps(object):
  1058. oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
  1059. def __init__(self, signed_certificate_timestamps):
  1060. signed_certificate_timestamps = list(signed_certificate_timestamps)
  1061. if not all(
  1062. isinstance(sct, SignedCertificateTimestamp)
  1063. for sct in signed_certificate_timestamps
  1064. ):
  1065. raise TypeError(
  1066. "Every item in the signed_certificate_timestamps list must be "
  1067. "a SignedCertificateTimestamp"
  1068. )
  1069. self._signed_certificate_timestamps = signed_certificate_timestamps
  1070. def __iter__(self):
  1071. return iter(self._signed_certificate_timestamps)
  1072. def __len__(self):
  1073. return len(self._signed_certificate_timestamps)
  1074. def __getitem__(self, idx):
  1075. return self._signed_certificate_timestamps[idx]
  1076. def __repr__(self):
  1077. return (
  1078. "<PrecertificateSignedCertificateTimestamps({})>".format(
  1079. list(self)
  1080. )
  1081. )
  1082. def __hash__(self):
  1083. return hash(tuple(self._signed_certificate_timestamps))
  1084. def __eq__(self, other):
  1085. if not isinstance(other, PrecertificateSignedCertificateTimestamps):
  1086. return NotImplemented
  1087. return (
  1088. self._signed_certificate_timestamps ==
  1089. other._signed_certificate_timestamps
  1090. )
  1091. def __ne__(self, other):
  1092. return not self == other
  1093. @utils.register_interface(ExtensionType)
  1094. class OCSPNonce(object):
  1095. oid = OCSPExtensionOID.NONCE
  1096. def __init__(self, nonce):
  1097. if not isinstance(nonce, bytes):
  1098. raise TypeError("nonce must be bytes")
  1099. self._nonce = nonce
  1100. def __eq__(self, other):
  1101. if not isinstance(other, OCSPNonce):
  1102. return NotImplemented
  1103. return self.nonce == other.nonce
  1104. def __ne__(self, other):
  1105. return not self == other
  1106. def __hash__(self):
  1107. return hash(self.nonce)
  1108. def __repr__(self):
  1109. return "<OCSPNonce(nonce={0.nonce!r})>".format(self)
  1110. nonce = utils.read_only_property("_nonce")
  1111. @utils.register_interface(ExtensionType)
  1112. class IssuingDistributionPoint(object):
  1113. oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT
  1114. def __init__(self, full_name, relative_name, only_contains_user_certs,
  1115. only_contains_ca_certs, only_some_reasons, indirect_crl,
  1116. only_contains_attribute_certs):
  1117. if (
  1118. only_some_reasons and (
  1119. not isinstance(only_some_reasons, frozenset) or not all(
  1120. isinstance(x, ReasonFlags) for x in only_some_reasons
  1121. )
  1122. )
  1123. ):
  1124. raise TypeError(
  1125. "only_some_reasons must be None or frozenset of ReasonFlags"
  1126. )
  1127. if only_some_reasons and (
  1128. ReasonFlags.unspecified in only_some_reasons or
  1129. ReasonFlags.remove_from_crl in only_some_reasons
  1130. ):
  1131. raise ValueError(
  1132. "unspecified and remove_from_crl are not valid reasons in an "
  1133. "IssuingDistributionPoint"
  1134. )
  1135. if not (
  1136. isinstance(only_contains_user_certs, bool) and
  1137. isinstance(only_contains_ca_certs, bool) and
  1138. isinstance(indirect_crl, bool) and
  1139. isinstance(only_contains_attribute_certs, bool)
  1140. ):
  1141. raise TypeError(
  1142. "only_contains_user_certs, only_contains_ca_certs, "
  1143. "indirect_crl and only_contains_attribute_certs "
  1144. "must all be boolean."
  1145. )
  1146. crl_constraints = [
  1147. only_contains_user_certs, only_contains_ca_certs,
  1148. indirect_crl, only_contains_attribute_certs
  1149. ]
  1150. if len([x for x in crl_constraints if x]) > 1:
  1151. raise ValueError(
  1152. "Only one of the following can be set to True: "
  1153. "only_contains_user_certs, only_contains_ca_certs, "
  1154. "indirect_crl, only_contains_attribute_certs"
  1155. )
  1156. if (
  1157. not any([
  1158. only_contains_user_certs, only_contains_ca_certs,
  1159. indirect_crl, only_contains_attribute_certs, full_name,
  1160. relative_name, only_some_reasons
  1161. ])
  1162. ):
  1163. raise ValueError(
  1164. "Cannot create empty extension: "
  1165. "if only_contains_user_certs, only_contains_ca_certs, "
  1166. "indirect_crl, and only_contains_attribute_certs are all False"
  1167. ", then either full_name, relative_name, or only_some_reasons "
  1168. "must have a value."
  1169. )
  1170. self._only_contains_user_certs = only_contains_user_certs
  1171. self._only_contains_ca_certs = only_contains_ca_certs
  1172. self._indirect_crl = indirect_crl
  1173. self._only_contains_attribute_certs = only_contains_attribute_certs
  1174. self._only_some_reasons = only_some_reasons
  1175. self._full_name = full_name
  1176. self._relative_name = relative_name
  1177. def __repr__(self):
  1178. return (
  1179. "<IssuingDistributionPoint(full_name={0.full_name}, "
  1180. "relative_name={0.relative_name}, "
  1181. "only_contains_user_certs={0.only_contains_user_certs}, "
  1182. "only_contains_ca_certs={0.only_contains_ca_certs}, "
  1183. "only_some_reasons={0.only_some_reasons}, "
  1184. "indirect_crl={0.indirect_crl}, "
  1185. "only_contains_attribute_certs="
  1186. "{0.only_contains_attribute_certs})>".format(self)
  1187. )
  1188. def __eq__(self, other):
  1189. if not isinstance(other, IssuingDistributionPoint):
  1190. return NotImplemented
  1191. return (
  1192. self.full_name == other.full_name and
  1193. self.relative_name == other.relative_name and
  1194. self.only_contains_user_certs == other.only_contains_user_certs and
  1195. self.only_contains_ca_certs == other.only_contains_ca_certs and
  1196. self.only_some_reasons == other.only_some_reasons and
  1197. self.indirect_crl == other.indirect_crl and
  1198. self.only_contains_attribute_certs ==
  1199. other.only_contains_attribute_certs
  1200. )
  1201. def __ne__(self, other):
  1202. return not self == other
  1203. def __hash__(self):
  1204. return hash((
  1205. self.full_name,
  1206. self.relative_name,
  1207. self.only_contains_user_certs,
  1208. self.only_contains_ca_certs,
  1209. self.only_some_reasons,
  1210. self.indirect_crl,
  1211. self.only_contains_attribute_certs,
  1212. ))
  1213. full_name = utils.read_only_property("_full_name")
  1214. relative_name = utils.read_only_property("_relative_name")
  1215. only_contains_user_certs = utils.read_only_property(
  1216. "_only_contains_user_certs"
  1217. )
  1218. only_contains_ca_certs = utils.read_only_property(
  1219. "_only_contains_ca_certs"
  1220. )
  1221. only_some_reasons = utils.read_only_property("_only_some_reasons")
  1222. indirect_crl = utils.read_only_property("_indirect_crl")
  1223. only_contains_attribute_certs = utils.read_only_property(
  1224. "_only_contains_attribute_certs"
  1225. )
  1226. @utils.register_interface(ExtensionType)
  1227. class UnrecognizedExtension(object):
  1228. def __init__(self, oid, value):
  1229. if not isinstance(oid, ObjectIdentifier):
  1230. raise TypeError("oid must be an ObjectIdentifier")
  1231. self._oid = oid
  1232. self._value = value
  1233. oid = utils.read_only_property("_oid")
  1234. value = utils.read_only_property("_value")
  1235. def __repr__(self):
  1236. return (
  1237. "<UnrecognizedExtension(oid={0.oid}, value={0.value!r})>".format(
  1238. self
  1239. )
  1240. )
  1241. def __eq__(self, other):
  1242. if not isinstance(other, UnrecognizedExtension):
  1243. return NotImplemented
  1244. return self.oid == other.oid and self.value == other.value
  1245. def __ne__(self, other):
  1246. return not self == other
  1247. def __hash__(self):
  1248. return hash((self.oid, self.value))