base.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  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 annotations
  5. import abc
  6. import datetime
  7. import os
  8. import typing
  9. import warnings
  10. from cryptography import utils
  11. from cryptography.hazmat.bindings._rust import x509 as rust_x509
  12. from cryptography.hazmat.primitives import hashes
  13. from cryptography.hazmat.primitives.asymmetric import (
  14. dsa,
  15. ec,
  16. ed448,
  17. ed25519,
  18. padding,
  19. rsa,
  20. x448,
  21. x25519,
  22. )
  23. from cryptography.hazmat.primitives.asymmetric.types import (
  24. CertificateIssuerPrivateKeyTypes,
  25. CertificatePublicKeyTypes,
  26. )
  27. from cryptography.x509.extensions import (
  28. Extension,
  29. Extensions,
  30. ExtensionType,
  31. _make_sequence_methods,
  32. )
  33. from cryptography.x509.name import Name, _ASN1Type
  34. from cryptography.x509.oid import ObjectIdentifier
  35. _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1)
  36. # This must be kept in sync with sign.rs's list of allowable types in
  37. # identify_hash_type
  38. _AllowedHashTypes = typing.Union[
  39. hashes.SHA224,
  40. hashes.SHA256,
  41. hashes.SHA384,
  42. hashes.SHA512,
  43. hashes.SHA3_224,
  44. hashes.SHA3_256,
  45. hashes.SHA3_384,
  46. hashes.SHA3_512,
  47. ]
  48. class AttributeNotFound(Exception):
  49. def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
  50. super().__init__(msg)
  51. self.oid = oid
  52. def _reject_duplicate_extension(
  53. extension: Extension[ExtensionType],
  54. extensions: list[Extension[ExtensionType]],
  55. ) -> None:
  56. # This is quadratic in the number of extensions
  57. for e in extensions:
  58. if e.oid == extension.oid:
  59. raise ValueError("This extension has already been set.")
  60. def _reject_duplicate_attribute(
  61. oid: ObjectIdentifier,
  62. attributes: list[tuple[ObjectIdentifier, bytes, int | None]],
  63. ) -> None:
  64. # This is quadratic in the number of attributes
  65. for attr_oid, _, _ in attributes:
  66. if attr_oid == oid:
  67. raise ValueError("This attribute has already been set.")
  68. def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime:
  69. """Normalizes a datetime to a naive datetime in UTC.
  70. time -- datetime to normalize. Assumed to be in UTC if not timezone
  71. aware.
  72. """
  73. if time.tzinfo is not None:
  74. offset = time.utcoffset()
  75. offset = offset if offset else datetime.timedelta()
  76. return time.replace(tzinfo=None) - offset
  77. else:
  78. return time
  79. class Attribute:
  80. def __init__(
  81. self,
  82. oid: ObjectIdentifier,
  83. value: bytes,
  84. _type: int = _ASN1Type.UTF8String.value,
  85. ) -> None:
  86. self._oid = oid
  87. self._value = value
  88. self._type = _type
  89. @property
  90. def oid(self) -> ObjectIdentifier:
  91. return self._oid
  92. @property
  93. def value(self) -> bytes:
  94. return self._value
  95. def __repr__(self) -> str:
  96. return f"<Attribute(oid={self.oid}, value={self.value!r})>"
  97. def __eq__(self, other: object) -> bool:
  98. if not isinstance(other, Attribute):
  99. return NotImplemented
  100. return (
  101. self.oid == other.oid
  102. and self.value == other.value
  103. and self._type == other._type
  104. )
  105. def __hash__(self) -> int:
  106. return hash((self.oid, self.value, self._type))
  107. class Attributes:
  108. def __init__(
  109. self,
  110. attributes: typing.Iterable[Attribute],
  111. ) -> None:
  112. self._attributes = list(attributes)
  113. __len__, __iter__, __getitem__ = _make_sequence_methods("_attributes")
  114. def __repr__(self) -> str:
  115. return f"<Attributes({self._attributes})>"
  116. def get_attribute_for_oid(self, oid: ObjectIdentifier) -> Attribute:
  117. for attr in self:
  118. if attr.oid == oid:
  119. return attr
  120. raise AttributeNotFound(f"No {oid} attribute was found", oid)
  121. class Version(utils.Enum):
  122. v1 = 0
  123. v3 = 2
  124. class InvalidVersion(Exception):
  125. def __init__(self, msg: str, parsed_version: int) -> None:
  126. super().__init__(msg)
  127. self.parsed_version = parsed_version
  128. Certificate = rust_x509.Certificate
  129. class RevokedCertificate(metaclass=abc.ABCMeta):
  130. @property
  131. @abc.abstractmethod
  132. def serial_number(self) -> int:
  133. """
  134. Returns the serial number of the revoked certificate.
  135. """
  136. @property
  137. @abc.abstractmethod
  138. def revocation_date(self) -> datetime.datetime:
  139. """
  140. Returns the date of when this certificate was revoked.
  141. """
  142. @property
  143. @abc.abstractmethod
  144. def revocation_date_utc(self) -> datetime.datetime:
  145. """
  146. Returns the date of when this certificate was revoked as a non-naive
  147. UTC datetime.
  148. """
  149. @property
  150. @abc.abstractmethod
  151. def extensions(self) -> Extensions:
  152. """
  153. Returns an Extensions object containing a list of Revoked extensions.
  154. """
  155. # Runtime isinstance checks need this since the rust class is not a subclass.
  156. RevokedCertificate.register(rust_x509.RevokedCertificate)
  157. class _RawRevokedCertificate(RevokedCertificate):
  158. def __init__(
  159. self,
  160. serial_number: int,
  161. revocation_date: datetime.datetime,
  162. extensions: Extensions,
  163. ):
  164. self._serial_number = serial_number
  165. self._revocation_date = revocation_date
  166. self._extensions = extensions
  167. @property
  168. def serial_number(self) -> int:
  169. return self._serial_number
  170. @property
  171. def revocation_date(self) -> datetime.datetime:
  172. warnings.warn(
  173. "Properties that return a naïve datetime object have been "
  174. "deprecated. Please switch to revocation_date_utc.",
  175. utils.DeprecatedIn42,
  176. stacklevel=2,
  177. )
  178. return self._revocation_date
  179. @property
  180. def revocation_date_utc(self) -> datetime.datetime:
  181. return self._revocation_date.replace(tzinfo=datetime.timezone.utc)
  182. @property
  183. def extensions(self) -> Extensions:
  184. return self._extensions
  185. CertificateRevocationList = rust_x509.CertificateRevocationList
  186. CertificateSigningRequest = rust_x509.CertificateSigningRequest
  187. load_pem_x509_certificate = rust_x509.load_pem_x509_certificate
  188. load_der_x509_certificate = rust_x509.load_der_x509_certificate
  189. load_pem_x509_certificates = rust_x509.load_pem_x509_certificates
  190. load_pem_x509_csr = rust_x509.load_pem_x509_csr
  191. load_der_x509_csr = rust_x509.load_der_x509_csr
  192. load_pem_x509_crl = rust_x509.load_pem_x509_crl
  193. load_der_x509_crl = rust_x509.load_der_x509_crl
  194. class CertificateSigningRequestBuilder:
  195. def __init__(
  196. self,
  197. subject_name: Name | None = None,
  198. extensions: list[Extension[ExtensionType]] = [],
  199. attributes: list[tuple[ObjectIdentifier, bytes, int | None]] = [],
  200. ):
  201. """
  202. Creates an empty X.509 certificate request (v1).
  203. """
  204. self._subject_name = subject_name
  205. self._extensions = extensions
  206. self._attributes = attributes
  207. def subject_name(self, name: Name) -> CertificateSigningRequestBuilder:
  208. """
  209. Sets the certificate requestor's distinguished name.
  210. """
  211. if not isinstance(name, Name):
  212. raise TypeError("Expecting x509.Name object.")
  213. if self._subject_name is not None:
  214. raise ValueError("The subject name may only be set once.")
  215. return CertificateSigningRequestBuilder(
  216. name, self._extensions, self._attributes
  217. )
  218. def add_extension(
  219. self, extval: ExtensionType, critical: bool
  220. ) -> CertificateSigningRequestBuilder:
  221. """
  222. Adds an X.509 extension to the certificate request.
  223. """
  224. if not isinstance(extval, ExtensionType):
  225. raise TypeError("extension must be an ExtensionType")
  226. extension = Extension(extval.oid, critical, extval)
  227. _reject_duplicate_extension(extension, self._extensions)
  228. return CertificateSigningRequestBuilder(
  229. self._subject_name,
  230. [*self._extensions, extension],
  231. self._attributes,
  232. )
  233. def add_attribute(
  234. self,
  235. oid: ObjectIdentifier,
  236. value: bytes,
  237. *,
  238. _tag: _ASN1Type | None = None,
  239. ) -> CertificateSigningRequestBuilder:
  240. """
  241. Adds an X.509 attribute with an OID and associated value.
  242. """
  243. if not isinstance(oid, ObjectIdentifier):
  244. raise TypeError("oid must be an ObjectIdentifier")
  245. if not isinstance(value, bytes):
  246. raise TypeError("value must be bytes")
  247. if _tag is not None and not isinstance(_tag, _ASN1Type):
  248. raise TypeError("tag must be _ASN1Type")
  249. _reject_duplicate_attribute(oid, self._attributes)
  250. if _tag is not None:
  251. tag = _tag.value
  252. else:
  253. tag = None
  254. return CertificateSigningRequestBuilder(
  255. self._subject_name,
  256. self._extensions,
  257. [*self._attributes, (oid, value, tag)],
  258. )
  259. def sign(
  260. self,
  261. private_key: CertificateIssuerPrivateKeyTypes,
  262. algorithm: _AllowedHashTypes | None,
  263. backend: typing.Any = None,
  264. *,
  265. rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
  266. ) -> CertificateSigningRequest:
  267. """
  268. Signs the request using the requestor's private key.
  269. """
  270. if self._subject_name is None:
  271. raise ValueError("A CertificateSigningRequest must have a subject")
  272. if rsa_padding is not None:
  273. if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
  274. raise TypeError("Padding must be PSS or PKCS1v15")
  275. if not isinstance(private_key, rsa.RSAPrivateKey):
  276. raise TypeError("Padding is only supported for RSA keys")
  277. return rust_x509.create_x509_csr(
  278. self, private_key, algorithm, rsa_padding
  279. )
  280. class CertificateBuilder:
  281. _extensions: list[Extension[ExtensionType]]
  282. def __init__(
  283. self,
  284. issuer_name: Name | None = None,
  285. subject_name: Name | None = None,
  286. public_key: CertificatePublicKeyTypes | None = None,
  287. serial_number: int | None = None,
  288. not_valid_before: datetime.datetime | None = None,
  289. not_valid_after: datetime.datetime | None = None,
  290. extensions: list[Extension[ExtensionType]] = [],
  291. ) -> None:
  292. self._version = Version.v3
  293. self._issuer_name = issuer_name
  294. self._subject_name = subject_name
  295. self._public_key = public_key
  296. self._serial_number = serial_number
  297. self._not_valid_before = not_valid_before
  298. self._not_valid_after = not_valid_after
  299. self._extensions = extensions
  300. def issuer_name(self, name: Name) -> CertificateBuilder:
  301. """
  302. Sets the CA's distinguished name.
  303. """
  304. if not isinstance(name, Name):
  305. raise TypeError("Expecting x509.Name object.")
  306. if self._issuer_name is not None:
  307. raise ValueError("The issuer name may only be set once.")
  308. return CertificateBuilder(
  309. name,
  310. self._subject_name,
  311. self._public_key,
  312. self._serial_number,
  313. self._not_valid_before,
  314. self._not_valid_after,
  315. self._extensions,
  316. )
  317. def subject_name(self, name: Name) -> CertificateBuilder:
  318. """
  319. Sets the requestor's distinguished name.
  320. """
  321. if not isinstance(name, Name):
  322. raise TypeError("Expecting x509.Name object.")
  323. if self._subject_name is not None:
  324. raise ValueError("The subject name may only be set once.")
  325. return CertificateBuilder(
  326. self._issuer_name,
  327. name,
  328. self._public_key,
  329. self._serial_number,
  330. self._not_valid_before,
  331. self._not_valid_after,
  332. self._extensions,
  333. )
  334. def public_key(
  335. self,
  336. key: CertificatePublicKeyTypes,
  337. ) -> CertificateBuilder:
  338. """
  339. Sets the requestor's public key (as found in the signing request).
  340. """
  341. if not isinstance(
  342. key,
  343. (
  344. dsa.DSAPublicKey,
  345. rsa.RSAPublicKey,
  346. ec.EllipticCurvePublicKey,
  347. ed25519.Ed25519PublicKey,
  348. ed448.Ed448PublicKey,
  349. x25519.X25519PublicKey,
  350. x448.X448PublicKey,
  351. ),
  352. ):
  353. raise TypeError(
  354. "Expecting one of DSAPublicKey, RSAPublicKey,"
  355. " EllipticCurvePublicKey, Ed25519PublicKey,"
  356. " Ed448PublicKey, X25519PublicKey, or "
  357. "X448PublicKey."
  358. )
  359. if self._public_key is not None:
  360. raise ValueError("The public key may only be set once.")
  361. return CertificateBuilder(
  362. self._issuer_name,
  363. self._subject_name,
  364. key,
  365. self._serial_number,
  366. self._not_valid_before,
  367. self._not_valid_after,
  368. self._extensions,
  369. )
  370. def serial_number(self, number: int) -> CertificateBuilder:
  371. """
  372. Sets the certificate serial number.
  373. """
  374. if not isinstance(number, int):
  375. raise TypeError("Serial number must be of integral type.")
  376. if self._serial_number is not None:
  377. raise ValueError("The serial number may only be set once.")
  378. if number <= 0:
  379. raise ValueError("The serial number should be positive.")
  380. # ASN.1 integers are always signed, so most significant bit must be
  381. # zero.
  382. if number.bit_length() >= 160: # As defined in RFC 5280
  383. raise ValueError(
  384. "The serial number should not be more than 159 bits."
  385. )
  386. return CertificateBuilder(
  387. self._issuer_name,
  388. self._subject_name,
  389. self._public_key,
  390. number,
  391. self._not_valid_before,
  392. self._not_valid_after,
  393. self._extensions,
  394. )
  395. def not_valid_before(self, time: datetime.datetime) -> CertificateBuilder:
  396. """
  397. Sets the certificate activation time.
  398. """
  399. if not isinstance(time, datetime.datetime):
  400. raise TypeError("Expecting datetime object.")
  401. if self._not_valid_before is not None:
  402. raise ValueError("The not valid before may only be set once.")
  403. time = _convert_to_naive_utc_time(time)
  404. if time < _EARLIEST_UTC_TIME:
  405. raise ValueError(
  406. "The not valid before date must be on or after"
  407. " 1950 January 1)."
  408. )
  409. if self._not_valid_after is not None and time > self._not_valid_after:
  410. raise ValueError(
  411. "The not valid before date must be before the not valid after "
  412. "date."
  413. )
  414. return CertificateBuilder(
  415. self._issuer_name,
  416. self._subject_name,
  417. self._public_key,
  418. self._serial_number,
  419. time,
  420. self._not_valid_after,
  421. self._extensions,
  422. )
  423. def not_valid_after(self, time: datetime.datetime) -> CertificateBuilder:
  424. """
  425. Sets the certificate expiration time.
  426. """
  427. if not isinstance(time, datetime.datetime):
  428. raise TypeError("Expecting datetime object.")
  429. if self._not_valid_after is not None:
  430. raise ValueError("The not valid after may only be set once.")
  431. time = _convert_to_naive_utc_time(time)
  432. if time < _EARLIEST_UTC_TIME:
  433. raise ValueError(
  434. "The not valid after date must be on or after"
  435. " 1950 January 1."
  436. )
  437. if (
  438. self._not_valid_before is not None
  439. and time < self._not_valid_before
  440. ):
  441. raise ValueError(
  442. "The not valid after date must be after the not valid before "
  443. "date."
  444. )
  445. return CertificateBuilder(
  446. self._issuer_name,
  447. self._subject_name,
  448. self._public_key,
  449. self._serial_number,
  450. self._not_valid_before,
  451. time,
  452. self._extensions,
  453. )
  454. def add_extension(
  455. self, extval: ExtensionType, critical: bool
  456. ) -> CertificateBuilder:
  457. """
  458. Adds an X.509 extension to the certificate.
  459. """
  460. if not isinstance(extval, ExtensionType):
  461. raise TypeError("extension must be an ExtensionType")
  462. extension = Extension(extval.oid, critical, extval)
  463. _reject_duplicate_extension(extension, self._extensions)
  464. return CertificateBuilder(
  465. self._issuer_name,
  466. self._subject_name,
  467. self._public_key,
  468. self._serial_number,
  469. self._not_valid_before,
  470. self._not_valid_after,
  471. [*self._extensions, extension],
  472. )
  473. def sign(
  474. self,
  475. private_key: CertificateIssuerPrivateKeyTypes,
  476. algorithm: _AllowedHashTypes | None,
  477. backend: typing.Any = None,
  478. *,
  479. rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
  480. ) -> Certificate:
  481. """
  482. Signs the certificate using the CA's private key.
  483. """
  484. if self._subject_name is None:
  485. raise ValueError("A certificate must have a subject name")
  486. if self._issuer_name is None:
  487. raise ValueError("A certificate must have an issuer name")
  488. if self._serial_number is None:
  489. raise ValueError("A certificate must have a serial number")
  490. if self._not_valid_before is None:
  491. raise ValueError("A certificate must have a not valid before time")
  492. if self._not_valid_after is None:
  493. raise ValueError("A certificate must have a not valid after time")
  494. if self._public_key is None:
  495. raise ValueError("A certificate must have a public key")
  496. if rsa_padding is not None:
  497. if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
  498. raise TypeError("Padding must be PSS or PKCS1v15")
  499. if not isinstance(private_key, rsa.RSAPrivateKey):
  500. raise TypeError("Padding is only supported for RSA keys")
  501. return rust_x509.create_x509_certificate(
  502. self, private_key, algorithm, rsa_padding
  503. )
  504. class CertificateRevocationListBuilder:
  505. _extensions: list[Extension[ExtensionType]]
  506. _revoked_certificates: list[RevokedCertificate]
  507. def __init__(
  508. self,
  509. issuer_name: Name | None = None,
  510. last_update: datetime.datetime | None = None,
  511. next_update: datetime.datetime | None = None,
  512. extensions: list[Extension[ExtensionType]] = [],
  513. revoked_certificates: list[RevokedCertificate] = [],
  514. ):
  515. self._issuer_name = issuer_name
  516. self._last_update = last_update
  517. self._next_update = next_update
  518. self._extensions = extensions
  519. self._revoked_certificates = revoked_certificates
  520. def issuer_name(
  521. self, issuer_name: Name
  522. ) -> CertificateRevocationListBuilder:
  523. if not isinstance(issuer_name, Name):
  524. raise TypeError("Expecting x509.Name object.")
  525. if self._issuer_name is not None:
  526. raise ValueError("The issuer name may only be set once.")
  527. return CertificateRevocationListBuilder(
  528. issuer_name,
  529. self._last_update,
  530. self._next_update,
  531. self._extensions,
  532. self._revoked_certificates,
  533. )
  534. def last_update(
  535. self, last_update: datetime.datetime
  536. ) -> CertificateRevocationListBuilder:
  537. if not isinstance(last_update, datetime.datetime):
  538. raise TypeError("Expecting datetime object.")
  539. if self._last_update is not None:
  540. raise ValueError("Last update may only be set once.")
  541. last_update = _convert_to_naive_utc_time(last_update)
  542. if last_update < _EARLIEST_UTC_TIME:
  543. raise ValueError(
  544. "The last update date must be on or after 1950 January 1."
  545. )
  546. if self._next_update is not None and last_update > self._next_update:
  547. raise ValueError(
  548. "The last update date must be before the next update date."
  549. )
  550. return CertificateRevocationListBuilder(
  551. self._issuer_name,
  552. last_update,
  553. self._next_update,
  554. self._extensions,
  555. self._revoked_certificates,
  556. )
  557. def next_update(
  558. self, next_update: datetime.datetime
  559. ) -> CertificateRevocationListBuilder:
  560. if not isinstance(next_update, datetime.datetime):
  561. raise TypeError("Expecting datetime object.")
  562. if self._next_update is not None:
  563. raise ValueError("Last update may only be set once.")
  564. next_update = _convert_to_naive_utc_time(next_update)
  565. if next_update < _EARLIEST_UTC_TIME:
  566. raise ValueError(
  567. "The last update date must be on or after 1950 January 1."
  568. )
  569. if self._last_update is not None and next_update < self._last_update:
  570. raise ValueError(
  571. "The next update date must be after the last update date."
  572. )
  573. return CertificateRevocationListBuilder(
  574. self._issuer_name,
  575. self._last_update,
  576. next_update,
  577. self._extensions,
  578. self._revoked_certificates,
  579. )
  580. def add_extension(
  581. self, extval: ExtensionType, critical: bool
  582. ) -> CertificateRevocationListBuilder:
  583. """
  584. Adds an X.509 extension to the certificate revocation list.
  585. """
  586. if not isinstance(extval, ExtensionType):
  587. raise TypeError("extension must be an ExtensionType")
  588. extension = Extension(extval.oid, critical, extval)
  589. _reject_duplicate_extension(extension, self._extensions)
  590. return CertificateRevocationListBuilder(
  591. self._issuer_name,
  592. self._last_update,
  593. self._next_update,
  594. [*self._extensions, extension],
  595. self._revoked_certificates,
  596. )
  597. def add_revoked_certificate(
  598. self, revoked_certificate: RevokedCertificate
  599. ) -> CertificateRevocationListBuilder:
  600. """
  601. Adds a revoked certificate to the CRL.
  602. """
  603. if not isinstance(revoked_certificate, RevokedCertificate):
  604. raise TypeError("Must be an instance of RevokedCertificate")
  605. return CertificateRevocationListBuilder(
  606. self._issuer_name,
  607. self._last_update,
  608. self._next_update,
  609. self._extensions,
  610. [*self._revoked_certificates, revoked_certificate],
  611. )
  612. def sign(
  613. self,
  614. private_key: CertificateIssuerPrivateKeyTypes,
  615. algorithm: _AllowedHashTypes | None,
  616. backend: typing.Any = None,
  617. *,
  618. rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
  619. ) -> CertificateRevocationList:
  620. if self._issuer_name is None:
  621. raise ValueError("A CRL must have an issuer name")
  622. if self._last_update is None:
  623. raise ValueError("A CRL must have a last update time")
  624. if self._next_update is None:
  625. raise ValueError("A CRL must have a next update time")
  626. if rsa_padding is not None:
  627. if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
  628. raise TypeError("Padding must be PSS or PKCS1v15")
  629. if not isinstance(private_key, rsa.RSAPrivateKey):
  630. raise TypeError("Padding is only supported for RSA keys")
  631. return rust_x509.create_x509_crl(
  632. self, private_key, algorithm, rsa_padding
  633. )
  634. class RevokedCertificateBuilder:
  635. def __init__(
  636. self,
  637. serial_number: int | None = None,
  638. revocation_date: datetime.datetime | None = None,
  639. extensions: list[Extension[ExtensionType]] = [],
  640. ):
  641. self._serial_number = serial_number
  642. self._revocation_date = revocation_date
  643. self._extensions = extensions
  644. def serial_number(self, number: int) -> RevokedCertificateBuilder:
  645. if not isinstance(number, int):
  646. raise TypeError("Serial number must be of integral type.")
  647. if self._serial_number is not None:
  648. raise ValueError("The serial number may only be set once.")
  649. if number <= 0:
  650. raise ValueError("The serial number should be positive")
  651. # ASN.1 integers are always signed, so most significant bit must be
  652. # zero.
  653. if number.bit_length() >= 160: # As defined in RFC 5280
  654. raise ValueError(
  655. "The serial number should not be more than 159 bits."
  656. )
  657. return RevokedCertificateBuilder(
  658. number, self._revocation_date, self._extensions
  659. )
  660. def revocation_date(
  661. self, time: datetime.datetime
  662. ) -> RevokedCertificateBuilder:
  663. if not isinstance(time, datetime.datetime):
  664. raise TypeError("Expecting datetime object.")
  665. if self._revocation_date is not None:
  666. raise ValueError("The revocation date may only be set once.")
  667. time = _convert_to_naive_utc_time(time)
  668. if time < _EARLIEST_UTC_TIME:
  669. raise ValueError(
  670. "The revocation date must be on or after 1950 January 1."
  671. )
  672. return RevokedCertificateBuilder(
  673. self._serial_number, time, self._extensions
  674. )
  675. def add_extension(
  676. self, extval: ExtensionType, critical: bool
  677. ) -> RevokedCertificateBuilder:
  678. if not isinstance(extval, ExtensionType):
  679. raise TypeError("extension must be an ExtensionType")
  680. extension = Extension(extval.oid, critical, extval)
  681. _reject_duplicate_extension(extension, self._extensions)
  682. return RevokedCertificateBuilder(
  683. self._serial_number,
  684. self._revocation_date,
  685. [*self._extensions, extension],
  686. )
  687. def build(self, backend: typing.Any = None) -> RevokedCertificate:
  688. if self._serial_number is None:
  689. raise ValueError("A revoked certificate must have a serial number")
  690. if self._revocation_date is None:
  691. raise ValueError(
  692. "A revoked certificate must have a revocation date"
  693. )
  694. return _RawRevokedCertificate(
  695. self._serial_number,
  696. self._revocation_date,
  697. Extensions(self._extensions),
  698. )
  699. def random_serial_number() -> int:
  700. return int.from_bytes(os.urandom(20), "big") >> 1