extensions.py 53 KB

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