1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
|
Basic usage
===========
The :mod:`pskc` module implements a simple and efficient API for parsing and
creating PSKC files. The :class:`~pskc.PSKC` class is used to access the file
as a whole which provides access to a list of :class:`~pskc.device.Device`
and :class:`~pskc.key.Key` instances which contain most of the useful
information of the PSKC file.
Reading a PSKC file
-------------------
Importing data from a PSKC file can be done by instantiating the
:class:`~pskc.PSKC` class with a file name argument::
>>> from pskc import PSKC
>>> pskc = PSKC('somefile.pskcxml')
>>> pskc.version
'1.0'
The :attr:`~pskc.PSKC.keys` attribute contains a list of keys in the PSKC
file. :class:`~pskc.key.Key` instances have a number of attributes that
provide information on the transmitted keys::
>>> key = pskc.keys[0]
>>> key.id
'some-id'
>>> key.algorithm
'urn:ietf:params:xml:ns:keyprov:pskc:hotp'
>>> key.secret
'SOME_SECRET_VALUE'
Attribute values will be ``None`` if it the value is not present in the PSKC
file.
The :attr:`~pskc.key.Key.secret`, :attr:`~pskc.key.Key.counter`,
:attr:`~pskc.key.Key.time_offset`, :attr:`~pskc.key.Key.time_interval` or
:attr:`~pskc.key.Key.time_drift` attributes may be stored in encrypted form
in the PSKC file. Decryption of these properties is done when they are
accessed. If decryption is unsuccessful a
:exc:`~pskc.exceptions.DecryptionError` exception is raised. See
:doc:`encryption` for more information.
Writing a PSKC file
-------------------
Creating a PSKC file can be done by creating a :class:`~pskc.PSKC` instance,
adding keys with :func:`~pskc.PSKC.add_key()` and writing the result::
>>> from pskc import PSKC
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.write('output.pskcxml')
By default an unencrypted PSKC file will be created but an encryption can be
configured using the
:func:`~pskc.encryption.Encryption.setup_preshared_key()` or
:func:`~pskc.encryption.Encryption.setup_pbkdf2()` function.
The PSKC class
--------------
.. module:: pskc
.. class:: PSKC([filename])
The :class:`PSKC` class is used as a wrapper to access information from a
PSKC file.
The `filename` argument can be either the name of a file or a file-like
object. The whole file is parsed in one go. If parsing the PSKC file
fails, a :exc:`~pskc.exceptions.ParseError` exception is raised.
If no argument is provided, an instance without any keys is created.
Instances of this class provide the following attributes and functions:
.. attribute:: version
The PSKC format version used. Only version ``1.0`` is currently
specified in
`RFC 6030 <https://tools.ietf.org/html/rfc6030#section-1.2>`__
and supported.
.. attribute:: id
A unique identifier for the container.
.. attribute:: devices
A list of :class:`~pskc.device.Device` instances that represent the key
containers within the PSKC file.
.. attribute:: keys
A list of :class:`~pskc.key.Key` instances that represent the keys
within the PSKC file.
.. attribute:: encryption
:class:`~pskc.encryption.Encryption` instance that handles PSKC file
encryption. See :doc:`encryption` for more information.
.. attribute:: mac
:class:`~pskc.mac.MAC` instance for handling integrity checking.
See :doc:`mac` for more information.
.. attribute:: signature
:class:`~pskc.signature.Signature` instance for handling embedded XML
signatures in the file.
See :doc:`signatures` for more information.
.. function:: add_device([**kwargs])
Add a new key package to the PSKC instance. The keyword arguments may
refer to any attributes of the :class:`~pskc.device.Device` class with
which the new device is initialised.
.. function:: add_key([**kwargs])
Add a new key to the PSKC instance. The keyword arguments may refer to
any attributes of the :class:`~pskc.key.Key` or
:class:`~pskc.device.Device` class with which the new key is
initialised.
.. function:: write(filename)
Write the PSKC object to the provided file. The `filename` argument can
be either the name of a file or a file-like object.
The Key class
-------------
.. module:: pskc.key
.. class:: Key()
Instances of this class provide the following attributes and functions:
.. attribute:: id
A unique identifier for the key. If there are multiple interactions
with the same key in multiple instances of PSKC files the `id` is
supposed to remain the same.
.. attribute:: algorithm
A URI that identifies the PSKC algorithm profile. The algorithm profile
associates specific semantics to the key. Some `known profiles
<https://www.iana.org/assignments/pskc/#alg-profiles>`__ are:
+------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| URI | Purpose |
+================================================+=============================================================================================================================+
| ``urn:ietf:params:xml:ns:keyprov:pskc:pin`` | `Symmetric static credential comparison <https://tools.ietf.org/html/rfc6030#section-10.2>`_ |
+------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| ``urn:ietf:params:xml:ns:keyprov:pskc:hotp`` | `OATH event-based OTP <https://tools.ietf.org/html/rfc6030#section-10.1>`_ |
+------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| ``urn:ietf:params:xml:ns:keyprov:pskc#totp`` | `OATH time-based OTP <https://tools.ietf.org/html/draft-hoyer-keyprov-pskc-algorithm-profiles-01#section-4>`_ |
| ``urn:ietf:params:xml:ns:keyprov:pskc:totp`` | |
+------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| ``urn:ietf:params:xml:ns:keyprov:pskc#OCRA-1`` | `OATH challenge-response algorithm <https://tools.ietf.org/html/draft-hoyer-keyprov-pskc-algorithm-profiles-01#section-3>`_ |
+------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
.. attribute:: secret
The binary value of the transported secret key. If the key information
is encrypted in the PSKC file it is transparently decrypted if
possible. Accessing the value may raise
:exc:`~pskc.exceptions.DecryptionError` if decryption fails.
.. attribute:: counter
The event counter (integer) for event-based OTP algorithms. Will also be
transparently decrypted and may also raise
:exc:`~pskc.exceptions.DecryptionError`.
.. attribute:: time_offset
The time offset (integer) for time-based OTP algorithms. If time
intervals are used it carries the number of time intervals passed from
an algorithm-dependent start point. Will also be transparently decrypted
and may also raise :exc:`~pskc.exceptions.DecryptionError`.
.. attribute:: time_interval
The time interval in seconds (integer) for time-based OTP algorithms
(usually ``30`` or ``60``). Will also be transparently decrypted and may
also raise :exc:`~pskc.exceptions.DecryptionError`.
.. attribute:: time_drift
For time-based OTP algorithms this contains the device clock drift in
number of intervals (integer). Will also be transparently decrypted and
may also raise :exc:`~pskc.exceptions.DecryptionError`.
.. attribute:: issuer
The name of the party that issued the key. This may be different from
the :attr:`~pskc.device.Device.manufacturer` of the device.
.. attribute:: key_profile
A reference to a pre-shared key profile agreed upon between the sending
and receiving parties. The profile information itself is not
transmitted within the container.
See `RFC 6030 <https://tools.ietf.org/html/rfc6030#section-4.4>`__.
.. attribute:: key_reference
A reference to an external key that is not contained within the PSKC
file (e.g., a PKCS #11 key label). If this attribute is present, the
:attr:`secret` attribute will generally be missing.
.. attribute:: friendly_name
A human-readable name for the secret key.
.. attribute:: key_userid
The distinguished name of the user associated with the key.
Also see :attr:`~pskc.device.Device.device_userid`.
.. attribute:: userid
The distinguished name of the user associated with the key or the device,
taken from :attr:`key_userid` or :attr:`~pskc.device.Device.device_userid`
whichever one is defined.
.. attribute:: algorithm_suite
Additional algorithm-specific characteristics. For example, in an
HMAC-based algorithm it could specify the hash algorithm used (SHA1
or SHA256).
.. attribute:: challenge_encoding
Encoding of the challenge accepted by the device for challenge-response
authentication. One of:
* ``DECIMAL``: only numerical digits
* ``HEXADECIMAL``: hexadecimal
* ``ALPHANUMERIC``: all letters and numbers (case sensitive)
* ``BASE64``: base-64 encoded
* ``BINARY``: binary data
.. attribute:: challenge_min_length
The minimum size of the challenge accepted by the device.
.. attribute:: challenge_max_length
The maximum size of the challenge accepted by the device.
.. attribute:: challenge_check
Boolean that indicates whether the device will check an embedded
`Luhn check digit <https://arthurdejong.org/python-stdnum/doc/stdnum.luhn.html>`_
contained in the challenge.
.. attribute:: response_encoding
Format of the response that is generated by the device. If must be one
of the values as described under :attr:`challenge_encoding`.
.. attribute:: response_length
The length of the response generated by the device.
.. attribute:: response_check
Boolean that indicates whether the device will append a
`Luhn check digit <https://arthurdejong.org/python-stdnum/doc/stdnum.luhn.html>`_
to the response.
.. attribute:: policy
:class:`~pskc.policy.Policy` instance that provides key and PIN policy
information. See :doc:`policy`.
.. function:: check()
Check if any MACs in the key data embedded in the PSKC file are valid.
This will return None if there is no MAC to be checked. It will return
True if all the MACs match. If any MAC fails a
:exc:`~pskc.exceptions.DecryptionError` exception is raised.
Apart from the above, all properties of the :class:`~pskc.device.Device`
class are also transparently available in :class:`~pskc.key.Key`
instances.
The Device class
----------------
.. module:: pskc.device
.. class:: Device()
Instances of this class provide the following attributes and functions:
.. attribute:: keys
A list of :class:`~pskc.key.Key` instances that represent the keys that
are linked to this device. Most PSKC files only allow one key per
device which is why all :class:`~pskc.device.Device` attributes are
available in :class:`~pskc.key.Key`.
.. function:: add_key([**kwargs])
Add a new key to the device. The keyword arguments may refer to
any attributes of the :class:`~pskc.key.Key` or
:class:`~pskc.device.Device` class with which the new key is
initialised.
.. attribute:: manufacturer
The name of the manufacturer of the device to which the key is
provisioned.
`RFC 6030 <https://tools.ietf.org/html/rfc6030#section-4.3.1>`__
prescribes that the value is of the form ``oath.prefix`` for `OATH
Manufacturer Prefixes <https://openauthentication.org/oath-manufacturers/>`_
or ``iana.organisation`` for `IANA Private Enterprise Numbers
<https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers>`_
however, it is generally just a string.
The value may be different from the :attr:`~pskc.key.Key.issuer` of
the key on the device.
.. attribute:: serial
The serial number of the device to which the key is provisioned.
Together with :attr:`manufacturer` (and possibly :attr:`issue_no`) this
should uniquely identify the device.
.. attribute:: model
A manufacturer-specific description of the model of the device.
.. attribute:: issue_no
The issue number in case there are devices with the same :attr:`serial`
number so that they can be distinguished by different issue numbers.
.. attribute:: device_binding
Reference to a device identifier (e.g. IMEI) that allows a provisioning
server to ensure that the key is going to be loaded into a specific
device.
.. attribute:: start_date
:class:`datetime.datetime` value that indicates that the device should
only be used after this date.
.. attribute:: expiry_date
:class:`datetime.datetime` value that indicates that the device should
only be used before this date. Systems should not rely upon the device
to enforce key usage date restrictions, as some devices do not have an
internal clock.
.. attribute:: device_userid
The distinguished name of the user associated with the device.
Also see :attr:`~pskc.key.Key.key_userid`.
.. attribute:: crypto_module
Implementation specific unique identifier of the cryptographic module
on the device to which the keys have been (or will be) provisioned.
|