pkcs12.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 typing
  6. from collections.abc import Iterable
  7. from cryptography import x509
  8. from cryptography.hazmat.bindings._rust import pkcs12 as rust_pkcs12
  9. from cryptography.hazmat.primitives import serialization
  10. from cryptography.hazmat.primitives._serialization import PBES as PBES
  11. from cryptography.hazmat.primitives.asymmetric import (
  12. dsa,
  13. ec,
  14. ed448,
  15. ed25519,
  16. rsa,
  17. )
  18. from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
  19. __all__ = [
  20. "PBES",
  21. "PKCS12Certificate",
  22. "PKCS12KeyAndCertificates",
  23. "PKCS12PrivateKeyTypes",
  24. "load_key_and_certificates",
  25. "load_pkcs12",
  26. "serialize_java_truststore",
  27. "serialize_key_and_certificates",
  28. ]
  29. PKCS12PrivateKeyTypes = typing.Union[
  30. rsa.RSAPrivateKey,
  31. dsa.DSAPrivateKey,
  32. ec.EllipticCurvePrivateKey,
  33. ed25519.Ed25519PrivateKey,
  34. ed448.Ed448PrivateKey,
  35. ]
  36. PKCS12Certificate = rust_pkcs12.PKCS12Certificate
  37. class PKCS12KeyAndCertificates:
  38. def __init__(
  39. self,
  40. key: PrivateKeyTypes | None,
  41. cert: PKCS12Certificate | None,
  42. additional_certs: list[PKCS12Certificate],
  43. ):
  44. if key is not None and not isinstance(
  45. key,
  46. (
  47. rsa.RSAPrivateKey,
  48. dsa.DSAPrivateKey,
  49. ec.EllipticCurvePrivateKey,
  50. ed25519.Ed25519PrivateKey,
  51. ed448.Ed448PrivateKey,
  52. ),
  53. ):
  54. raise TypeError(
  55. "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448"
  56. " private key, or None."
  57. )
  58. if cert is not None and not isinstance(cert, PKCS12Certificate):
  59. raise TypeError("cert must be a PKCS12Certificate object or None")
  60. if not all(
  61. isinstance(add_cert, PKCS12Certificate)
  62. for add_cert in additional_certs
  63. ):
  64. raise TypeError(
  65. "all values in additional_certs must be PKCS12Certificate"
  66. " objects"
  67. )
  68. self._key = key
  69. self._cert = cert
  70. self._additional_certs = additional_certs
  71. @property
  72. def key(self) -> PrivateKeyTypes | None:
  73. return self._key
  74. @property
  75. def cert(self) -> PKCS12Certificate | None:
  76. return self._cert
  77. @property
  78. def additional_certs(self) -> list[PKCS12Certificate]:
  79. return self._additional_certs
  80. def __eq__(self, other: object) -> bool:
  81. if not isinstance(other, PKCS12KeyAndCertificates):
  82. return NotImplemented
  83. return (
  84. self.key == other.key
  85. and self.cert == other.cert
  86. and self.additional_certs == other.additional_certs
  87. )
  88. def __hash__(self) -> int:
  89. return hash((self.key, self.cert, tuple(self.additional_certs)))
  90. def __repr__(self) -> str:
  91. fmt = (
  92. "<PKCS12KeyAndCertificates(key={}, cert={}, additional_certs={})>"
  93. )
  94. return fmt.format(self.key, self.cert, self.additional_certs)
  95. load_key_and_certificates = rust_pkcs12.load_key_and_certificates
  96. load_pkcs12 = rust_pkcs12.load_pkcs12
  97. _PKCS12CATypes = typing.Union[
  98. x509.Certificate,
  99. PKCS12Certificate,
  100. ]
  101. def serialize_java_truststore(
  102. certs: Iterable[PKCS12Certificate],
  103. encryption_algorithm: serialization.KeySerializationEncryption,
  104. ) -> bytes:
  105. if not certs:
  106. raise ValueError("You must supply at least one cert")
  107. if not isinstance(
  108. encryption_algorithm, serialization.KeySerializationEncryption
  109. ):
  110. raise TypeError(
  111. "Key encryption algorithm must be a "
  112. "KeySerializationEncryption instance"
  113. )
  114. return rust_pkcs12.serialize_java_truststore(certs, encryption_algorithm)
  115. def serialize_key_and_certificates(
  116. name: bytes | None,
  117. key: PKCS12PrivateKeyTypes | None,
  118. cert: x509.Certificate | None,
  119. cas: Iterable[_PKCS12CATypes] | None,
  120. encryption_algorithm: serialization.KeySerializationEncryption,
  121. ) -> bytes:
  122. if key is not None and not isinstance(
  123. key,
  124. (
  125. rsa.RSAPrivateKey,
  126. dsa.DSAPrivateKey,
  127. ec.EllipticCurvePrivateKey,
  128. ed25519.Ed25519PrivateKey,
  129. ed448.Ed448PrivateKey,
  130. ),
  131. ):
  132. raise TypeError(
  133. "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448"
  134. " private key, or None."
  135. )
  136. if not isinstance(
  137. encryption_algorithm, serialization.KeySerializationEncryption
  138. ):
  139. raise TypeError(
  140. "Key encryption algorithm must be a "
  141. "KeySerializationEncryption instance"
  142. )
  143. if key is None and cert is None and not cas:
  144. raise ValueError("You must supply at least one of key, cert, or cas")
  145. return rust_pkcs12.serialize_key_and_certificates(
  146. name, key, cert, cas, encryption_algorithm
  147. )