python-pkcs11 0.9.2__tar.gz → 0.9.4__tar.gz

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 (73) hide show
  1. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/actions/test-setup/action.yml +2 -2
  2. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/workflows/coverage.yml +3 -3
  3. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/workflows/quality.yml +10 -4
  4. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/workflows/release.yml +6 -6
  5. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/workflows/tests.yml +2 -2
  6. python_pkcs11-0.9.4/MANIFEST.in +3 -0
  7. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/PKG-INFO +1 -1
  8. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/__init__.py +11 -3
  9. python_pkcs11-0.9.4/pkcs11/_pkcs11.pyi +38 -0
  10. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/_pkcs11.pyx +8 -1
  11. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/attributes.py +70 -46
  12. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/constants.py +7 -4
  13. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/defaults.py +18 -14
  14. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/exceptions.py +2 -0
  15. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/mechanisms.py +18 -6
  16. python_pkcs11-0.9.4/pkcs11/py.typed +0 -0
  17. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/types.py +301 -140
  18. python_pkcs11-0.9.4/pkcs11/util/__init__.py +17 -0
  19. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/util/dh.py +11 -4
  20. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/util/dsa.py +13 -6
  21. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/util/ec.py +16 -6
  22. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/util/rsa.py +24 -14
  23. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/util/x509.py +11 -4
  24. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pyproject.toml +4 -0
  25. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/python_pkcs11.egg-info/PKG-INFO +1 -1
  26. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/python_pkcs11.egg-info/SOURCES.txt +3 -0
  27. python_pkcs11-0.9.4/tests/test_attributes.py +65 -0
  28. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_rsa.py +89 -1
  29. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/uv.lock +33 -2
  30. python_pkcs11-0.9.2/MANIFEST.in +0 -2
  31. python_pkcs11-0.9.2/pkcs11/util/__init__.py +0 -12
  32. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/actions/install-opencryptoki/action.yml +0 -0
  33. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/actions/install-softhsm/action.yml +0 -0
  34. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.github/release-template.md +0 -0
  35. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.gitignore +0 -0
  36. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.python-version +0 -0
  37. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/.readthedocs.yaml +0 -0
  38. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/LICENSE +0 -0
  39. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/README.rst +0 -0
  40. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/Makefile +0 -0
  41. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/api.rst +0 -0
  42. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/applied.rst +0 -0
  43. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/concurrency.rst +0 -0
  44. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/conf.py +0 -0
  45. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/index.rst +0 -0
  46. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/make.bat +0 -0
  47. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/docs/opensc.rst +0 -0
  48. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/.gitignore +0 -0
  49. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/cryptoki.h +0 -0
  50. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/load_module.c +0 -0
  51. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/load_module.h +0 -0
  52. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/pkcs11.h +0 -0
  53. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/pkcs11f.h +0 -0
  54. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/extern/pkcs11t.h +0 -0
  55. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/pkcs11/_pkcs11.pxd +0 -0
  56. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/python_pkcs11.egg-info/dependency_links.txt +0 -0
  57. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/python_pkcs11.egg-info/requires.txt +0 -0
  58. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/python_pkcs11.egg-info/top_level.txt +0 -0
  59. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/setup.cfg +0 -0
  60. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/__init__.py +0 -0
  61. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_aes.py +0 -0
  62. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_des.py +0 -0
  63. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_dh.py +0 -0
  64. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_digest.py +0 -0
  65. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_dsa.py +0 -0
  66. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_ecc.py +0 -0
  67. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_iterators.py +0 -0
  68. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_multilib.py +0 -0
  69. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_public_key_external.py +0 -0
  70. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_sessions.py +0 -0
  71. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_slots_and_tokens.py +0 -0
  72. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_threading.py +0 -0
  73. {python_pkcs11-0.9.2 → python_pkcs11-0.9.4}/tests/test_x509.py +0 -0
@@ -34,7 +34,7 @@ runs:
34
34
  using: "composite"
35
35
  steps:
36
36
  - name: Setup Python
37
- uses: actions/setup-python@v5
37
+ uses: actions/setup-python@v6
38
38
  with:
39
39
  python-version: ${{ inputs.python-version }}
40
40
  - uses: ./.github/actions/install-softhsm
@@ -78,7 +78,7 @@ runs:
78
78
  env:
79
79
  PLATFORM: ${{ inputs.pkcs11-platform }}
80
80
  - name: Install uv
81
- uses: astral-sh/setup-uv@v4
81
+ uses: astral-sh/setup-uv@v7
82
82
  with:
83
83
  enable-cache: true
84
84
  python-version: ${{ inputs.python-version }}
@@ -23,7 +23,7 @@ jobs:
23
23
  - opencryptoki
24
24
  steps:
25
25
  - name: Acquire sources
26
- uses: actions/checkout@v4
26
+ uses: actions/checkout@v6
27
27
  - name: Arm coverage-only compiler directives
28
28
  # Unfortunately, it doesn't seem to be possible to pass directives
29
29
  # to Cython through environment variables: https://github.com/cython/cython/issues/3930
@@ -56,7 +56,7 @@ jobs:
56
56
  runs-on: ubuntu-latest
57
57
  steps:
58
58
  - name: Acquire sources
59
- uses: actions/checkout@v4
59
+ uses: actions/checkout@v6
60
60
  - uses: ./.github/actions/test-setup
61
61
  id: setup
62
62
  with:
@@ -85,7 +85,7 @@ jobs:
85
85
  needs: [pytest-coverage,pytest-coverage-multilib]
86
86
  steps:
87
87
  # checkout necessary to ensure the uploaded report contains the correct paths
88
- - uses: actions/checkout@v4
88
+ - uses: actions/checkout@v6
89
89
  - name: Retrieve coverage reports
90
90
  uses: actions/download-artifact@v4
91
91
  with:
@@ -10,15 +10,15 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
12
  - name: Acquire sources
13
- uses: actions/checkout@v4
13
+ uses: actions/checkout@v6
14
14
 
15
15
  - name: Install uv
16
- uses: astral-sh/setup-uv@v4
16
+ uses: astral-sh/setup-uv@v7
17
17
  with:
18
18
  enable-cache: true
19
19
 
20
20
  - name: Setup Python
21
- uses: actions/setup-python@v5
21
+ uses: actions/setup-python@v6
22
22
  with:
23
23
  python-version: "3.13"
24
24
  architecture: x64
@@ -30,4 +30,10 @@ jobs:
30
30
  run: uv run ruff format --diff .
31
31
 
32
32
  - name: ruff check
33
- run: uv run ruff check --diff .
33
+ run: uv run ruff check --diff .
34
+
35
+ - name: Install project dependencies for type checking
36
+ run: uv pip install asn1crypto
37
+
38
+ - name: ty type check
39
+ run: uv run ty check pkcs11/
@@ -51,7 +51,7 @@ jobs:
51
51
  echo "Tag $VERSION does not follow v<version> naming scheme"
52
52
  exit 1
53
53
  fi
54
- - uses: actions/checkout@v4
54
+ - uses: actions/checkout@v6
55
55
  - name: Generate release body
56
56
  run: |
57
57
  sed "s/:VERSION/$VERSION/g" < .github/release-template.md > release.md
@@ -75,9 +75,9 @@ jobs:
75
75
  - windows-latest
76
76
  - macos-14
77
77
  steps:
78
- - uses: actions/checkout@v4
78
+ - uses: actions/checkout@v6
79
79
  - name: Setup Python
80
- uses: actions/setup-python@v5
80
+ uses: actions/setup-python@v6
81
81
  - name: Build wheels
82
82
  uses: pypa/cibuildwheel@v3.3.0
83
83
  - uses: actions/upload-artifact@v4
@@ -88,11 +88,11 @@ jobs:
88
88
  runs-on: ubuntu-latest
89
89
  needs: [extract-params]
90
90
  steps:
91
- - uses: actions/checkout@v4
91
+ - uses: actions/checkout@v6
92
92
  - name: Setup Python
93
- uses: actions/setup-python@v5
93
+ uses: actions/setup-python@v6
94
94
  - name: Install uv
95
- uses: astral-sh/setup-uv@v4
95
+ uses: astral-sh/setup-uv@v7
96
96
  with:
97
97
  enable-cache: true
98
98
  - name: Build source distribution
@@ -40,7 +40,7 @@ jobs:
40
40
  os: macos-14
41
41
  steps:
42
42
  - name: Acquire sources
43
- uses: actions/checkout@v4
43
+ uses: actions/checkout@v6
44
44
  - uses: ./.github/actions/test-setup
45
45
  id: setup
46
46
  with:
@@ -69,7 +69,7 @@ jobs:
69
69
  - "3.14"
70
70
  steps:
71
71
  - name: Acquire sources
72
- uses: actions/checkout@v4
72
+ uses: actions/checkout@v6
73
73
  - uses: ./.github/actions/test-setup
74
74
  id: setup
75
75
  with:
@@ -0,0 +1,3 @@
1
+ graft extern/
2
+ include pkcs11/*.pxd
3
+ include pkcs11/py.typed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-pkcs11
3
- Version: 0.9.2
3
+ Version: 0.9.4
4
4
  Summary: PKCS#11 support for Python
5
5
  Author-email: Andrey Kislyuk <kislyuk@gmail.com>, Danielle Madeley <danielle@madeley.id.au>
6
6
  Maintainer-email: Andrey Kislyuk <kislyuk@gmail.com>
@@ -2,16 +2,24 @@
2
2
  :mod:`pkcs11` defines a high-level, "Pythonic" interface to PKCS#11.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Any
8
+
5
9
  from pkcs11.constants import * # noqa: F403
6
10
  from pkcs11.exceptions import * # noqa: F403
7
11
  from pkcs11.mechanisms import * # noqa: F403
8
12
  from pkcs11.types import * # noqa: F403
9
13
  from pkcs11.util import dh, dsa, ec, rsa, x509 # noqa: F401
10
14
 
11
- _loaded = {}
15
+ if TYPE_CHECKING:
16
+ from pkcs11._pkcs11 import lib as _lib_type
17
+
18
+
19
+ _loaded: dict[str, Any] = {}
12
20
 
13
21
 
14
- def lib(so):
22
+ def lib(so: str) -> _lib_type:
15
23
  """
16
24
  Wrap the main library call coming from Cython with a preemptive
17
25
  dynamic loading.
@@ -34,7 +42,7 @@ def lib(so):
34
42
  return _lib
35
43
 
36
44
 
37
- def unload(so):
45
+ def unload(so: str) -> None:
38
46
  global _loaded
39
47
  try:
40
48
  loaded_lib = _loaded[so]
@@ -0,0 +1,38 @@
1
+ """Type stubs for the _pkcs11 Cython extension module."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Iterator
6
+
7
+ from pkcs11.types import Slot, Token
8
+
9
+ class lib:
10
+ """Main entry point for PKCS#11 library."""
11
+
12
+ so: str
13
+ manufacturer_id: str
14
+ library_description: str
15
+ initialized: bool
16
+
17
+ def __init__(self, so: str) -> None: ...
18
+ @property
19
+ def library_version(self) -> tuple[int, int]: ...
20
+ @property
21
+ def cryptoki_version(self) -> tuple[int, int]: ...
22
+ def initialize(self) -> None: ...
23
+ def finalize(self) -> None: ...
24
+ def reinitialize(self) -> None: ...
25
+ def unload(self) -> None: ...
26
+ def get_slots(self, token_present: bool = False) -> list[Slot]: ...
27
+ def get_tokens(
28
+ self,
29
+ token_label: str | None = None,
30
+ token_serial: bytes | None = None,
31
+ token_flags: Any | None = None,
32
+ slot_flags: Any | None = None,
33
+ mechanisms: Any | None = None,
34
+ ) -> Iterator[Token]: ...
35
+ def get_token(self, **kwargs: Any) -> Token: ...
36
+ def wait_for_slot_event(self, blocking: bool = True) -> Slot: ...
37
+ def __str__(self) -> str: ...
38
+ def __repr__(self) -> str: ...
@@ -1366,8 +1366,15 @@ cdef object make_object(Session session, CK_OBJECT_HANDLE handle) with gil:
1366
1366
  # Determine a list of base classes to manufacture our class with
1367
1367
  try:
1368
1368
  attributes = wrapper.get_attribute_list(&attr_keys[0], 8)
1369
- except (AttributeTypeInvalid, FunctionFailed) as e:
1369
+ except PKCS11Error:
1370
+ # retry fetching the flags one by one, some tokens do not implement error handling
1371
+ # on bulk fetches correctly.
1370
1372
  attributes = {}
1373
+ for key in attr_keys:
1374
+ try:
1375
+ attributes[key] = wrapper[key]
1376
+ except (AttributeTypeInvalid, AttributeSensitive, FunctionFailed):
1377
+ continue
1371
1378
 
1372
1379
  object_class = attributes.get(Attribute.CLASS, session.attribute_mapper)
1373
1380
  bases = (_CLASS_MAP[object_class],)
@@ -1,36 +1,46 @@
1
+ from __future__ import annotations
2
+
1
3
  from datetime import datetime
4
+ from enum import IntEnum
2
5
  from struct import Struct
6
+ from typing import Any, Callable, Final
3
7
 
4
- from pkcs11.constants import (
5
- Attribute,
6
- CertificateType,
7
- MechanismFlag,
8
- ObjectClass,
9
- )
8
+ from pkcs11.constants import Attribute, CertificateType, MechanismFlag, ObjectClass
10
9
  from pkcs11.mechanisms import KeyType, Mechanism
11
10
 
11
+ # Type aliases for pack/unpack function pairs
12
+ PackFunc = Callable[[Any], bytes]
13
+ UnpackFunc = Callable[[bytes], Any]
14
+ Handler = tuple[PackFunc, UnpackFunc]
15
+
12
16
  # (Pack Function, Unpack Function) functions
13
- handle_bool = (Struct("?").pack, lambda v: False if len(v) == 0 else Struct("?").unpack(v)[0])
14
- handle_ulong = (Struct("L").pack, lambda v: Struct("L").unpack(v)[0])
15
- handle_str = (lambda s: s.encode("utf-8"), lambda b: b.decode("utf-8"))
16
- handle_date = (
17
+ _bool_struct = Struct("?")
18
+ _ulong_struct = Struct("L")
19
+
20
+ handle_bool: Handler = (
21
+ _bool_struct.pack,
22
+ lambda v: False if len(v) == 0 else _bool_struct.unpack(v)[0],
23
+ )
24
+ handle_ulong: Handler = (_ulong_struct.pack, lambda v: _ulong_struct.unpack(v)[0])
25
+ handle_str: Handler = (lambda s: s.encode("utf-8"), lambda b: b.decode("utf-8"))
26
+ handle_date: Handler = (
17
27
  lambda s: s.strftime("%Y%m%d").encode("ascii"),
18
28
  lambda s: datetime.strptime(s.decode("ascii"), "%Y%m%d").date(),
19
29
  )
20
- handle_bytes = (bytes, bytes)
30
+ handle_bytes: Handler = (bytes, bytes)
21
31
  # The PKCS#11 biginteger type is an array of bytes in network byte order.
22
32
  # If you have an int type, wrap it in biginteger()
23
- handle_biginteger = handle_bytes
33
+ handle_biginteger: Handler = handle_bytes
24
34
 
25
35
 
26
- def _enum(type_):
36
+ def _enum(type_: type[IntEnum]) -> Handler:
27
37
  """Factory to pack/unpack ints into IntEnums."""
28
38
  pack, unpack = handle_ulong
29
39
 
30
40
  return (lambda v: pack(int(v)), lambda v: type_(unpack(v)))
31
41
 
32
42
 
33
- ATTRIBUTE_TYPES = {
43
+ ATTRIBUTE_TYPES: dict[Attribute, Handler] = {
34
44
  Attribute.ALWAYS_AUTHENTICATE: handle_bool,
35
45
  Attribute.ALWAYS_SENSITIVE: handle_bool,
36
46
  Attribute.APPLICATION: handle_str,
@@ -96,7 +106,7 @@ ATTRIBUTE_TYPES = {
96
106
  Map of attributes to (serialize, deserialize) functions.
97
107
  """
98
108
 
99
- ALL_CAPABILITIES = (
109
+ ALL_CAPABILITIES: Final[tuple[Attribute, ...]] = (
100
110
  Attribute.ENCRYPT,
101
111
  Attribute.DECRYPT,
102
112
  Attribute.WRAP,
@@ -107,7 +117,12 @@ ALL_CAPABILITIES = (
107
117
  )
108
118
 
109
119
 
110
- def _apply_common(template, id_, label, store):
120
+ def _apply_common(
121
+ template: dict[Attribute, Any],
122
+ id_: bytes | None,
123
+ label: str | None,
124
+ store: bool,
125
+ ) -> None:
111
126
  if id_:
112
127
  template[Attribute.ID] = id_
113
128
  if label:
@@ -115,12 +130,16 @@ def _apply_common(template, id_, label, store):
115
130
  template[Attribute.TOKEN] = bool(store)
116
131
 
117
132
 
118
- def _apply_capabilities(template, possible_capas, capabilities):
133
+ def _apply_capabilities(
134
+ template: dict[Attribute, Any],
135
+ possible_capas: tuple[Attribute, ...],
136
+ capabilities: MechanismFlag | int,
137
+ ) -> None:
119
138
  for attr in possible_capas:
120
139
  template[attr] = _capa_attr_to_mechanism_flag[attr] & capabilities
121
140
 
122
141
 
123
- _capa_attr_to_mechanism_flag = {
142
+ _capa_attr_to_mechanism_flag: Final[dict[Attribute, MechanismFlag]] = {
124
143
  Attribute.ENCRYPT: MechanismFlag.ENCRYPT,
125
144
  Attribute.DECRYPT: MechanismFlag.DECRYPT,
126
145
  Attribute.WRAP: MechanismFlag.WRAP,
@@ -136,7 +155,12 @@ class AttributeMapper:
136
155
  Class mapping PKCS#11 attributes to and from Python values.
137
156
  """
138
157
 
139
- def __init__(self):
158
+ attribute_types: dict[Attribute, Handler]
159
+ default_secret_key_template: dict[Attribute, Any]
160
+ default_public_key_template: dict[Attribute, Any]
161
+ default_private_key_template: dict[Attribute, Any]
162
+
163
+ def __init__(self) -> None:
140
164
  self.attribute_types = dict(ATTRIBUTE_TYPES)
141
165
  self.default_secret_key_template = {
142
166
  Attribute.CLASS: ObjectClass.SECRET_KEY,
@@ -158,21 +182,21 @@ class AttributeMapper:
158
182
  Attribute.SENSITIVE: True,
159
183
  }
160
184
 
161
- def register_handler(self, key, pack, unpack):
185
+ def register_handler(self, key: Attribute, pack: PackFunc, unpack: UnpackFunc) -> None:
162
186
  self.attribute_types[key] = (pack, unpack)
163
187
 
164
- def _handler(self, key):
188
+ def _handler(self, key: Attribute) -> Handler:
165
189
  try:
166
190
  return self.attribute_types[key]
167
191
  except KeyError as e:
168
192
  raise NotImplementedError(f"Can't handle attribute type {hex(key)}.") from e
169
193
 
170
- def pack_attribute(self, key, value):
194
+ def pack_attribute(self, key: Attribute, value: Any) -> bytes:
171
195
  """Pack a Attribute value into a bytes array."""
172
196
  pack, _ = self._handler(key)
173
197
  return pack(value)
174
198
 
175
- def unpack_attributes(self, key, value):
199
+ def unpack_attributes(self, key: Attribute, value: bytes) -> Any:
176
200
  """Unpack a Attribute bytes array into a Python value."""
177
201
  _, unpack = self._handler(key)
178
202
  return unpack(value)
@@ -180,12 +204,12 @@ class AttributeMapper:
180
204
  def public_key_template(
181
205
  self,
182
206
  *,
183
- capabilities,
184
- id_,
185
- label,
186
- store,
187
- ):
188
- template = self.default_public_key_template
207
+ capabilities: MechanismFlag | int,
208
+ id_: bytes | None,
209
+ label: str | None,
210
+ store: bool,
211
+ ) -> dict[Attribute, Any]:
212
+ template = dict(self.default_public_key_template)
189
213
  _apply_capabilities(
190
214
  template, (Attribute.ENCRYPT, Attribute.WRAP, Attribute.VERIFY), capabilities
191
215
  )
@@ -195,12 +219,12 @@ class AttributeMapper:
195
219
  def private_key_template(
196
220
  self,
197
221
  *,
198
- capabilities,
199
- id_,
200
- label,
201
- store,
202
- ):
203
- template = self.default_private_key_template
222
+ capabilities: MechanismFlag | int,
223
+ id_: bytes | None,
224
+ label: str | None,
225
+ store: bool,
226
+ ) -> dict[Attribute, Any]:
227
+ template = dict(self.default_private_key_template)
204
228
  _apply_capabilities(
205
229
  template,
206
230
  (Attribute.DECRYPT, Attribute.UNWRAP, Attribute.SIGN, Attribute.DERIVE),
@@ -212,11 +236,11 @@ class AttributeMapper:
212
236
  def secret_key_template(
213
237
  self,
214
238
  *,
215
- capabilities,
216
- id_,
217
- label,
218
- store,
219
- ):
239
+ capabilities: MechanismFlag | int,
240
+ id_: bytes | None,
241
+ label: str | None,
242
+ store: bool,
243
+ ) -> dict[Attribute, Any]:
220
244
  return self.generic_key_template(
221
245
  self.default_secret_key_template,
222
246
  capabilities=capabilities,
@@ -227,13 +251,13 @@ class AttributeMapper:
227
251
 
228
252
  def generic_key_template(
229
253
  self,
230
- base_template,
254
+ base_template: dict[Attribute, Any],
231
255
  *,
232
- capabilities,
233
- id_,
234
- label,
235
- store,
236
- ):
256
+ capabilities: MechanismFlag | int,
257
+ id_: bytes | None,
258
+ label: str | None,
259
+ store: bool,
260
+ ) -> dict[Attribute, Any]:
237
261
  template = dict(base_template)
238
262
  _apply_capabilities(template, ALL_CAPABILITIES, capabilities)
239
263
  _apply_common(template, id_, label, store)
@@ -5,9 +5,12 @@ See the Python :mod:`enum` documentation for more information on how to
5
5
  use these classes.
6
6
  """
7
7
 
8
+ from __future__ import annotations
9
+
8
10
  from enum import IntEnum, IntFlag, unique
11
+ from typing import Final
9
12
 
10
- DEFAULT = object()
13
+ DEFAULT: Final[object] = object()
11
14
  """Sentinel value used in templates.
12
15
 
13
16
  Not all pkcs11 attribute sets are accepted by HSMs.
@@ -55,11 +58,11 @@ class ObjectClass(IntEnum):
55
58
 
56
59
  _VENDOR_DEFINED = 0x80000000
57
60
 
58
- def __repr__(self):
61
+ def __repr__(self) -> str:
59
62
  return "<ObjectClass.%s>" % self.name
60
63
 
61
64
 
62
- _ARRAY_ATTRIBUTE = 0x40000000
65
+ _ARRAY_ATTRIBUTE: Final[int] = 0x40000000
63
66
  """Attribute consists of an array of values."""
64
67
 
65
68
 
@@ -343,7 +346,7 @@ class Attribute(IntEnum):
343
346
 
344
347
  _VENDOR_DEFINED = 0x80000000
345
348
 
346
- def __repr__(self):
349
+ def __repr__(self) -> str:
347
350
  return "<Attribute.%s>" % self.name
348
351
 
349
352
 
@@ -5,12 +5,14 @@ None of this is provided for in PKCS#11 and its correctness should not be
5
5
  assumed.
6
6
  """
7
7
 
8
- from pkcs11.constants import (
9
- MechanismFlag,
10
- )
8
+ from __future__ import annotations
9
+
10
+ from typing import Final
11
+
12
+ from pkcs11.constants import MechanismFlag
11
13
  from pkcs11.mechanisms import MGF, KeyType, Mechanism
12
14
 
13
- DEFAULT_GENERATE_MECHANISMS = {
15
+ DEFAULT_GENERATE_MECHANISMS: Final[dict[KeyType, Mechanism]] = {
14
16
  KeyType.AES: Mechanism.AES_KEY_GEN,
15
17
  KeyType.DES2: Mechanism.DES2_KEY_GEN,
16
18
  KeyType.DES3: Mechanism.DES3_KEY_GEN,
@@ -26,11 +28,11 @@ DEFAULT_GENERATE_MECHANISMS = {
26
28
  Default mechanisms for generating keys.
27
29
  """
28
30
 
29
- _ENCRYPTION = MechanismFlag.ENCRYPT | MechanismFlag.DECRYPT
30
- _SIGNING = MechanismFlag.SIGN | MechanismFlag.VERIFY
31
- _WRAPPING = MechanismFlag.WRAP | MechanismFlag.UNWRAP
31
+ _ENCRYPTION: Final[MechanismFlag] = MechanismFlag.ENCRYPT | MechanismFlag.DECRYPT
32
+ _SIGNING: Final[MechanismFlag] = MechanismFlag.SIGN | MechanismFlag.VERIFY
33
+ _WRAPPING: Final[MechanismFlag] = MechanismFlag.WRAP | MechanismFlag.UNWRAP
32
34
 
33
- DEFAULT_KEY_CAPABILITIES = {
35
+ DEFAULT_KEY_CAPABILITIES: Final[dict[KeyType, MechanismFlag | int]] = {
34
36
  KeyType.AES: _ENCRYPTION | _SIGNING | _WRAPPING,
35
37
  KeyType.DES2: _ENCRYPTION | _SIGNING | _WRAPPING,
36
38
  KeyType.DES3: _ENCRYPTION | _SIGNING | _WRAPPING,
@@ -45,7 +47,7 @@ DEFAULT_KEY_CAPABILITIES = {
45
47
  Default capabilities for generating keys.
46
48
  """
47
49
 
48
- DEFAULT_ENCRYPT_MECHANISMS = {
50
+ DEFAULT_ENCRYPT_MECHANISMS: Final[dict[KeyType, Mechanism]] = {
49
51
  KeyType.AES: Mechanism.AES_CBC_PAD,
50
52
  KeyType.DES2: Mechanism.DES3_CBC_PAD,
51
53
  KeyType.DES3: Mechanism.DES3_CBC_PAD,
@@ -55,7 +57,7 @@ DEFAULT_ENCRYPT_MECHANISMS = {
55
57
  Default mechanisms for encrypt/decrypt.
56
58
  """
57
59
 
58
- DEFAULT_SIGN_MECHANISMS = {
60
+ DEFAULT_SIGN_MECHANISMS: Final[dict[KeyType, Mechanism]] = {
59
61
  KeyType.AES: Mechanism.AES_MAC,
60
62
  KeyType.DES2: Mechanism.DES3_MAC,
61
63
  KeyType.DES3: Mechanism.DES3_MAC,
@@ -68,7 +70,7 @@ DEFAULT_SIGN_MECHANISMS = {
68
70
  Default mechanisms for sign/verify.
69
71
  """
70
72
 
71
- DEFAULT_WRAP_MECHANISMS = {
73
+ DEFAULT_WRAP_MECHANISMS: Final[dict[KeyType, Mechanism]] = {
72
74
  KeyType.AES: Mechanism.AES_KEY_WRAP,
73
75
  KeyType.DES2: Mechanism.DES3_ECB,
74
76
  KeyType.DES3: Mechanism.DES3_ECB,
@@ -78,7 +80,7 @@ DEFAULT_WRAP_MECHANISMS = {
78
80
  Default mechanism for wrap/unwrap.
79
81
  """
80
82
 
81
- DEFAULT_DERIVE_MECHANISMS = {
83
+ DEFAULT_DERIVE_MECHANISMS: Final[dict[KeyType, Mechanism]] = {
82
84
  KeyType.DH: Mechanism.DH_PKCS_DERIVE,
83
85
  KeyType.EC: Mechanism.ECDH1_DERIVE,
84
86
  KeyType.X9_42_DH: Mechanism.X9_42_DH_DERIVE,
@@ -87,7 +89,7 @@ DEFAULT_DERIVE_MECHANISMS = {
87
89
  Default mechanisms for key derivation
88
90
  """
89
91
 
90
- DEFAULT_PARAM_GENERATE_MECHANISMS = {
92
+ DEFAULT_PARAM_GENERATE_MECHANISMS: Final[dict[KeyType, Mechanism]] = {
91
93
  KeyType.DH: Mechanism.DH_PKCS_PARAMETER_GEN,
92
94
  KeyType.DSA: Mechanism.DSA_PARAMETER_GEN,
93
95
  KeyType.X9_42_DH: Mechanism.X9_42_DH_PARAMETER_GEN,
@@ -97,7 +99,9 @@ Default mechanisms for domain parameter generation
97
99
  """
98
100
 
99
101
 
100
- DEFAULT_MECHANISM_PARAMS = {
102
+ DEFAULT_MECHANISM_PARAMS: Final[
103
+ dict[Mechanism, tuple[Mechanism, MGF, None] | tuple[Mechanism, MGF, int]]
104
+ ] = {
101
105
  Mechanism.RSA_PKCS_OAEP: (Mechanism.SHA_1, MGF.SHA1, None),
102
106
  Mechanism.RSA_PKCS_PSS: (Mechanism.SHA_1, MGF.SHA1, 20),
103
107
  }
@@ -3,6 +3,8 @@ PKCS#11 return codes are exposed as Python exceptions inheriting from
3
3
  :class:`PKCS11Error`.
4
4
  """
5
5
 
6
+ from __future__ import annotations
7
+
6
8
 
7
9
  class PKCS11Error(RuntimeError):
8
10
  """
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from enum import IntEnum
2
4
 
3
5
  from pkcs11.exceptions import ArgumentsBad
@@ -107,7 +109,7 @@ class KeyType(IntEnum):
107
109
 
108
110
  _VENDOR_DEFINED = 0x80000000
109
111
 
110
- def __repr__(self):
112
+ def __repr__(self) -> str:
111
113
  return "<KeyType.%s>" % self.name
112
114
 
113
115
 
@@ -751,7 +753,7 @@ class Mechanism(IntEnum):
751
753
 
752
754
  _VENDOR_DEFINED = 0x80000000
753
755
 
754
- def __repr__(self):
756
+ def __repr__(self) -> str:
755
757
  return "<Mechanism.%s>" % self.name
756
758
 
757
759
 
@@ -775,7 +777,7 @@ class KDF(IntEnum):
775
777
  SHA3_384_KDF = 0x0000000C
776
778
  SHA3_512_KDF = 0x0000000D
777
779
 
778
- def __repr__(self):
780
+ def __repr__(self) -> str:
779
781
  return "<KDF.%s>" % self.name
780
782
 
781
783
 
@@ -794,12 +796,18 @@ class MGF(IntEnum):
794
796
  SHA3_384 = 0x00000008
795
797
  SHA3_512 = 0x00000009
796
798
 
797
- def __repr__(self):
799
+ def __repr__(self) -> str:
798
800
  return "<MGF.%s>" % self.name
799
801
 
800
802
 
801
803
  class GCMParams:
802
- def __init__(self, nonce, aad=None, tag_bits=128):
804
+ """Parameters for AES-GCM mode."""
805
+
806
+ nonce: bytes
807
+ aad: bytes | None
808
+ tag_bits: int
809
+
810
+ def __init__(self, nonce: bytes, aad: bytes | None = None, tag_bits: int = 128) -> None:
803
811
  if len(nonce) > 12:
804
812
  raise ArgumentsBad("IV must be less than 12 bytes")
805
813
  self.nonce = nonce
@@ -808,7 +816,11 @@ class GCMParams:
808
816
 
809
817
 
810
818
  class CTRParams:
811
- def __init__(self, nonce):
819
+ """Parameters for AES-CTR mode."""
820
+
821
+ nonce: bytes
822
+
823
+ def __init__(self, nonce: bytes) -> None:
812
824
  if len(nonce) >= 16:
813
825
  raise ArgumentsBad(
814
826
  f"{nonce.hex()} is too long to serve as a CTR nonce, must be 15 bytes or less "
File without changes