py2docfx 0.1.9.dev1927679__py3-none-any.whl → 0.1.9.dev1929293__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. py2docfx/__main__.py +18 -2
  2. py2docfx/convert_prepare/git.py +8 -5
  3. py2docfx/docfx_yaml/logger.py +13 -0
  4. py2docfx/venv/venv1/Lib/site-packages/cryptography/__about__.py +1 -1
  5. py2docfx/venv/venv1/Lib/site-packages/cryptography/__init__.py +13 -0
  6. py2docfx/venv/venv1/Lib/site-packages/cryptography/fernet.py +8 -0
  7. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/_oid.py +2 -0
  8. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py +8 -14
  9. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py +10 -7
  10. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py +12 -6
  11. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/argon2.py +13 -0
  12. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py +3 -64
  13. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/padding.py +3 -24
  14. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py +33 -0
  15. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py +9 -1
  16. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py +5 -0
  17. py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/__init__.py +8 -0
  18. py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/base.py +4 -415
  19. py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/certificate_transparency.py +1 -63
  20. py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/extensions.py +286 -5
  21. py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/ocsp.py +4 -338
  22. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/__init__.py +1 -1
  23. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/any.py +39 -0
  24. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/any_pb2.py +3 -3
  25. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/api_pb2.py +3 -3
  26. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py +3 -3
  27. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pb2.py +108 -108
  28. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/duration.py +100 -0
  29. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/duration_pb2.py +3 -3
  30. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/empty_pb2.py +3 -3
  31. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/field_mask_pb2.py +3 -3
  32. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_message.py +7 -4
  33. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/well_known_types.py +1 -1
  34. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/pyext/cpp_message.py +1 -1
  35. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/runtime_version.py +16 -9
  36. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/service.py +4 -4
  37. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/source_context_pb2.py +3 -3
  38. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/struct_pb2.py +3 -3
  39. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/text_format.py +1 -1
  40. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/timestamp.py +112 -0
  41. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/timestamp_pb2.py +3 -3
  42. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/type_pb2.py +3 -3
  43. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/wrappers_pb2.py +3 -3
  44. py2docfx/venv/venv1/Lib/site-packages/jwt/__init__.py +1 -1
  45. py2docfx/venv/venv1/Lib/site-packages/jwt/api_jwt.py +3 -3
  46. {py2docfx-0.1.9.dev1927679.dist-info → py2docfx-0.1.9.dev1929293.dist-info}/METADATA +1 -1
  47. {py2docfx-0.1.9.dev1927679.dist-info → py2docfx-0.1.9.dev1929293.dist-info}/RECORD +49 -45
  48. {py2docfx-0.1.9.dev1927679.dist-info → py2docfx-0.1.9.dev1929293.dist-info}/WHEEL +0 -0
  49. {py2docfx-0.1.9.dev1927679.dist-info → py2docfx-0.1.9.dev1929293.dist-info}/top_level.txt +0 -0
py2docfx/__main__.py CHANGED
@@ -3,6 +3,7 @@ import asyncio
3
3
  import argparse
4
4
  import logging
5
5
  import os
6
+ import stat
6
7
  import sys
7
8
  import shutil
8
9
 
@@ -16,6 +17,8 @@ from py2docfx.convert_prepare.params import load_file_params, load_command_param
16
17
  from py2docfx.convert_prepare.package_info import PackageInfo
17
18
  import py2docfx.convert_prepare.environment as py2docfxEnvironment
18
19
 
20
+ os.chdir(PACKAGE_ROOT)
21
+
19
22
  def get_parser() -> argparse.ArgumentParser:
20
23
  parser = argparse.ArgumentParser(
21
24
  description=(
@@ -310,10 +313,24 @@ def prepare_out_dir(output_root: str | os.PathLike) -> os.PathLike | None:
310
313
  else:
311
314
  return None
312
315
 
316
+ def on_rm_error( func, path, exc_info):
317
+ # path contains the path of the file that couldn't be removed
318
+ # let's just assume that it's read-only and unlink it.
319
+ os.chmod(path, stat.S_IWRITE)
320
+ os.unlink(path)
321
+
322
+ def remove_folder(folder: str | os.PathLike) -> None:
323
+ try:
324
+ shutil.rmtree(folder)
325
+ except PermissionError:
326
+ shutil.rmtree(folder, ignore_errors=False, onerror=on_rm_error)
327
+ if os.path.exists(folder):
328
+ raise ValueError(f"Failed to remove folder {folder}")
329
+
313
330
  def temp_folder_clean_up(folder_list: list[str | os.PathLike]) -> None:
314
331
  for folder in folder_list:
315
332
  if os.path.exists(folder):
316
- shutil.rmtree(folder)
333
+ remove_folder(folder)
317
334
 
318
335
  def decide_global_log_level(verbose: bool, show_warning: bool) -> None:
319
336
  if verbose and show_warning:
@@ -347,7 +364,6 @@ def main(argv) -> int:
347
364
  py2docfx_logger.info(msg)
348
365
 
349
366
  sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),'docfx_yaml'))
350
- os.chdir(PACKAGE_ROOT)
351
367
  output_doc_folder = prepare_out_dir(output_root)
352
368
 
353
369
  try:
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  import subprocess
3
3
 
4
- from py2docfx.docfx_yaml.logger import get_logger
4
+ from py2docfx.docfx_yaml.logger import get_logger, log_git_clone_subprocess_ouput
5
5
 
6
6
  repoMap = {}
7
7
 
@@ -57,7 +57,8 @@ def clone(repo_location, branch, folder, extra_token=None):
57
57
  extra_token
58
58
  ),
59
59
  ]
60
- subprocess.run(clone_params, check=True)
60
+ output = subprocess.run(clone_params, check=True, capture_output=True, text=True)
61
+ log_git_clone_subprocess_ouput(output, py2docfx_logger)
61
62
  repoMap[pureURL] = folder
62
63
  msg = "<CI INFO>: Repo {} successfully cloned in {}...".format(
63
64
  repo_location, repoMap[pureURL]
@@ -144,7 +145,7 @@ def checkout(folder, branch):
144
145
  if "* {}".format(branch) not in branches:
145
146
  # branch is not exactly current branch
146
147
  if branch not in branches:
147
- subprocess.run(
148
+ output = subprocess.run(
148
149
  [
149
150
  "git",
150
151
  "-C",
@@ -153,10 +154,12 @@ def checkout(folder, branch):
153
154
  "--quiet",
154
155
  remote,
155
156
  "{}:{}".format(branch, branch),
156
- ]
157
+ ], capture_output=True, text=True
157
158
  )
159
+ log_subprocess_ouput(output, py2docfx_logger)
158
160
 
159
- subprocess.run(["git", "-C", folder, "checkout", "--quiet", branch])
161
+ output = subprocess.run(["git", "-C", folder, "checkout", "--quiet", branch], check=True, capture_output=True, text=True)
162
+ log_subprocess_ouput(output, py2docfx_logger)
160
163
  msg = "<CI INFO>: Switched to branch {}.".format(branch)
161
164
  py2docfx_logger.info(msg)
162
165
 
@@ -71,6 +71,19 @@ def log_subprocess_ouput(subprocess_out: subprocess.CompletedProcess, logger: lo
71
71
  logger.error(f"Subprocess failed with return code {subprocess_out.returncode}")
72
72
  raise RuntimeError()
73
73
 
74
+ def log_git_clone_subprocess_ouput(subprocess_out: subprocess.CompletedProcess, logger: logging.Logger):
75
+ if subprocess_out.stdout:
76
+ logger.info(subprocess_out.stdout)
77
+ if subprocess_out.stderr:
78
+ msgs = subprocess_out.stderr.split('\n')
79
+ for msg in msgs:
80
+ if msg is None or msg == "":
81
+ continue
82
+ logger.info(msg)
83
+ if subprocess_out.returncode != 0:
84
+ logger.error(f"Subprocess failed with return code {subprocess_out.returncode}")
85
+ raise RuntimeError()
86
+
74
87
  def counts_errors_warnings(log_file_path):
75
88
  error_count = 0
76
89
  warning_count = 0
@@ -10,7 +10,7 @@ __all__ = [
10
10
  "__version__",
11
11
  ]
12
12
 
13
- __version__ = "43.0.3"
13
+ __version__ = "44.0.0"
14
14
 
15
15
 
16
16
  __author__ = "The Python Cryptographic Authority and individual contributors"
@@ -4,6 +4,10 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ import sys
8
+ import warnings
9
+
10
+ from cryptography import utils
7
11
  from cryptography.__about__ import __author__, __copyright__, __version__
8
12
 
9
13
  __all__ = [
@@ -11,3 +15,12 @@ __all__ = [
11
15
  "__copyright__",
12
16
  "__version__",
13
17
  ]
18
+
19
+ if sys.version_info[:2] == (3, 7):
20
+ warnings.warn(
21
+ "Python 3.7 is no longer supported by the Python core team "
22
+ "and support for it is deprecated in cryptography. A future "
23
+ "release of cryptography will remove support for Python 3.7.",
24
+ utils.CryptographyDeprecationWarning,
25
+ stacklevel=2,
26
+ )
@@ -213,3 +213,11 @@ class MultiFernet:
213
213
  except InvalidToken:
214
214
  pass
215
215
  raise InvalidToken
216
+
217
+ def extract_timestamp(self, msg: bytes | str) -> int:
218
+ for f in self._fernets:
219
+ try:
220
+ return f.extract_timestamp(msg)
221
+ except InvalidToken:
222
+ pass
223
+ raise InvalidToken
@@ -39,6 +39,7 @@ class ExtensionOID:
39
39
  PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3")
40
40
  SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5")
41
41
  MS_CERTIFICATE_TEMPLATE = ObjectIdentifier("1.3.6.1.4.1.311.21.7")
42
+ ADMISSIONS = ObjectIdentifier("1.3.36.8.3.3")
42
43
 
43
44
 
44
45
  class OCSPExtensionOID:
@@ -284,6 +285,7 @@ _OID_NAMES = {
284
285
  ),
285
286
  ExtensionOID.PRECERT_POISON: "ctPoison",
286
287
  ExtensionOID.MS_CERTIFICATE_TEMPLATE: "msCertificateTemplate",
288
+ ExtensionOID.ADMISSIONS: "Admissions",
287
289
  CRLEntryExtensionOID.CRL_REASON: "cRLReason",
288
290
  CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate",
289
291
  CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer",
@@ -101,23 +101,11 @@ class Backend:
101
101
  def openssl_version_number(self) -> int:
102
102
  return rust_openssl.openssl_version()
103
103
 
104
- def _evp_md_from_algorithm(self, algorithm: hashes.HashAlgorithm):
105
- if algorithm.name in ("blake2b", "blake2s"):
106
- alg = f"{algorithm.name}{algorithm.digest_size * 8}".encode(
107
- "ascii"
108
- )
109
- else:
110
- alg = algorithm.name.encode("ascii")
111
-
112
- evp_md = self._lib.EVP_get_digestbyname(alg)
113
- return evp_md
114
-
115
104
  def hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool:
116
105
  if self._fips_enabled and not isinstance(algorithm, self._fips_hashes):
117
106
  return False
118
107
 
119
- evp_md = self._evp_md_from_algorithm(algorithm)
120
- return evp_md != self._ffi.NULL
108
+ return rust_openssl.hashes.hash_supported(algorithm)
121
109
 
122
110
  def signature_hash_supported(
123
111
  self, algorithm: hashes.HashAlgorithm
@@ -132,7 +120,13 @@ class Backend:
132
120
  if self._fips_enabled:
133
121
  return False
134
122
  else:
135
- return hasattr(rust_openssl.kdf, "derive_scrypt")
123
+ return hasattr(rust_openssl.kdf.Scrypt, "derive")
124
+
125
+ def argon2_supported(self) -> bool:
126
+ if self._fips_enabled:
127
+ return False
128
+ else:
129
+ return hasattr(rust_openssl.kdf.Argon2id, "derive")
136
130
 
137
131
  def hmac_supported(self, algorithm: hashes.HashAlgorithm) -> bool:
138
132
  # FIPS mode still allows SHA1 for HMAC
@@ -5,6 +5,7 @@
5
5
  from __future__ import annotations
6
6
 
7
7
  import abc
8
+ import random
8
9
  import typing
9
10
  from math import gcd
10
11
 
@@ -212,9 +213,8 @@ def rsa_recover_private_exponent(e: int, p: int, q: int) -> int:
212
213
 
213
214
 
214
215
  # Controls the number of iterations rsa_recover_prime_factors will perform
215
- # to obtain the prime factors. Each iteration increments by 2 so the actual
216
- # maximum attempts is half this number.
217
- _MAX_RECOVERY_ATTEMPTS = 1000
216
+ # to obtain the prime factors.
217
+ _MAX_RECOVERY_ATTEMPTS = 500
218
218
 
219
219
 
220
220
  def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]:
@@ -222,6 +222,9 @@ def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]:
222
222
  Compute factors p and q from the private exponent d. We assume that n has
223
223
  no more than two factors. This function is adapted from code in PyCrypto.
224
224
  """
225
+ # reject invalid values early
226
+ if 17 != pow(17, e * d, n):
227
+ raise ValueError("n, d, e don't match")
225
228
  # See 8.2.2(i) in Handbook of Applied Cryptography.
226
229
  ktot = d * e - 1
227
230
  # The quantity d*e-1 is a multiple of phi(n), even,
@@ -235,8 +238,10 @@ def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]:
235
238
  # See "Digitalized Signatures and Public Key Functions as Intractable
236
239
  # as Factorization", M. Rabin, 1979
237
240
  spotted = False
238
- a = 2
239
- while not spotted and a < _MAX_RECOVERY_ATTEMPTS:
241
+ tries = 0
242
+ while not spotted and tries < _MAX_RECOVERY_ATTEMPTS:
243
+ a = random.randint(2, n - 1)
244
+ tries += 1
240
245
  k = t
241
246
  # Cycle through all values a^{t*2^i}=a^k
242
247
  while k < ktot:
@@ -249,8 +254,6 @@ def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]:
249
254
  spotted = True
250
255
  break
251
256
  k *= 2
252
- # This value was not any good... let's try another!
253
- a += 2
254
257
  if not spotted:
255
258
  raise ValueError("Unable to compute factors p and q from exponent d.")
256
259
  # Found !
@@ -82,7 +82,8 @@ utils.deprecated(
82
82
  __name__,
83
83
  "ARC4 has been moved to "
84
84
  "cryptography.hazmat.decrepit.ciphers.algorithms.ARC4 and "
85
- "will be removed from this module in 48.0.0.",
85
+ "will be removed from "
86
+ "cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.",
86
87
  utils.DeprecatedIn43,
87
88
  name="ARC4",
88
89
  )
@@ -93,7 +94,8 @@ utils.deprecated(
93
94
  __name__,
94
95
  "TripleDES has been moved to "
95
96
  "cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and "
96
- "will be removed from this module in 48.0.0.",
97
+ "will be removed from "
98
+ "cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.",
97
99
  utils.DeprecatedIn43,
98
100
  name="TripleDES",
99
101
  )
@@ -103,7 +105,8 @@ utils.deprecated(
103
105
  __name__,
104
106
  "Blowfish has been moved to "
105
107
  "cryptography.hazmat.decrepit.ciphers.algorithms.Blowfish and "
106
- "will be removed from this module in 45.0.0.",
108
+ "will be removed from "
109
+ "cryptography.hazmat.primitives.ciphers.algorithms in 45.0.0.",
107
110
  utils.DeprecatedIn37,
108
111
  name="Blowfish",
109
112
  )
@@ -114,7 +117,8 @@ utils.deprecated(
114
117
  __name__,
115
118
  "CAST5 has been moved to "
116
119
  "cryptography.hazmat.decrepit.ciphers.algorithms.CAST5 and "
117
- "will be removed from this module in 45.0.0.",
120
+ "will be removed from "
121
+ "cryptography.hazmat.primitives.ciphers.algorithms in 45.0.0.",
118
122
  utils.DeprecatedIn37,
119
123
  name="CAST5",
120
124
  )
@@ -125,7 +129,8 @@ utils.deprecated(
125
129
  __name__,
126
130
  "IDEA has been moved to "
127
131
  "cryptography.hazmat.decrepit.ciphers.algorithms.IDEA and "
128
- "will be removed from this module in 45.0.0.",
132
+ "will be removed from "
133
+ "cryptography.hazmat.primitives.ciphers.algorithms in 45.0.0.",
129
134
  utils.DeprecatedIn37,
130
135
  name="IDEA",
131
136
  )
@@ -136,7 +141,8 @@ utils.deprecated(
136
141
  __name__,
137
142
  "SEED has been moved to "
138
143
  "cryptography.hazmat.decrepit.ciphers.algorithms.SEED and "
139
- "will be removed from this module in 45.0.0.",
144
+ "will be removed from "
145
+ "cryptography.hazmat.primitives.ciphers.algorithms in 45.0.0.",
140
146
  utils.DeprecatedIn37,
141
147
  name="SEED",
142
148
  )
@@ -0,0 +1,13 @@
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
+
5
+ from __future__ import annotations
6
+
7
+ from cryptography.hazmat.bindings._rust import openssl as rust_openssl
8
+ from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
9
+
10
+ Argon2id = rust_openssl.kdf.Argon2id
11
+ KeyDerivationFunction.register(Argon2id)
12
+
13
+ __all__ = ["Argon2id"]
@@ -5,76 +5,15 @@
5
5
  from __future__ import annotations
6
6
 
7
7
  import sys
8
- import typing
9
8
 
10
- from cryptography import utils
11
- from cryptography.exceptions import (
12
- AlreadyFinalized,
13
- InvalidKey,
14
- UnsupportedAlgorithm,
15
- )
16
9
  from cryptography.hazmat.bindings._rust import openssl as rust_openssl
17
- from cryptography.hazmat.primitives import constant_time
18
10
  from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
19
11
 
20
12
  # This is used by the scrypt tests to skip tests that require more memory
21
13
  # than the MEM_LIMIT
22
14
  _MEM_LIMIT = sys.maxsize // 2
23
15
 
16
+ Scrypt = rust_openssl.kdf.Scrypt
17
+ KeyDerivationFunction.register(Scrypt)
24
18
 
25
- class Scrypt(KeyDerivationFunction):
26
- def __init__(
27
- self,
28
- salt: bytes,
29
- length: int,
30
- n: int,
31
- r: int,
32
- p: int,
33
- backend: typing.Any = None,
34
- ):
35
- from cryptography.hazmat.backends.openssl.backend import (
36
- backend as ossl,
37
- )
38
-
39
- if not ossl.scrypt_supported():
40
- raise UnsupportedAlgorithm(
41
- "This version of OpenSSL does not support scrypt"
42
- )
43
- self._length = length
44
- utils._check_bytes("salt", salt)
45
- if n < 2 or (n & (n - 1)) != 0:
46
- raise ValueError("n must be greater than 1 and be a power of 2.")
47
-
48
- if r < 1:
49
- raise ValueError("r must be greater than or equal to 1.")
50
-
51
- if p < 1:
52
- raise ValueError("p must be greater than or equal to 1.")
53
-
54
- self._used = False
55
- self._salt = salt
56
- self._n = n
57
- self._r = r
58
- self._p = p
59
-
60
- def derive(self, key_material: bytes) -> bytes:
61
- if self._used:
62
- raise AlreadyFinalized("Scrypt instances can only be used once.")
63
- self._used = True
64
-
65
- utils._check_byteslike("key_material", key_material)
66
-
67
- return rust_openssl.kdf.derive_scrypt(
68
- key_material,
69
- self._salt,
70
- self._n,
71
- self._r,
72
- self._p,
73
- _MEM_LIMIT,
74
- self._length,
75
- )
76
-
77
- def verify(self, key_material: bytes, expected_key: bytes) -> None:
78
- derived_key = self.derive(key_material)
79
- if not constant_time.bytes_eq(derived_key, expected_key):
80
- raise InvalidKey("Keys do not match.")
19
+ __all__ = ["Scrypt"]
@@ -11,8 +11,8 @@ from cryptography import utils
11
11
  from cryptography.exceptions import AlreadyFinalized
12
12
  from cryptography.hazmat.bindings._rust import (
13
13
  PKCS7PaddingContext,
14
+ PKCS7UnpaddingContext,
14
15
  check_ansix923_padding,
15
- check_pkcs7_padding,
16
16
  )
17
17
 
18
18
 
@@ -115,32 +115,11 @@ class PKCS7:
115
115
  return PKCS7PaddingContext(self.block_size)
116
116
 
117
117
  def unpadder(self) -> PaddingContext:
118
- return _PKCS7UnpaddingContext(self.block_size)
119
-
120
-
121
- class _PKCS7UnpaddingContext(PaddingContext):
122
- _buffer: bytes | None
123
-
124
- def __init__(self, block_size: int):
125
- self.block_size = block_size
126
- # TODO: more copies than necessary, we should use zero-buffer (#193)
127
- self._buffer = b""
128
-
129
- def update(self, data: bytes) -> bytes:
130
- self._buffer, result = _byte_unpadding_update(
131
- self._buffer, data, self.block_size
132
- )
133
- return result
134
-
135
- def finalize(self) -> bytes:
136
- result = _byte_unpadding_check(
137
- self._buffer, self.block_size, check_pkcs7_padding
138
- )
139
- self._buffer = None
140
- return result
118
+ return PKCS7UnpaddingContext(self.block_size)
141
119
 
142
120
 
143
121
  PaddingContext.register(PKCS7PaddingContext)
122
+ PaddingContext.register(PKCS7UnpaddingContext)
144
123
 
145
124
 
146
125
  class ANSIX923:
@@ -263,6 +263,11 @@ class PKCS7EnvelopeBuilder:
263
263
  return rust_pkcs7.encrypt_and_serialize(self, encoding, options)
264
264
 
265
265
 
266
+ pkcs7_decrypt_der = rust_pkcs7.decrypt_der
267
+ pkcs7_decrypt_pem = rust_pkcs7.decrypt_pem
268
+ pkcs7_decrypt_smime = rust_pkcs7.decrypt_smime
269
+
270
+
266
271
  def _smime_signed_encode(
267
272
  data: bytes, signature: bytes, micalg: str, text_mode: bool
268
273
  ) -> bytes:
@@ -328,6 +333,34 @@ def _smime_enveloped_encode(data: bytes) -> bytes:
328
333
  return m.as_bytes(policy=m.policy.clone(linesep="\n", max_line_length=0))
329
334
 
330
335
 
336
+ def _smime_enveloped_decode(data: bytes) -> bytes:
337
+ m = email.message_from_bytes(data)
338
+ if m.get_content_type() not in {
339
+ "application/x-pkcs7-mime",
340
+ "application/pkcs7-mime",
341
+ }:
342
+ raise ValueError("Not an S/MIME enveloped message")
343
+ return bytes(m.get_payload(decode=True))
344
+
345
+
346
+ def _smime_remove_text_headers(data: bytes) -> bytes:
347
+ m = email.message_from_bytes(data)
348
+ # Using get() instead of get_content_type() since it has None as default,
349
+ # where the latter has "text/plain". Both methods are case-insensitive.
350
+ content_type = m.get("content-type")
351
+ if content_type is None:
352
+ raise ValueError(
353
+ "Decrypted MIME data has no 'Content-Type' header. "
354
+ "Please remove the 'Text' option to parse it manually."
355
+ )
356
+ if "text/plain" not in content_type:
357
+ raise ValueError(
358
+ f"Decrypted MIME data content type is '{content_type}', not "
359
+ "'text/plain'. Remove the 'Text' option to parse it manually."
360
+ )
361
+ return bytes(m.get_payload(decode=True))
362
+
363
+
331
364
  class OpenSSLMimePart(email.message.MIMEPart):
332
365
  # A MIMEPart subclass that replicates OpenSSL's behavior of not including
333
366
  # a newline if there are no headers.
@@ -67,6 +67,9 @@ class HOTP:
67
67
  self._algorithm = algorithm
68
68
 
69
69
  def generate(self, counter: int) -> bytes:
70
+ if not isinstance(counter, int):
71
+ raise TypeError("Counter parameter must be an integer type.")
72
+
70
73
  truncated_value = self._dynamic_truncate(counter)
71
74
  hotp = truncated_value % (10**self._length)
72
75
  return "{0:0{1}}".format(hotp, self._length).encode()
@@ -77,7 +80,12 @@ class HOTP:
77
80
 
78
81
  def _dynamic_truncate(self, counter: int) -> int:
79
82
  ctx = hmac.HMAC(self._key, self._algorithm)
80
- ctx.update(counter.to_bytes(length=8, byteorder="big"))
83
+
84
+ try:
85
+ ctx.update(counter.to_bytes(length=8, byteorder="big"))
86
+ except OverflowError:
87
+ raise ValueError(f"Counter must be between 0 and {2 ** 64 - 1}.")
88
+
81
89
  hmac_value = ctx.finalize()
82
90
 
83
91
  offset = hmac_value[len(hmac_value) - 1] & 0b1111
@@ -31,6 +31,11 @@ class TOTP:
31
31
  )
32
32
 
33
33
  def generate(self, time: int | float) -> bytes:
34
+ if not isinstance(time, (int, float)):
35
+ raise TypeError(
36
+ "Time parameter must be an integer type or float type."
37
+ )
38
+
34
39
  counter = int(time / self._time_step)
35
40
  return self._hotp.generate(counter)
36
41
 
@@ -30,6 +30,8 @@ from cryptography.x509.base import (
30
30
  )
31
31
  from cryptography.x509.extensions import (
32
32
  AccessDescription,
33
+ Admission,
34
+ Admissions,
33
35
  AuthorityInformationAccess,
34
36
  AuthorityKeyIdentifier,
35
37
  BasicConstraints,
@@ -55,6 +57,7 @@ from cryptography.x509.extensions import (
55
57
  KeyUsage,
56
58
  MSCertificateTemplate,
57
59
  NameConstraints,
60
+ NamingAuthority,
58
61
  NoticeReference,
59
62
  OCSPAcceptableResponses,
60
63
  OCSPNoCheck,
@@ -63,6 +66,7 @@ from cryptography.x509.extensions import (
63
66
  PolicyInformation,
64
67
  PrecertificateSignedCertificateTimestamps,
65
68
  PrecertPoison,
69
+ ProfessionInfo,
66
70
  ReasonFlags,
67
71
  SignedCertificateTimestamps,
68
72
  SubjectAlternativeName,
@@ -174,6 +178,8 @@ __all__ = [
174
178
  "OID_CA_ISSUERS",
175
179
  "OID_OCSP",
176
180
  "AccessDescription",
181
+ "Admission",
182
+ "Admissions",
177
183
  "Attribute",
178
184
  "AttributeNotFound",
179
185
  "Attributes",
@@ -216,6 +222,7 @@ __all__ = [
216
222
  "NameAttribute",
217
223
  "NameConstraints",
218
224
  "NameOID",
225
+ "NamingAuthority",
219
226
  "NoticeReference",
220
227
  "OCSPAcceptableResponses",
221
228
  "OCSPNoCheck",
@@ -226,6 +233,7 @@ __all__ = [
226
233
  "PolicyInformation",
227
234
  "PrecertPoison",
228
235
  "PrecertificateSignedCertificateTimestamps",
236
+ "ProfessionInfo",
229
237
  "PublicKeyAlgorithmOID",
230
238
  "RFC822Name",
231
239
  "ReasonFlags",