base.py 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  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, serialization
  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. CertificateIssuerPublicKeyTypes,
  26. CertificatePublicKeyTypes,
  27. )
  28. from cryptography.x509.extensions import (
  29. Extension,
  30. Extensions,
  31. ExtensionType,
  32. _make_sequence_methods,
  33. )
  34. from cryptography.x509.name import Name, _ASN1Type
  35. from cryptography.x509.oid import ObjectIdentifier
  36. _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1)
  37. # This must be kept in sync with sign.rs's list of allowable types in
  38. # identify_hash_type
  39. _AllowedHashTypes = typing.Union[
  40. hashes.SHA224,
  41. hashes.SHA256,
  42. hashes.SHA384,
  43. hashes.SHA512,
  44. hashes.SHA3_224,
  45. hashes.SHA3_256,
  46. hashes.SHA3_384,
  47. hashes.SHA3_512,
  48. ]
  49. class AttributeNotFound(Exception):
  50. def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
  51. super().__init__(msg)
  52. self.oid = oid
  53. def _reject_duplicate_extension(
  54. extension: Extension[ExtensionType],
  55. extensions: list[Extension[ExtensionType]],
  56. ) -> None:
  57. # This is quadratic in the number of extensions
  58. for e in extensions:
  59. if e.oid == extension.oid:
  60. raise ValueError("This extension has already been set.")
  61. def _reject_duplicate_attribute(
  62. oid: ObjectIdentifier,
  63. attributes: list[tuple[ObjectIdentifier, bytes, int | None]],
  64. ) -> None:
  65. # This is quadratic in the number of attributes
  66. for attr_oid, _, _ in attributes:
  67. if attr_oid == oid:
  68. raise ValueError("This attribute has already been set.")
  69. def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime:
  70. """Normalizes a datetime to a naive datetime in UTC.
  71. time -- datetime to normalize. Assumed to be in UTC if not timezone
  72. aware.
  73. """
  74. if time.tzinfo is not None:
  75. offset = time.utcoffset()
  76. offset = offset if offset else datetime.timedelta()
  77. return time.replace(tzinfo=None) - offset
  78. else:
  79. return time
  80. class Attribute:
  81. def __init__(
  82. self,
  83. oid: ObjectIdentifier,
  84. value: bytes,
  85. _type: int = _ASN1Type.UTF8String.value,
  86. ) -> None:
  87. self._oid = oid
  88. self._value = value
  89. self._type = _type
  90. @property
  91. def oid(self) -> ObjectIdentifier:
  92. return self._oid
  93. @property
  94. def value(self) -> bytes:
  95. return self._value
  96. def __repr__(self) -> str:
  97. return f"<Attribute(oid={self.oid}, value={self.value!r})>"
  98. def __eq__(self, other: object) -> bool:
  99. if not isinstance(other, Attribute):
  100. return NotImplemented
  101. return (
  102. self.oid == other.oid
  103. and self.value == other.value
  104. and self._type == other._type
  105. )
  106. def __hash__(self) -> int:
  107. return hash((self.oid, self.value, self._type))
  108. class Attributes:
  109. def __init__(
  110. self,
  111. attributes: typing.Iterable[Attribute],
  112. ) -> None:
  113. self._attributes = list(attributes)
  114. __len__, __iter__, __getitem__ = _make_sequence_methods("_attributes")
  115. def __repr__(self) -> str:
  116. return f"<Attributes({self._attributes})>"
  117. def get_attribute_for_oid(self, oid: ObjectIdentifier) -> Attribute:
  118. for attr in self:
  119. if attr.oid == oid:
  120. return attr
  121. raise AttributeNotFound(f"No {oid} attribute was found", oid)
  122. class Version(utils.Enum):
  123. v1 = 0
  124. v3 = 2
  125. class InvalidVersion(Exception):
  126. def __init__(self, msg: str, parsed_version: int) -> None:
  127. super().__init__(msg)
  128. self.parsed_version = parsed_version
  129. class Certificate(metaclass=abc.ABCMeta):
  130. @abc.abstractmethod
  131. def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes:
  132. """
  133. Returns bytes using digest passed.
  134. """
  135. @property
  136. @abc.abstractmethod
  137. def serial_number(self) -> int:
  138. """
  139. Returns certificate serial number
  140. """
  141. @property
  142. @abc.abstractmethod
  143. def version(self) -> Version:
  144. """
  145. Returns the certificate version
  146. """
  147. @abc.abstractmethod
  148. def public_key(self) -> CertificatePublicKeyTypes:
  149. """
  150. Returns the public key
  151. """
  152. @property
  153. @abc.abstractmethod
  154. def public_key_algorithm_oid(self) -> ObjectIdentifier:
  155. """
  156. Returns the ObjectIdentifier of the public key.
  157. """
  158. @property
  159. @abc.abstractmethod
  160. def not_valid_before(self) -> datetime.datetime:
  161. """
  162. Not before time (represented as UTC datetime)
  163. """
  164. @property
  165. @abc.abstractmethod
  166. def not_valid_before_utc(self) -> datetime.datetime:
  167. """
  168. Not before time (represented as a non-naive UTC datetime)
  169. """
  170. @property
  171. @abc.abstractmethod
  172. def not_valid_after(self) -> datetime.datetime:
  173. """
  174. Not after time (represented as UTC datetime)
  175. """
  176. @property
  177. @abc.abstractmethod
  178. def not_valid_after_utc(self) -> datetime.datetime:
  179. """
  180. Not after time (represented as a non-naive UTC datetime)
  181. """
  182. @property
  183. @abc.abstractmethod
  184. def issuer(self) -> Name:
  185. """
  186. Returns the issuer name object.
  187. """
  188. @property
  189. @abc.abstractmethod
  190. def subject(self) -> Name:
  191. """
  192. Returns the subject name object.
  193. """
  194. @property
  195. @abc.abstractmethod
  196. def signature_hash_algorithm(
  197. self,
  198. ) -> hashes.HashAlgorithm | None:
  199. """
  200. Returns a HashAlgorithm corresponding to the type of the digest signed
  201. in the certificate.
  202. """
  203. @property
  204. @abc.abstractmethod
  205. def signature_algorithm_oid(self) -> ObjectIdentifier:
  206. """
  207. Returns the ObjectIdentifier of the signature algorithm.
  208. """
  209. @property
  210. @abc.abstractmethod
  211. def signature_algorithm_parameters(
  212. self,
  213. ) -> None | padding.PSS | padding.PKCS1v15 | ec.ECDSA:
  214. """
  215. Returns the signature algorithm parameters.
  216. """
  217. @property
  218. @abc.abstractmethod
  219. def extensions(self) -> Extensions:
  220. """
  221. Returns an Extensions object.
  222. """
  223. @property
  224. @abc.abstractmethod
  225. def signature(self) -> bytes:
  226. """
  227. Returns the signature bytes.
  228. """
  229. @property
  230. @abc.abstractmethod
  231. def tbs_certificate_bytes(self) -> bytes:
  232. """
  233. Returns the tbsCertificate payload bytes as defined in RFC 5280.
  234. """
  235. @property
  236. @abc.abstractmethod
  237. def tbs_precertificate_bytes(self) -> bytes:
  238. """
  239. Returns the tbsCertificate payload bytes with the SCT list extension
  240. stripped.
  241. """
  242. @abc.abstractmethod
  243. def __eq__(self, other: object) -> bool:
  244. """
  245. Checks equality.
  246. """
  247. @abc.abstractmethod
  248. def __hash__(self) -> int:
  249. """
  250. Computes a hash.
  251. """
  252. @abc.abstractmethod
  253. def public_bytes(self, encoding: serialization.Encoding) -> bytes:
  254. """
  255. Serializes the certificate to PEM or DER format.
  256. """
  257. @abc.abstractmethod
  258. def verify_directly_issued_by(self, issuer: Certificate) -> None:
  259. """
  260. This method verifies that certificate issuer name matches the
  261. issuer subject name and that the certificate is signed by the
  262. issuer's private key. No other validation is performed.
  263. """
  264. # Runtime isinstance checks need this since the rust class is not a subclass.
  265. Certificate.register(rust_x509.Certificate)
  266. class RevokedCertificate(metaclass=abc.ABCMeta):
  267. @property
  268. @abc.abstractmethod
  269. def serial_number(self) -> int:
  270. """
  271. Returns the serial number of the revoked certificate.
  272. """
  273. @property
  274. @abc.abstractmethod
  275. def revocation_date(self) -> datetime.datetime:
  276. """
  277. Returns the date of when this certificate was revoked.
  278. """
  279. @property
  280. @abc.abstractmethod
  281. def revocation_date_utc(self) -> datetime.datetime:
  282. """
  283. Returns the date of when this certificate was revoked as a non-naive
  284. UTC datetime.
  285. """
  286. @property
  287. @abc.abstractmethod
  288. def extensions(self) -> Extensions:
  289. """
  290. Returns an Extensions object containing a list of Revoked extensions.
  291. """
  292. # Runtime isinstance checks need this since the rust class is not a subclass.
  293. RevokedCertificate.register(rust_x509.RevokedCertificate)
  294. class _RawRevokedCertificate(RevokedCertificate):
  295. def __init__(
  296. self,
  297. serial_number: int,
  298. revocation_date: datetime.datetime,
  299. extensions: Extensions,
  300. ):
  301. self._serial_number = serial_number
  302. self._revocation_date = revocation_date
  303. self._extensions = extensions
  304. @property
  305. def serial_number(self) -> int:
  306. return self._serial_number
  307. @property
  308. def revocation_date(self) -> datetime.datetime:
  309. warnings.warn(
  310. "Properties that return a naïve datetime object have been "
  311. "deprecated. Please switch to revocation_date_utc.",
  312. utils.DeprecatedIn42,
  313. stacklevel=2,
  314. )
  315. return self._revocation_date
  316. @property
  317. def revocation_date_utc(self) -> datetime.datetime:
  318. return self._revocation_date.replace(tzinfo=datetime.timezone.utc)
  319. @property
  320. def extensions(self) -> Extensions:
  321. return self._extensions
  322. class CertificateRevocationList(metaclass=abc.ABCMeta):
  323. @abc.abstractmethod
  324. def public_bytes(self, encoding: serialization.Encoding) -> bytes:
  325. """
  326. Serializes the CRL to PEM or DER format.
  327. """
  328. @abc.abstractmethod
  329. def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes:
  330. """
  331. Returns bytes using digest passed.
  332. """
  333. @abc.abstractmethod
  334. def get_revoked_certificate_by_serial_number(
  335. self, serial_number: int
  336. ) -> RevokedCertificate | None:
  337. """
  338. Returns an instance of RevokedCertificate or None if the serial_number
  339. is not in the CRL.
  340. """
  341. @property
  342. @abc.abstractmethod
  343. def signature_hash_algorithm(
  344. self,
  345. ) -> hashes.HashAlgorithm | None:
  346. """
  347. Returns a HashAlgorithm corresponding to the type of the digest signed
  348. in the certificate.
  349. """
  350. @property
  351. @abc.abstractmethod
  352. def signature_algorithm_oid(self) -> ObjectIdentifier:
  353. """
  354. Returns the ObjectIdentifier of the signature algorithm.
  355. """
  356. @property
  357. @abc.abstractmethod
  358. def signature_algorithm_parameters(
  359. self,
  360. ) -> None | padding.PSS | padding.PKCS1v15 | ec.ECDSA:
  361. """
  362. Returns the signature algorithm parameters.
  363. """
  364. @property
  365. @abc.abstractmethod
  366. def issuer(self) -> Name:
  367. """
  368. Returns the X509Name with the issuer of this CRL.
  369. """
  370. @property
  371. @abc.abstractmethod
  372. def next_update(self) -> datetime.datetime | None:
  373. """
  374. Returns the date of next update for this CRL.
  375. """
  376. @property
  377. @abc.abstractmethod
  378. def next_update_utc(self) -> datetime.datetime | None:
  379. """
  380. Returns the date of next update for this CRL as a non-naive UTC
  381. datetime.
  382. """
  383. @property
  384. @abc.abstractmethod
  385. def last_update(self) -> datetime.datetime:
  386. """
  387. Returns the date of last update for this CRL.
  388. """
  389. @property
  390. @abc.abstractmethod
  391. def last_update_utc(self) -> datetime.datetime:
  392. """
  393. Returns the date of last update for this CRL as a non-naive UTC
  394. datetime.
  395. """
  396. @property
  397. @abc.abstractmethod
  398. def extensions(self) -> Extensions:
  399. """
  400. Returns an Extensions object containing a list of CRL extensions.
  401. """
  402. @property
  403. @abc.abstractmethod
  404. def signature(self) -> bytes:
  405. """
  406. Returns the signature bytes.
  407. """
  408. @property
  409. @abc.abstractmethod
  410. def tbs_certlist_bytes(self) -> bytes:
  411. """
  412. Returns the tbsCertList payload bytes as defined in RFC 5280.
  413. """
  414. @abc.abstractmethod
  415. def __eq__(self, other: object) -> bool:
  416. """
  417. Checks equality.
  418. """
  419. @abc.abstractmethod
  420. def __len__(self) -> int:
  421. """
  422. Number of revoked certificates in the CRL.
  423. """
  424. @typing.overload
  425. def __getitem__(self, idx: int) -> RevokedCertificate: ...
  426. @typing.overload
  427. def __getitem__(self, idx: slice) -> list[RevokedCertificate]: ...
  428. @abc.abstractmethod
  429. def __getitem__(
  430. self, idx: int | slice
  431. ) -> RevokedCertificate | list[RevokedCertificate]:
  432. """
  433. Returns a revoked certificate (or slice of revoked certificates).
  434. """
  435. @abc.abstractmethod
  436. def __iter__(self) -> typing.Iterator[RevokedCertificate]:
  437. """
  438. Iterator over the revoked certificates
  439. """
  440. @abc.abstractmethod
  441. def is_signature_valid(
  442. self, public_key: CertificateIssuerPublicKeyTypes
  443. ) -> bool:
  444. """
  445. Verifies signature of revocation list against given public key.
  446. """
  447. CertificateRevocationList.register(rust_x509.CertificateRevocationList)
  448. class CertificateSigningRequest(metaclass=abc.ABCMeta):
  449. @abc.abstractmethod
  450. def __eq__(self, other: object) -> bool:
  451. """
  452. Checks equality.
  453. """
  454. @abc.abstractmethod
  455. def __hash__(self) -> int:
  456. """
  457. Computes a hash.
  458. """
  459. @abc.abstractmethod
  460. def public_key(self) -> CertificatePublicKeyTypes:
  461. """
  462. Returns the public key
  463. """
  464. @property
  465. @abc.abstractmethod
  466. def subject(self) -> Name:
  467. """
  468. Returns the subject name object.
  469. """
  470. @property
  471. @abc.abstractmethod
  472. def signature_hash_algorithm(
  473. self,
  474. ) -> hashes.HashAlgorithm | None:
  475. """
  476. Returns a HashAlgorithm corresponding to the type of the digest signed
  477. in the certificate.
  478. """
  479. @property
  480. @abc.abstractmethod
  481. def signature_algorithm_oid(self) -> ObjectIdentifier:
  482. """
  483. Returns the ObjectIdentifier of the signature algorithm.
  484. """
  485. @property
  486. @abc.abstractmethod
  487. def signature_algorithm_parameters(
  488. self,
  489. ) -> None | padding.PSS | padding.PKCS1v15 | ec.ECDSA:
  490. """
  491. Returns the signature algorithm parameters.
  492. """
  493. @property
  494. @abc.abstractmethod
  495. def extensions(self) -> Extensions:
  496. """
  497. Returns the extensions in the signing request.
  498. """
  499. @property
  500. @abc.abstractmethod
  501. def attributes(self) -> Attributes:
  502. """
  503. Returns an Attributes object.
  504. """
  505. @abc.abstractmethod
  506. def public_bytes(self, encoding: serialization.Encoding) -> bytes:
  507. """
  508. Encodes the request to PEM or DER format.
  509. """
  510. @property
  511. @abc.abstractmethod
  512. def signature(self) -> bytes:
  513. """
  514. Returns the signature bytes.
  515. """
  516. @property
  517. @abc.abstractmethod
  518. def tbs_certrequest_bytes(self) -> bytes:
  519. """
  520. Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC
  521. 2986.
  522. """
  523. @property
  524. @abc.abstractmethod
  525. def is_signature_valid(self) -> bool:
  526. """
  527. Verifies signature of signing request.
  528. """
  529. @abc.abstractmethod
  530. def get_attribute_for_oid(self, oid: ObjectIdentifier) -> bytes:
  531. """
  532. Get the attribute value for a given OID.
  533. """
  534. # Runtime isinstance checks need this since the rust class is not a subclass.
  535. CertificateSigningRequest.register(rust_x509.CertificateSigningRequest)
  536. load_pem_x509_certificate = rust_x509.load_pem_x509_certificate
  537. load_der_x509_certificate = rust_x509.load_der_x509_certificate
  538. load_pem_x509_certificates = rust_x509.load_pem_x509_certificates
  539. load_pem_x509_csr = rust_x509.load_pem_x509_csr
  540. load_der_x509_csr = rust_x509.load_der_x509_csr
  541. load_pem_x509_crl = rust_x509.load_pem_x509_crl
  542. load_der_x509_crl = rust_x509.load_der_x509_crl
  543. class CertificateSigningRequestBuilder:
  544. def __init__(
  545. self,
  546. subject_name: Name | None = None,
  547. extensions: list[Extension[ExtensionType]] = [],
  548. attributes: list[tuple[ObjectIdentifier, bytes, int | None]] = [],
  549. ):
  550. """
  551. Creates an empty X.509 certificate request (v1).
  552. """
  553. self._subject_name = subject_name
  554. self._extensions = extensions
  555. self._attributes = attributes
  556. def subject_name(self, name: Name) -> CertificateSigningRequestBuilder:
  557. """
  558. Sets the certificate requestor's distinguished name.
  559. """
  560. if not isinstance(name, Name):
  561. raise TypeError("Expecting x509.Name object.")
  562. if self._subject_name is not None:
  563. raise ValueError("The subject name may only be set once.")
  564. return CertificateSigningRequestBuilder(
  565. name, self._extensions, self._attributes
  566. )
  567. def add_extension(
  568. self, extval: ExtensionType, critical: bool
  569. ) -> CertificateSigningRequestBuilder:
  570. """
  571. Adds an X.509 extension to the certificate request.
  572. """
  573. if not isinstance(extval, ExtensionType):
  574. raise TypeError("extension must be an ExtensionType")
  575. extension = Extension(extval.oid, critical, extval)
  576. _reject_duplicate_extension(extension, self._extensions)
  577. return CertificateSigningRequestBuilder(
  578. self._subject_name,
  579. [*self._extensions, extension],
  580. self._attributes,
  581. )
  582. def add_attribute(
  583. self,
  584. oid: ObjectIdentifier,
  585. value: bytes,
  586. *,
  587. _tag: _ASN1Type | None = None,
  588. ) -> CertificateSigningRequestBuilder:
  589. """
  590. Adds an X.509 attribute with an OID and associated value.
  591. """
  592. if not isinstance(oid, ObjectIdentifier):
  593. raise TypeError("oid must be an ObjectIdentifier")
  594. if not isinstance(value, bytes):
  595. raise TypeError("value must be bytes")
  596. if _tag is not None and not isinstance(_tag, _ASN1Type):
  597. raise TypeError("tag must be _ASN1Type")
  598. _reject_duplicate_attribute(oid, self._attributes)
  599. if _tag is not None:
  600. tag = _tag.value
  601. else:
  602. tag = None
  603. return CertificateSigningRequestBuilder(
  604. self._subject_name,
  605. self._extensions,
  606. [*self._attributes, (oid, value, tag)],
  607. )
  608. def sign(
  609. self,
  610. private_key: CertificateIssuerPrivateKeyTypes,
  611. algorithm: _AllowedHashTypes | None,
  612. backend: typing.Any = None,
  613. *,
  614. rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
  615. ) -> CertificateSigningRequest:
  616. """
  617. Signs the request using the requestor's private key.
  618. """
  619. if self._subject_name is None:
  620. raise ValueError("A CertificateSigningRequest must have a subject")
  621. if rsa_padding is not None:
  622. if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
  623. raise TypeError("Padding must be PSS or PKCS1v15")
  624. if not isinstance(private_key, rsa.RSAPrivateKey):
  625. raise TypeError("Padding is only supported for RSA keys")
  626. return rust_x509.create_x509_csr(
  627. self, private_key, algorithm, rsa_padding
  628. )
  629. class CertificateBuilder:
  630. _extensions: list[Extension[ExtensionType]]
  631. def __init__(
  632. self,
  633. issuer_name: Name | None = None,
  634. subject_name: Name | None = None,
  635. public_key: CertificatePublicKeyTypes | None = None,
  636. serial_number: int | None = None,
  637. not_valid_before: datetime.datetime | None = None,
  638. not_valid_after: datetime.datetime | None = None,
  639. extensions: list[Extension[ExtensionType]] = [],
  640. ) -> None:
  641. self._version = Version.v3
  642. self._issuer_name = issuer_name
  643. self._subject_name = subject_name
  644. self._public_key = public_key
  645. self._serial_number = serial_number
  646. self._not_valid_before = not_valid_before
  647. self._not_valid_after = not_valid_after
  648. self._extensions = extensions
  649. def issuer_name(self, name: Name) -> CertificateBuilder:
  650. """
  651. Sets the CA's distinguished name.
  652. """
  653. if not isinstance(name, Name):
  654. raise TypeError("Expecting x509.Name object.")
  655. if self._issuer_name is not None:
  656. raise ValueError("The issuer name may only be set once.")
  657. return CertificateBuilder(
  658. name,
  659. self._subject_name,
  660. self._public_key,
  661. self._serial_number,
  662. self._not_valid_before,
  663. self._not_valid_after,
  664. self._extensions,
  665. )
  666. def subject_name(self, name: Name) -> CertificateBuilder:
  667. """
  668. Sets the requestor's distinguished name.
  669. """
  670. if not isinstance(name, Name):
  671. raise TypeError("Expecting x509.Name object.")
  672. if self._subject_name is not None:
  673. raise ValueError("The subject name may only be set once.")
  674. return CertificateBuilder(
  675. self._issuer_name,
  676. name,
  677. self._public_key,
  678. self._serial_number,
  679. self._not_valid_before,
  680. self._not_valid_after,
  681. self._extensions,
  682. )
  683. def public_key(
  684. self,
  685. key: CertificatePublicKeyTypes,
  686. ) -> CertificateBuilder:
  687. """
  688. Sets the requestor's public key (as found in the signing request).
  689. """
  690. if not isinstance(
  691. key,
  692. (
  693. dsa.DSAPublicKey,
  694. rsa.RSAPublicKey,
  695. ec.EllipticCurvePublicKey,
  696. ed25519.Ed25519PublicKey,
  697. ed448.Ed448PublicKey,
  698. x25519.X25519PublicKey,
  699. x448.X448PublicKey,
  700. ),
  701. ):
  702. raise TypeError(
  703. "Expecting one of DSAPublicKey, RSAPublicKey,"
  704. " EllipticCurvePublicKey, Ed25519PublicKey,"
  705. " Ed448PublicKey, X25519PublicKey, or "
  706. "X448PublicKey."
  707. )
  708. if self._public_key is not None:
  709. raise ValueError("The public key may only be set once.")
  710. return CertificateBuilder(
  711. self._issuer_name,
  712. self._subject_name,
  713. key,
  714. self._serial_number,
  715. self._not_valid_before,
  716. self._not_valid_after,
  717. self._extensions,
  718. )
  719. def serial_number(self, number: int) -> CertificateBuilder:
  720. """
  721. Sets the certificate serial number.
  722. """
  723. if not isinstance(number, int):
  724. raise TypeError("Serial number must be of integral type.")
  725. if self._serial_number is not None:
  726. raise ValueError("The serial number may only be set once.")
  727. if number <= 0:
  728. raise ValueError("The serial number should be positive.")
  729. # ASN.1 integers are always signed, so most significant bit must be
  730. # zero.
  731. if number.bit_length() >= 160: # As defined in RFC 5280
  732. raise ValueError(
  733. "The serial number should not be more than 159 bits."
  734. )
  735. return CertificateBuilder(
  736. self._issuer_name,
  737. self._subject_name,
  738. self._public_key,
  739. number,
  740. self._not_valid_before,
  741. self._not_valid_after,
  742. self._extensions,
  743. )
  744. def not_valid_before(self, time: datetime.datetime) -> CertificateBuilder:
  745. """
  746. Sets the certificate activation time.
  747. """
  748. if not isinstance(time, datetime.datetime):
  749. raise TypeError("Expecting datetime object.")
  750. if self._not_valid_before is not None:
  751. raise ValueError("The not valid before may only be set once.")
  752. time = _convert_to_naive_utc_time(time)
  753. if time < _EARLIEST_UTC_TIME:
  754. raise ValueError(
  755. "The not valid before date must be on or after"
  756. " 1950 January 1)."
  757. )
  758. if self._not_valid_after is not None and time > self._not_valid_after:
  759. raise ValueError(
  760. "The not valid before date must be before the not valid after "
  761. "date."
  762. )
  763. return CertificateBuilder(
  764. self._issuer_name,
  765. self._subject_name,
  766. self._public_key,
  767. self._serial_number,
  768. time,
  769. self._not_valid_after,
  770. self._extensions,
  771. )
  772. def not_valid_after(self, time: datetime.datetime) -> CertificateBuilder:
  773. """
  774. Sets the certificate expiration time.
  775. """
  776. if not isinstance(time, datetime.datetime):
  777. raise TypeError("Expecting datetime object.")
  778. if self._not_valid_after is not None:
  779. raise ValueError("The not valid after may only be set once.")
  780. time = _convert_to_naive_utc_time(time)
  781. if time < _EARLIEST_UTC_TIME:
  782. raise ValueError(
  783. "The not valid after date must be on or after"
  784. " 1950 January 1."
  785. )
  786. if (
  787. self._not_valid_before is not None
  788. and time < self._not_valid_before
  789. ):
  790. raise ValueError(
  791. "The not valid after date must be after the not valid before "
  792. "date."
  793. )
  794. return CertificateBuilder(
  795. self._issuer_name,
  796. self._subject_name,
  797. self._public_key,
  798. self._serial_number,
  799. self._not_valid_before,
  800. time,
  801. self._extensions,
  802. )
  803. def add_extension(
  804. self, extval: ExtensionType, critical: bool
  805. ) -> CertificateBuilder:
  806. """
  807. Adds an X.509 extension to the certificate.
  808. """
  809. if not isinstance(extval, ExtensionType):
  810. raise TypeError("extension must be an ExtensionType")
  811. extension = Extension(extval.oid, critical, extval)
  812. _reject_duplicate_extension(extension, self._extensions)
  813. return CertificateBuilder(
  814. self._issuer_name,
  815. self._subject_name,
  816. self._public_key,
  817. self._serial_number,
  818. self._not_valid_before,
  819. self._not_valid_after,
  820. [*self._extensions, extension],
  821. )
  822. def sign(
  823. self,
  824. private_key: CertificateIssuerPrivateKeyTypes,
  825. algorithm: _AllowedHashTypes | None,
  826. backend: typing.Any = None,
  827. *,
  828. rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
  829. ) -> Certificate:
  830. """
  831. Signs the certificate using the CA's private key.
  832. """
  833. if self._subject_name is None:
  834. raise ValueError("A certificate must have a subject name")
  835. if self._issuer_name is None:
  836. raise ValueError("A certificate must have an issuer name")
  837. if self._serial_number is None:
  838. raise ValueError("A certificate must have a serial number")
  839. if self._not_valid_before is None:
  840. raise ValueError("A certificate must have a not valid before time")
  841. if self._not_valid_after is None:
  842. raise ValueError("A certificate must have a not valid after time")
  843. if self._public_key is None:
  844. raise ValueError("A certificate must have a public key")
  845. if rsa_padding is not None:
  846. if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
  847. raise TypeError("Padding must be PSS or PKCS1v15")
  848. if not isinstance(private_key, rsa.RSAPrivateKey):
  849. raise TypeError("Padding is only supported for RSA keys")
  850. return rust_x509.create_x509_certificate(
  851. self, private_key, algorithm, rsa_padding
  852. )
  853. class CertificateRevocationListBuilder:
  854. _extensions: list[Extension[ExtensionType]]
  855. _revoked_certificates: list[RevokedCertificate]
  856. def __init__(
  857. self,
  858. issuer_name: Name | None = None,
  859. last_update: datetime.datetime | None = None,
  860. next_update: datetime.datetime | None = None,
  861. extensions: list[Extension[ExtensionType]] = [],
  862. revoked_certificates: list[RevokedCertificate] = [],
  863. ):
  864. self._issuer_name = issuer_name
  865. self._last_update = last_update
  866. self._next_update = next_update
  867. self._extensions = extensions
  868. self._revoked_certificates = revoked_certificates
  869. def issuer_name(
  870. self, issuer_name: Name
  871. ) -> CertificateRevocationListBuilder:
  872. if not isinstance(issuer_name, Name):
  873. raise TypeError("Expecting x509.Name object.")
  874. if self._issuer_name is not None:
  875. raise ValueError("The issuer name may only be set once.")
  876. return CertificateRevocationListBuilder(
  877. issuer_name,
  878. self._last_update,
  879. self._next_update,
  880. self._extensions,
  881. self._revoked_certificates,
  882. )
  883. def last_update(
  884. self, last_update: datetime.datetime
  885. ) -> CertificateRevocationListBuilder:
  886. if not isinstance(last_update, datetime.datetime):
  887. raise TypeError("Expecting datetime object.")
  888. if self._last_update is not None:
  889. raise ValueError("Last update may only be set once.")
  890. last_update = _convert_to_naive_utc_time(last_update)
  891. if last_update < _EARLIEST_UTC_TIME:
  892. raise ValueError(
  893. "The last update date must be on or after 1950 January 1."
  894. )
  895. if self._next_update is not None and last_update > self._next_update:
  896. raise ValueError(
  897. "The last update date must be before the next update date."
  898. )
  899. return CertificateRevocationListBuilder(
  900. self._issuer_name,
  901. last_update,
  902. self._next_update,
  903. self._extensions,
  904. self._revoked_certificates,
  905. )
  906. def next_update(
  907. self, next_update: datetime.datetime
  908. ) -> CertificateRevocationListBuilder:
  909. if not isinstance(next_update, datetime.datetime):
  910. raise TypeError("Expecting datetime object.")
  911. if self._next_update is not None:
  912. raise ValueError("Last update may only be set once.")
  913. next_update = _convert_to_naive_utc_time(next_update)
  914. if next_update < _EARLIEST_UTC_TIME:
  915. raise ValueError(
  916. "The last update date must be on or after 1950 January 1."
  917. )
  918. if self._last_update is not None and next_update < self._last_update:
  919. raise ValueError(
  920. "The next update date must be after the last update date."
  921. )
  922. return CertificateRevocationListBuilder(
  923. self._issuer_name,
  924. self._last_update,
  925. next_update,
  926. self._extensions,
  927. self._revoked_certificates,
  928. )
  929. def add_extension(
  930. self, extval: ExtensionType, critical: bool
  931. ) -> CertificateRevocationListBuilder:
  932. """
  933. Adds an X.509 extension to the certificate revocation list.
  934. """
  935. if not isinstance(extval, ExtensionType):
  936. raise TypeError("extension must be an ExtensionType")
  937. extension = Extension(extval.oid, critical, extval)
  938. _reject_duplicate_extension(extension, self._extensions)
  939. return CertificateRevocationListBuilder(
  940. self._issuer_name,
  941. self._last_update,
  942. self._next_update,
  943. [*self._extensions, extension],
  944. self._revoked_certificates,
  945. )
  946. def add_revoked_certificate(
  947. self, revoked_certificate: RevokedCertificate
  948. ) -> CertificateRevocationListBuilder:
  949. """
  950. Adds a revoked certificate to the CRL.
  951. """
  952. if not isinstance(revoked_certificate, RevokedCertificate):
  953. raise TypeError("Must be an instance of RevokedCertificate")
  954. return CertificateRevocationListBuilder(
  955. self._issuer_name,
  956. self._last_update,
  957. self._next_update,
  958. self._extensions,
  959. [*self._revoked_certificates, revoked_certificate],
  960. )
  961. def sign(
  962. self,
  963. private_key: CertificateIssuerPrivateKeyTypes,
  964. algorithm: _AllowedHashTypes | None,
  965. backend: typing.Any = None,
  966. *,
  967. rsa_padding: padding.PSS | padding.PKCS1v15 | None = None,
  968. ) -> CertificateRevocationList:
  969. if self._issuer_name is None:
  970. raise ValueError("A CRL must have an issuer name")
  971. if self._last_update is None:
  972. raise ValueError("A CRL must have a last update time")
  973. if self._next_update is None:
  974. raise ValueError("A CRL must have a next update time")
  975. if rsa_padding is not None:
  976. if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)):
  977. raise TypeError("Padding must be PSS or PKCS1v15")
  978. if not isinstance(private_key, rsa.RSAPrivateKey):
  979. raise TypeError("Padding is only supported for RSA keys")
  980. return rust_x509.create_x509_crl(
  981. self, private_key, algorithm, rsa_padding
  982. )
  983. class RevokedCertificateBuilder:
  984. def __init__(
  985. self,
  986. serial_number: int | None = None,
  987. revocation_date: datetime.datetime | None = None,
  988. extensions: list[Extension[ExtensionType]] = [],
  989. ):
  990. self._serial_number = serial_number
  991. self._revocation_date = revocation_date
  992. self._extensions = extensions
  993. def serial_number(self, number: int) -> RevokedCertificateBuilder:
  994. if not isinstance(number, int):
  995. raise TypeError("Serial number must be of integral type.")
  996. if self._serial_number is not None:
  997. raise ValueError("The serial number may only be set once.")
  998. if number <= 0:
  999. raise ValueError("The serial number should be positive")
  1000. # ASN.1 integers are always signed, so most significant bit must be
  1001. # zero.
  1002. if number.bit_length() >= 160: # As defined in RFC 5280
  1003. raise ValueError(
  1004. "The serial number should not be more than 159 bits."
  1005. )
  1006. return RevokedCertificateBuilder(
  1007. number, self._revocation_date, self._extensions
  1008. )
  1009. def revocation_date(
  1010. self, time: datetime.datetime
  1011. ) -> RevokedCertificateBuilder:
  1012. if not isinstance(time, datetime.datetime):
  1013. raise TypeError("Expecting datetime object.")
  1014. if self._revocation_date is not None:
  1015. raise ValueError("The revocation date may only be set once.")
  1016. time = _convert_to_naive_utc_time(time)
  1017. if time < _EARLIEST_UTC_TIME:
  1018. raise ValueError(
  1019. "The revocation date must be on or after 1950 January 1."
  1020. )
  1021. return RevokedCertificateBuilder(
  1022. self._serial_number, time, self._extensions
  1023. )
  1024. def add_extension(
  1025. self, extval: ExtensionType, critical: bool
  1026. ) -> RevokedCertificateBuilder:
  1027. if not isinstance(extval, ExtensionType):
  1028. raise TypeError("extension must be an ExtensionType")
  1029. extension = Extension(extval.oid, critical, extval)
  1030. _reject_duplicate_extension(extension, self._extensions)
  1031. return RevokedCertificateBuilder(
  1032. self._serial_number,
  1033. self._revocation_date,
  1034. [*self._extensions, extension],
  1035. )
  1036. def build(self, backend: typing.Any = None) -> RevokedCertificate:
  1037. if self._serial_number is None:
  1038. raise ValueError("A revoked certificate must have a serial number")
  1039. if self._revocation_date is None:
  1040. raise ValueError(
  1041. "A revoked certificate must have a revocation date"
  1042. )
  1043. return _RawRevokedCertificate(
  1044. self._serial_number,
  1045. self._revocation_date,
  1046. Extensions(self._extensions),
  1047. )
  1048. def random_serial_number() -> int:
  1049. return int.from_bytes(os.urandom(20), "big") >> 1