1Python PKCS#11 - High Level Wrapper API
2=======================================
3
4A high level, "more Pythonic" interface to the PKCS#11 (Cryptoki) standard
5to support HSM and Smartcard devices in Python.
6
7The interface is designed to follow the logical structure of a HSM, with
8useful defaults for obscurely documented parameters. Many APIs will optionally
9accept iterables and act as generators, allowing you to stream large data
10blocks for symmetric encryption.
11
12python-pkcs11 also includes numerous utility functions to convert between PKCS
13#11 data structures and common interchange formats including PKCS #1 and X.509.
14
15python-pkcs11 is fully documented and has a full integration test suite for all
16features, with continuous integration against multiple HSM platforms including:
17
18* Thales nCipher
19* Opencryptoki TPM
20* OpenSC/Smartcard-HSM/Nitrokey HSM
21
22Source: https://github.com/danni/python-pkcs11
23
24Documentation: http://python-pkcs11.readthedocs.io/en/latest/
25
26Getting Started
27---------------
28
29Install from Pip:
30
31::
32
33 pip install python-pkcs11
34
35
36Or build from source:
37
38::
39
40 python setup.py build
41
42Assuming your PKCS#11 library is set as `PKCS11_MODULE` and contains a
43token named `DEMO`:
44
45AES
46~~~
47
48::
49
50 import pkcs11
51
52 # Initialise our PKCS#11 library
53 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
54 token = lib.get_token(token_label='DEMO')
55
56 data = b'INPUT DATA'
57
58 # Open a session on our token
59 with token.open(user_pin='1234') as session:
60 # Generate an AES key in this session
61 key = session.generate_key(pkcs11.KeyType.AES, 256)
62
63 # Get an initialisation vector
64 iv = session.generate_random(128) # AES blocks are fixed at 128 bits
65 # Encrypt our data
66 crypttext = key.encrypt(data, mechanism_param=iv)
67
683DES
69~~~~
70
71::
72
73 import pkcs11
74
75 # Initialise our PKCS#11 library
76 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
77 token = lib.get_token(token_label='DEMO')
78
79 data = b'INPUT DATA'
80
81 # Open a session on our token
82 with token.open(user_pin='1234') as session:
83 # Generate a DES key in this session
84 key = session.generate_key(pkcs11.KeyType.DES3)
85
86 # Get an initialisation vector
87 iv = session.generate_random(64) # DES blocks are fixed at 64 bits
88 # Encrypt our data
89 crypttext = key.encrypt(data, mechanism_param=iv)
90
91RSA
92~~~
93
94::
95
96 import pkcs11
97
98 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
99 token = lib.get_token(token_label='DEMO')
100
101 data = b'INPUT DATA'
102
103 # Open a session on our token
104 with token.open(user_pin='1234') as session:
105 # Generate an RSA keypair in this session
106 pub, priv = session.generate_keypair(pkcs11.KeyType.RSA, 2048)
107
108 # Encrypt as one block
109 crypttext = pub.encrypt(data)
110
111DSA
112~~~
113
114::
115
116 import pkcs11
117
118 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
119 token = lib.get_token(token_label='DEMO')
120
121 data = b'INPUT DATA'
122
123 # Open a session on our token
124 with token.open(user_pin='1234') as session:
125 # Generate an DSA keypair in this session
126 pub, priv = session.generate_keypair(pkcs11.KeyType.DSA, 1024)
127
128 # Sign
129 signature = priv.sign(data)
130
131ECDSA
132~~~~~
133
134::
135
136 import pkcs11
137
138 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
139 token = lib.get_token(token_label='DEMO')
140
141 data = b'INPUT DATA'
142
143 # Open a session on our token
144 with token.open(user_pin='1234') as session:
145 # Generate an EC keypair in this session from a named curve
146 ecparams = session.create_domain_parameters(
147 pkcs11.KeyType.EC, {
148 pkcs11.Attribute.EC_PARAMS: pkcs11.util.ec.encode_named_curve_parameters('prime256v1'),
149 }, local=True)
150 pub, priv = ecparams.generate_keypair()
151
152 # Sign
153 signature = priv.sign(data)
154
155Diffie-Hellman
156~~~~~~~~~~~~~~
157
158::
159
160 import pkcs11
161
162 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
163 token = lib.get_token(token_label='DEMO')
164
165 with token.open() as session:
166 # Given shared Diffie-Hellman parameters
167 parameters = session.create_domain_parameters(pkcs11.KeyType.DH, {
168 pkcs11.Attribute.PRIME: prime, # Diffie-Hellman parameters
169 pkcs11.Attribute.BASE: base,
170 })
171
172 # Generate a DH key pair from the public parameters
173 public, private = parameters.generate_keypair()
174
175 # Share the public half of it with our other party.
176 _network_.write(public[Attribute.VALUE])
177 # And get their shared value
178 other_value = _network_.read()
179
180 # Derive a shared session key with perfect forward secrecy
181 session_key = private.derive_key(
182 pkcs11.KeyType.AES, 128,
183 mechanism_param=other_value)
184
185
186Elliptic-Curve Diffie-Hellman
187~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188
189::
190
191 import pkcs11
192
193 lib = pkcs11.lib(os.environ['PKCS11_MODULE'])
194 token = lib.get_token(token_label='DEMO')
195
196 with token.open() as session:
197 # Given DER encocded EC parameters, e.g. from
198 # openssl ecparam -outform der -name <named curve>
199 parameters = session.create_domain_parameters(pkcs11.KeyType.EC, {
200 pkcs11.Attribute.EC_PARAMS: ecparams,
201 })
202
203 # Generate a DH key pair from the public parameters
204 public, private = parameters.generate_keypair()
205
206 # Share the public half of it with our other party.
207 _network_.write(public[pkcs11.Attribute.EC_POINT])
208 # And get their shared value
209 other_value = _network_.read()
210
211 # Derive a shared session key
212 session_key = private.derive_key(
213 pkcs11.KeyType.AES, 128,
214 mechanism_param=(pkcs11.KDF.NULL, None, other_value))
215
216Tested Compatibility
217--------------------
218
219+------------------------------+--------------+-----------------+--------------+-------------------+
220| Functionality | SoftHSMv2 | Thales nCipher | Opencryptoki | OpenSC (Nitrokey) |
221+==============================+==============+=================+==============+===================+
222| Get Slots/Tokens | Works | Works | Works | Works |
223+------------------------------+--------------+-----------------+--------------+-------------------+
224| Get Mechanisms | Works | Works | Works | Works |
225+------------------------------+--------------+-----------------+--------------+-------------------+
226| Initialize token | Not implemented |
227+------------------------------+-------------------------------------------------------------------+
228| Slot events | Not implemented |
229+------------------------------+-------------------------------------------------------------------+
230| Alternative authentication | Not implemented |
231| path | |
232+------------------------------+-------------------------------------------------------------------+
233| `Always authenticate` keys | Not implemented |
234+-------------+----------------+--------------+-----------------+--------------+-------------------+
235| Create/Copy | Keys | Works | Works | Errors | Create |
236| +----------------+--------------+-----------------+--------------+-------------------+
237| | Certificates | Caveats [1]_ | Caveats [1]_ | Caveats [1]_ | ? |
238| +----------------+--------------+-----------------+--------------+-------------------+
239| | Domain Params | Caveats [1]_ | Caveats [1]_ | ? | N/A |
240+-------------+----------------+--------------+-----------------+--------------+-------------------+
241| Destroy Object | Works | N/A | Works | Works |
242+------------------------------+--------------+-----------------+--------------+-------------------+
243| Generate Random | Works | Works | Works | Works |
244+------------------------------+--------------+-----------------+--------------+-------------------+
245| Seed Random | Works | N/A | N/A | N/A |
246+------------------------------+--------------+-----------------+--------------+-------------------+
247| Digest (Data & Keys) | Works | Caveats [2]_ | Works | Works |
248+--------+---------------------+--------------+-----------------+--------------+-------------------+
249| AES | Generate key | Works | Works | Works | N/A |
250| +---------------------+--------------+-----------------+--------------+ |
251| | Encrypt/Decrypt | Works | Works | Works | |
252| +---------------------+--------------+-----------------+--------------+ |
253| | Wrap/Unwrap | ? [3]_ | Works | Errors | |
254| +---------------------+--------------+-----------------+--------------+ |
255| | Sign/Verify | Works | Works [4]_ | N/A | |
256+--------+---------------------+--------------+-----------------+--------------+-------------------+
257| DES2/ | Generate key | Works | Works | Works | N/A |
258| DES3 +---------------------+--------------+-----------------+--------------+ |
259| | Encrypt/Decrypt | Works | Works | Works | |
260| +---------------------+--------------+-----------------+--------------+ |
261| | Wrap/Unwrap | ? | ? | ? | |
262| +---------------------+--------------+-----------------+--------------+ |
263| | Sign/Verify | ? | ? | ? | |
264+--------+---------------------+--------------+-----------------+--------------+-------------------+
265| RSA | Generate key pair | Works | Works | Works | Works [4]_ [8]_ |
266| +---------------------+--------------+-----------------+--------------+-------------------+
267| | Encrypt/Decrypt | Works | Works | Works | Decrypt only [9]_ |
268| +---------------------+--------------+-----------------+--------------+-------------------+
269| | Wrap/Unwrap | Works | Works | Works | N/A |
270| +---------------------+--------------+-----------------+--------------+-------------------+
271| | Sign/Verify | Works | Works | Works | Works |
272+--------+---------------------+--------------+-----------------+--------------+-------------------+
273| DSA | Generate parameters | Works | Error | N/A | N/A |
274| +---------------------+--------------+-----------------+ | |
275| | Generate key pair | Works | Caveats [5]_ | | |
276| +---------------------+--------------+-----------------+ | |
277| | Sign/Verify | Works | Works [4]_ | | |
278+--------+---------------------+--------------+-----------------+--------------+-------------------+
279| DH | Generate parameters | Works | N/A | N/A | N/A |
280| +---------------------+--------------+-----------------+ | |
281| | Generate key pair | Works | Caveats [6]_ | | |
282| +---------------------+--------------+-----------------+ | |
283| | Derive Key | Works | Caveats [7]_ | | |
284+--------+---------------------+--------------+-----------------+--------------+-------------------+
285| EC | Generate key pair | Caveats [6]_ | ? [3]_ | N/A | Works |
286| +---------------------+--------------+-----------------+ +-------------------+
287| | Sign/Verify (ECDSA) | Works [4]_ | ? [3]_ | | Sign only [9]_ |
288| +---------------------+--------------+-----------------+ +-------------------+
289| | Derive key (ECDH) | Works | ? [3]_ | | ? |
290+--------+---------------------+--------------+-----------------+--------------+-------------------+
291| Proprietary extensions | N/A | Not implemented | N/A | N/A |
292+------------------------------+--------------+-----------------+--------------+-------------------+
293
294.. [1] Device supports limited set of attributes.
295.. [2] Digesting keys is not supported.
296.. [3] Untested: requires support in device.
297.. [4] Default mechanism not supported, must specify a mechanism.
298.. [5] From existing domain parameters.
299.. [6] Local domain parameters only.
300.. [7] Generates security warnings about the derived key.
301.. [8] `store` parameter is ignored, all keys are stored.
302.. [9] Encryption/verify not supported, extract the public key
303
304Python version:
305
306* 3.4 (with `aenum`)
307* 3.5 (with `aenum`)
308* 3.6
309
310PKCS#11 versions:
311
312* 2.11
313* 2.20
314* 2.40
315
316Feel free to send pull requests for any functionality that's not exposed. The
317code is designed to be readable and expose the PKCS #11 spec in a
318straight-forward way.
319
320If you want your device supported, get in touch!
321
322More info on PKCS #11
323---------------------
324
325The latest version of the PKCS #11 spec is available from OASIS:
326
327http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
328
329You should also consult the documentation for your PKCS #11 implementation.
330Many implementations expose additional vendor options configurable in your
331environment, including alternative features, modes and debugging
332information.
333
334License
335-------
336
337MIT License
338
339Copyright (c) 2017 Danielle Madeley
340
341Permission is hereby granted, free of charge, to any person obtaining a copy
342of this software and associated documentation files (the "Software"), to deal
343in the Software without restriction, including without limitation the rights
344to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
345copies of the Software, and to permit persons to whom the Software is
346furnished to do so, subject to the following conditions:
347
348The above copyright notice and this permission notice shall be included in all
349copies or substantial portions of the Software.
350
351THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
353FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
354AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
355LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
356OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
357SOFTWARE.
358