Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
python-pskc
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Jobs
Commits
Open sidebar
Debian Python Team
DPMT
python-pskc
Commits
3a94d054
Commit
3a94d054
authored
Jan 21, 2017
by
Arthur de Jong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import python-pskc_0.5.orig.tar.gz
parent
816c2f20
Changes
62
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
62 changed files
with
3567 additions
and
965 deletions
+3567
-965
ChangeLog
ChangeLog
+317
-43
NEWS
NEWS
+22
-0
PKG-INFO
PKG-INFO
+11
-2
README
README
+11
-2
docs/conf.py
docs/conf.py
+1
-1
docs/encryption.rst
docs/encryption.rst
+2
-2
docs/usage.rst
docs/usage.rst
+103
-61
pskc/__init__.py
pskc/__init__.py
+37
-51
pskc/algorithms.py
pskc/algorithms.py
+72
-0
pskc/crypto/__init__.py
pskc/crypto/__init__.py
+38
-0
pskc/device.py
pskc/device.py
+69
-0
pskc/encryption.py
pskc/encryption.py
+114
-215
pskc/key.py
pskc/key.py
+75
-254
pskc/mac.py
pskc/mac.py
+16
-57
pskc/parser.py
pskc/parser.py
+291
-0
pskc/policy.py
pskc/policy.py
+3
-69
pskc/serialiser.py
pskc/serialiser.py
+222
-0
pskc/xml.py
pskc/xml.py
+16
-14
pskc2csv.py
pskc2csv.py
+2
-2
python_pskc.egg-info/PKG-INFO
python_pskc.egg-info/PKG-INFO
+11
-2
python_pskc.egg-info/SOURCES.txt
python_pskc.egg-info/SOURCES.txt
+29
-2
setup.cfg
setup.cfg
+3
-1
setup.py
setup.py
+2
-2
tests/draft-hoyer-keyprov-pskc-algorithm-profiles-01/actividentity-3des.pskcxml
...rov-pskc-algorithm-profiles-01/actividentity-3des.pskcxml
+35
-37
tests/draft-hoyer-keyprov-pskc-algorithm-profiles-01/ocra.pskcxml
...aft-hoyer-keyprov-pskc-algorithm-profiles-01/ocra.pskcxml
+26
-27
tests/draft-hoyer-keyprov-pskc-algorithm-profiles-01/securid-aes-counter.pskcxml
...ov-pskc-algorithm-profiles-01/securid-aes-counter.pskcxml
+28
-29
tests/draft-hoyer-keyprov-pskc-algorithm-profiles-01/totp.pskcxml
...aft-hoyer-keyprov-pskc-algorithm-profiles-01/totp.pskcxml
+32
-32
tests/draft-ietf-keyprov-pskc-02/figure2.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure2.pskcxml
+31
-0
tests/draft-ietf-keyprov-pskc-02/figure3.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure3.pskcxml
+52
-0
tests/draft-ietf-keyprov-pskc-02/figure4.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure4.pskcxml
+51
-0
tests/draft-ietf-keyprov-pskc-02/figure5.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure5.pskcxml
+71
-0
tests/draft-ietf-keyprov-pskc-02/figure6.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure6.pskcxml
+63
-0
tests/draft-ietf-keyprov-pskc-02/figure7.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure7.pskcxml
+34
-0
tests/draft-ietf-keyprov-pskc-02/figure8.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure8.pskcxml
+68
-0
tests/draft-ietf-keyprov-pskc-02/figure9.pskcxml
tests/draft-ietf-keyprov-pskc-02/figure9.pskcxml
+112
-0
tests/encryption/aes128-cbc-noiv.pskcxml
tests/encryption/aes128-cbc-noiv.pskcxml
+38
-0
tests/encryption/mac-over-plaintext.pskcxml
tests/encryption/mac-over-plaintext.pskcxml
+39
-0
tests/encryption/no-mac-key.pskcxml
tests/encryption/no-mac-key.pskcxml
+32
-0
tests/invalid/incomplete-derivation.pskcxml
tests/invalid/incomplete-derivation.pskcxml
+46
-0
tests/invalid/mac-value.pskcxml
tests/invalid/mac-value.pskcxml
+3
-3
tests/invalid/missing-encryption-method.pskcxml
tests/invalid/missing-encryption-method.pskcxml
+32
-0
tests/invalid/missing-encryption.pskcxml
tests/invalid/missing-encryption.pskcxml
+1
-1
tests/invalid/no-mac-method.pskcxml
tests/invalid/no-mac-method.pskcxml
+1
-1
tests/misc/SampleFullyQualifiedNS.xml
tests/misc/SampleFullyQualifiedNS.xml
+0
-1
tests/misc/policy.pskcxml
tests/misc/policy.pskcxml
+4
-2
tests/rfc6030/figure8.pskcxml
tests/rfc6030/figure8.pskcxml
+60
-0
tests/rfc6030/figure9.pskcxml
tests/rfc6030/figure9.pskcxml
+65
-0
tests/test_actividentity.doctest
tests/test_actividentity.doctest
+62
-0
tests/test_aeskw.doctest
tests/test_aeskw.doctest
+38
-4
tests/test_crypto.doctest
tests/test_crypto.doctest
+76
-0
tests/test_draft_ietf_keyprov_pskc_02.doctest
tests/test_draft_ietf_keyprov_pskc_02.doctest
+305
-0
tests/test_encryption.doctest
tests/test_encryption.doctest
+57
-3
tests/test_feitian.doctest
tests/test_feitian.doctest
+1
-27
tests/test_invalid.doctest
tests/test_invalid.doctest
+38
-1
tests/test_misc.doctest
tests/test_misc.doctest
+38
-3
tests/test_nagraid.doctest
tests/test_nagraid.doctest
+54
-0
tests/test_rfc6030.doctest
tests/test_rfc6030.doctest
+74
-10
tests/test_write.doctest
tests/test_write.doctest
+138
-4
tests/test_yubico.doctest
tests/test_yubico.doctest
+149
-0
tests/yubico/example1.pskcxml
tests/yubico/example1.pskcxml
+38
-0
tests/yubico/example2.pskcxml
tests/yubico/example2.pskcxml
+61
-0
tests/yubico/example3.pskcxml
tests/yubico/example3.pskcxml
+47
-0
No files found.
ChangeLog
View file @
3a94d054
This diff is collapsed.
Click to expand it.
NEWS
View file @
3a94d054
changes from 0.4 to 0.5
-----------------------
* numerous compatibility improvements for reading PSKC files that do not
follow the RFC 6030 schema exactly: specifically accept a number of old
Internet Draft specifications that preceded RFC 6030 and support an
ActivIdentity file format
* split device information from key information (keep old API available) to
allow multiple keys per device (this is not allowed by RFC 6030 but was
allowed in older Internet Drafts)
* accept MAC to be over plaintext in addition to ciphertext
* fall back to using encryption key as MAC key
* refactoring of some encryption, parsing and serialising functionality into
separate modules for better maintainability
* add configuration for running test suite via Tox
* addition of a large number of test cases, bringing the branch coverage to
100%
* documentation improvements
* drop official support for Python 2.6 (the module still works but is just no
longer tested with it)
changes from 0.3 to 0.4
-----------------------
...
...
PKG-INFO
View file @
3a94d054
Metadata-Version: 1.1
Name: python-pskc
Version: 0.
4
Version: 0.
5
Summary: Python module for handling PSKC files
Home-page: http://arthurdejong.org/python-pskc/
Author: Arthur de Jong
...
...
@@ -25,6 +25,15 @@ Description: Python module for handling PSKC files
... print('%s %s' % (key.serial, str(key.secret.decode())))
987654321 12345678901234567890
The following generates an encrypted PSKC file:
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.encryption.setup_pbkdf2('passphrase')
>>> pskc.write('output.pskcxml')
The module should be able to handle most common PSKC files.
Keywords: PSKC,RFC 6030,key container
...
...
@@ -37,11 +46,11 @@ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or l
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
...
...
README
View file @
3a94d054
...
...
@@ -19,7 +19,7 @@ API
The module provides a straightforward API that is mostly geared towards
parsing existing PSKC files.
Extracting key material from encrypted PSKC files is as simple as
.
Extracting key material from encrypted PSKC files is as simple as
:
>>> from pskc import PSKC
>>> pskc = PSKC('tests/rfc6030/figure7.pskcxml')
...
...
@@ -28,6 +28,15 @@ Extracting key material from encrypted PSKC files is as simple as.
... print key.serial, key.secret
987654321 12345678901234567890
Writing am encrypted PSKC file is as simple as:
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.encryption.setup_pbkdf2('passphrase')
>>> pskc.write('output.pskcxml')
The key object has a number of properties. See the pskc.key.Key documentation
for details.
...
...
@@ -44,7 +53,7 @@ private key material.
Copyright
---------
Copyright (C) 2014-201
6
Arthur de Jong
Copyright (C) 2014-201
7
Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
...
...
docs/conf.py
View file @
3a94d054
...
...
@@ -46,7 +46,7 @@ master_doc = 'index'
# General information about the project.
project
=
u'python-pskc'
copyright
=
u'2014-201
6
Arthur de Jong'
copyright
=
u'2014-201
7
Arthur de Jong'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
...
...
docs/encryption.rst
View file @
3a94d054
...
...
@@ -93,7 +93,7 @@ The Encryption class
.. function:: setup_preshared_key(...)
Configure pre-shared key encryption.
Configure pre-shared key encryption
when writing the file
.
:param binary key: the encryption key to use
:param str id: encryption key identifier
...
...
@@ -119,7 +119,7 @@ The Encryption class
.. function:: setup_pbkdf2(...)
Configure password-based PSKC encryption.
Configure password-based PSKC encryption
when writing the file
.
:param str password: the password to use (required)
:param str id: encryption key identifier
...
...
docs/usage.rst
View file @
3a94d054
...
...
@@ -3,8 +3,9 @@ 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.key.Key`
instances which contain most of the useful information of the PSKC 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
...
...
@@ -89,6 +90,11 @@ The PSKC class
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
...
...
@@ -105,11 +111,18 @@ The PSKC class
See :doc:`mac` 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` class with which the new
key is initialised.
any attributes of the :class:`~pskc.key.Key` or
:class:`~pskc.device.Device` class with which the new key is
initialised.
.. function:: write(filename)
...
...
@@ -186,7 +199,7 @@ The Key class
.. attribute:: issuer
The name of the party that issued the key. This may be different from
the :attr:`manufacturer` of the device.
the :attr:`
~pskc.device.Device.
manufacturer` of the device.
.. attribute:: key_profile
...
...
@@ -208,62 +221,7 @@ The Key class
.. attribute:: key_userid
The distinguished name of the user associated with the key.
Also see :attr:`device_userid`.
.. 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 <http://www.openauthentication.org/oath-id/prefixes/>`_
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:`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:`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.
Also see :attr:`~pskc.device.Device.device_userid`.
.. attribute:: algorithm_suite
...
...
@@ -322,3 +280,87 @@ The Key class
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 <http://www.openauthentication.org/oath-id/prefixes/>`_
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.
pskc/__init__.py
View file @
3a94d054
# __init__.py - main module
# coding: utf-8
#
# Copyright (C) 2014-201
6
Arthur de Jong
# Copyright (C) 2014-201
7
Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
...
...
@@ -37,6 +37,15 @@ The following prints all keys, decrypting using a password:
... print('
%
s
%
s'
%
(key.serial, str(key.secret.decode())))
987654321 12345678901234567890
The following generates an encrypted PSKC file:
>>> pskc = PSKC()
>>> key = pskc.add_key(
... id='456', secret='987654321', manufacturer='Manufacturer',
... algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp')
>>> pskc.encryption.setup_pbkdf2('passphrase')
>>> pskc.write('output.pskcxml')
The module should be able to handle most common PSKC files.
"""
...
...
@@ -45,7 +54,7 @@ __all__ = ['PSKC', '__version__']
# the version number of the library
__version__
=
'0.
4
'
__version__
=
'0.
5
'
class
PSKC
(
object
):
...
...
@@ -57,68 +66,50 @@ class PSKC(object):
id: identifier
encryption: information on used encryption (Encryption instance)
mac: information on used MAC method (MAC instance)
devices: list of devices (Device instances)
keys: list of keys (Key instances)
"""
def
__init__
(
self
,
filename
=
None
):
from
pskc.encryption
import
Encryption
from
pskc.exceptions
import
ParseError
from
pskc.mac
import
MAC
self
.
version
=
None
self
.
id
=
None
self
.
encryption
=
Encryption
(
self
)
self
.
mac
=
MAC
(
self
)
self
.
key
s
=
[]
self
.
device
s
=
[]
if
filename
is
not
None
:
from
pskc.xml
import
parse
,
remove_namespaces
try
:
tree
=
parse
(
filename
)
except
Exception
:
raise
ParseError
(
'Error parsing XML'
)
remove_namespaces
(
tree
)
self
.
parse
(
tree
.
getroot
())
from
pskc.parser
import
PSKCParser
PSKCParser
.
parse_file
(
self
,
filename
)
else
:
self
.
version
=
'1.0'
def
parse
(
self
,
container
):
"""Read information from the provided <KeyContainer> tree."""
from
pskc.exceptions
import
ParseError
from
pskc.key
import
Key
from
pskc.xml
import
find
,
findall
if
container
.
tag
!=
'KeyContainer'
:
raise
ParseError
(
'Missing KeyContainer'
)
# the version of the PSKC schema
self
.
version
=
container
.
get
(
'Version'
)
if
self
.
version
!=
'1.0'
:
raise
ParseError
(
'Unsupported version
%
r'
%
self
.
version
)
# unique identifier for the container
self
.
id
=
container
.
get
(
'Id'
)
# handle EncryptionKey entries
self
.
encryption
.
parse
(
find
(
container
,
'EncryptionKey'
))
# handle MACMethod entries
self
.
mac
.
parse
(
find
(
container
,
'MACMethod'
))
# handle KeyPackage entries
for
key_package
in
findall
(
container
,
'KeyPackage'
):
self
.
keys
.
append
(
Key
(
self
,
key_package
))
def
make_xml
(
self
):
from
pskc.xml
import
mk_elem
container
=
mk_elem
(
'pskc:KeyContainer'
,
Version
=
self
.
version
,
Id
=
self
.
id
)
self
.
encryption
.
make_xml
(
container
)
self
.
mac
.
make_xml
(
container
)
for
key
in
self
.
keys
:
key
.
make_xml
(
container
)
return
container
@
property
def
keys
(
self
):
return
tuple
(
key
for
device
in
self
.
devices
for
key
in
device
.
keys
)
def
add_device
(
self
,
**
kwargs
):
"""Create a new device instance for the PSKC file.
The device is initialised with properties from the provided keyword
arguments if any."""
from
pskc.device
import
Device
device
=
Device
(
self
)
self
.
devices
.
append
(
device
)
# assign the kwargs as key properties
for
k
,
v
in
kwargs
.
items
():
if
not
hasattr
(
device
,
k
):
raise
AttributeError
()
setattr
(
device
,
k
,
v
)
return
device
def
add_key
(
self
,
**
kwargs
):
"""Create a new key instance for the PSKC file.
The new key is initialised with properties from the provided keyword
arguments if any."""
from
pskc.key
import
Key
key
=
Key
(
self
)
self
.
keys
.
append
(
key
)
device
=
self
.
add_device
()
key
=
device
.
add_key
()
# assign the kwargs as key properties
for
k
,
v
in
kwargs
.
items
():
if
not
hasattr
(
key
,
k
):
...
...
@@ -128,14 +119,9 @@ class PSKC(object):
def
write
(
self
,
filename
):
"""Write the PSKC file to the provided file."""
from
pskc.
xml
import
tostring
from
pskc.
serialiser
import
PSKCSerialiser
if
hasattr
(
filename
,
'write'
):
xml
=
tostring
(
self
.
make_xml
())
try
:
filename
.
write
(
xml
)
except
TypeError
:
# pragma: no cover (Python 3 specific)
# fall back to writing as string for Python 3
filename
.
write
(
xml
.
decode
(
'utf-8'
))
PSKCSerialiser
.
serialise_file
(
self
,
filename
)
else
:
with
open
(
filename
,
'wb'
)
as
output
:
self
.
write
(
output
)
pskc/algorithms.py
0 → 100644
View file @
3a94d054
# algorithms.py - module for handling algorithm URIs
# coding: utf-8
#
# Copyright (C) 2016 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Utility module that handles algorthm URIs."""
# cannonical URIs of known algorithms
_algorithms
=
{
'tripledes-cbc'
:
'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
,
'kw-tripledes'
:
'http://www.w3.org/2001/04/xmlenc#kw-tripledes'
,
'aes128-cbc'
:
'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
,
'aes192-cbc'
:
'http://www.w3.org/2001/04/xmlenc#aes192-cbc'
,
'aes256-cbc'
:
'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
,
'kw-aes128'
:
'http://www.w3.org/2001/04/xmlenc#kw-aes128'
,
'kw-aes192'
:
'http://www.w3.org/2001/04/xmlenc#kw-aes192'
,
'kw-aes256'
:
'http://www.w3.org/2001/04/xmlenc#kw-aes256'
,
'camellia128'
:
'http://www.w3.org/2001/04/xmldsig-more#camellia128'
,
'camellia192'
:
'http://www.w3.org/2001/04/xmldsig-more#camellia192'
,
'camellia256'
:
'http://www.w3.org/2001/04/xmldsig-more#camellia256'
,
'kw-camellia128'
:
'http://www.w3.org/2001/04/xmldsig-more#kw-camellia128'
,
'kw-camellia192'
:
'http://www.w3.org/2001/04/xmldsig-more#kw-camellia192'
,
'kw-camellia256'
:
'http://www.w3.org/2001/04/xmldsig-more#kw-camellia256'
,
'hmac-md5'
:
'http://www.w3.org/2001/04/xmldsig-more#hmac-md5'
,
'hmac-sha1'
:
'http://www.w3.org/2000/09/xmldsig#hmac-sha1'
,
'hmac-sha224'
:
'http://www.w3.org/2001/04/xmldsig-more#hmac-sha224'
,
'hmac-sha256'
:
'http://www.w3.org/2001/04/xmldsig-more#hmac-sha256'
,
'hmac-sha384'
:
'http://www.w3.org/2001/04/xmldsig-more#hmac-sha384'
,
'hmac-sha512'
:
'http://www.w3.org/2001/04/xmldsig-more#hmac-sha512'
,
'hmac-ripemd160'
:
'http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160'
,
'pbkdf2'
:
'http://www.rsasecurity.com/rsalabs/pkcs/schemas/'
+
'pkcs-5v2-0#pbkdf2'
,
}
# translation table to change old encryption names to new names
_algorithm_aliases
=
{
'3des-cbc'
:
'tripledes-cbc'
,
'3des112-cbc'
:
'tripledes-cbc'
,
'3des168-cbc'
:
'tripledes-cbc'
,
'kw-3des'
:
'kw-tripledes'
,
'pbe-3des112-cbc'
:
'tripledes-cbc'
,
'pbe-3des168-cbc'
:
'tripledes-cbc'
,
'pbe-aes128-cbc'
:
'aes128-cbc'
,
'pbe-aes192-cbc'
:
'aes192-cbc'
,
'pbe-aes256-cbc'
:
'aes256-cbc'
,
'rsa-1_5'
:
'rsa-1_5'
,
'rsa-oaep-mgf1p'
:
'rsa-oaep-mgf1p'
,
}
def
normalise_algorithm
(
algorithm
):
"""Return the canonical URI for the provided algorithm."""
if
not
algorithm
or
algorithm
.
lower
()
==
'none'
:
return
None
algorithm
=
_algorithm_aliases
.
get
(
algorithm
.
lower
(),
algorithm
)
return
_algorithms
.
get
(
algorithm
.
rsplit
(
'#'
,
1
)[
-
1
]
.
lower
(),
algorithm
)
pskc/crypto/__init__.py
View file @
3a94d054
# __init__.py - general crypto utility functions
# coding: utf-8
#
# Copyright (C) 2016 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Implement crypto utility functions."""
def
pad
(
value
,
block_size
):
"""Pad the value to block_size length."""
padding
=
block_size
-
(
len
(
value
)
%
block_size
)
return
value
+
padding
*
chr
(
padding
)
.
encode
(
'ascii'
)
def
unpad
(
value
,
block_size
):
"""Remove padding from the plaintext."""
from
pskc.exceptions
import
DecryptionError
padding
=
ord
(
value
[
-
1
:])
# only unpad if all padding bytes are the same
if
(
padding
>
0
and
padding
<=
block_size
and
value
[
-
padding
:]
==
padding
*
chr
(
padding
)
.
encode
(
'ascii'
)):
return
value
[:
-
padding
]
raise
DecryptionError
(
'Invalid padding'
)
pskc/device.py
0 → 100644
View file @
3a94d054
# device.py - module for handling device info from pskc files
# coding: utf-8
#
# Copyright (C) 2016 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Module that handles device information stored in PSKC files."""
class
Device
(
object
):
"""Representation of a single key from a PSKC file.
Instances of this class provide the following properties:
manufacturer: name of the organisation that made the device
serial: serial number of the device
model: device model description
issue_no: issue number per serial number
device_binding: device (class) identifier for the key to be loaded upon
start_date: key should not be used before this date
expiry_date: key or device may expire after this date
device_userid: user distinguished name associated with the device
crypto_module: id of module to which keys are provisioned within device
"""
def
__init__
(
self
,
pskc
):
self
.
pskc
=
pskc
self
.
manufacturer
=
None
self
.
serial
=
None
self
.
model
=
None
self
.
issue_no
=
None
self
.
device_binding
=
None
self
.
start_date
=
None
self
.
expiry_date
=
None
self
.
device_userid
=
None
self
.
crypto_module
=
None
self
.
keys
=
[]
def
add_key
(
self
,
**
kwargs
):
"""Create a new key instance for the device.
The new key is initialised with properties from the provided keyword
arguments if any."""
from
pskc.key
import
Key
key
=
Key
(
self
)
self
.
keys
.
append
(
key
)
# assign the kwargs as key properties
for
k
,
v
in
kwargs
.
items
():
if
not
hasattr
(
key
,
k
):
raise
AttributeError
()
setattr
(
key
,
k
,
v
)
return
key
pskc/encryption.py
View file @
3a94d054
This diff is collapsed.
Click to expand it.
pskc/key.py
View file @
3a94d054
This diff is collapsed.
Click to expand it.
pskc/mac.py
View file @
3a94d054
...
...
@@ -29,7 +29,6 @@ with the PSKC encryption key.
"""
import
base64
import
re
...
...
@@ -53,6 +52,18 @@ def get_hmac(algorithm):
return
lambda
key
,
value
:
hmac
.
new
(
key
,
value
,
digestmod
)
.
digest
()
def
get_mac
(
algorithm
,
key
,
value
):
"""Generate the MAC value over the specified value."""
from
pskc.exceptions
import
DecryptionError
if
algorithm
is
None
:
raise
DecryptionError
(
'No MAC algorithm set'
)
hmacfn
=
get_hmac
(
algorithm
)
if
hmacfn
is
None
:
raise
DecryptionError
(
'Unsupported MAC algorithm:
%
r'
%
algorithm
)
return
hmacfn
(
key
,
value
)
class
MAC
(
object
):
"""Class describing the MAC algorithm to use and how to get the key.
...
...
@@ -69,41 +80,6 @@ class MAC(object):
self
.
key_cipher_value
=
None
self
.
key_algorithm
=
None
def
parse
(
self
,
mac_method
):
"""Read MAC information from the <MACMethod> XML tree."""
from
pskc.xml
import
find
,
findtext
,
findbin
if
mac_method
is
None
:
return
self
.
algorithm
=
mac_method
.
get
(
'Algorithm'
)
mac_key
=
find
(
mac_method
,
'MACKey'
)
if
mac_key
is
not
None
:
self
.
key_cipher_value
=
findbin
(
mac_key
,
'CipherData/CipherValue'
)
encryption_method
=
find
(
mac_key
,
'EncryptionMethod'
)
if
encryption_method
is
not
None
:
self
.
key_algorithm
=
encryption_method
.
attrib
.
get
(
'Algorithm'
)
mac_key_reference
=
findtext
(
mac_method
,
'MACKeyReference'
)
def
make_xml
(
self
,
container
):
from
pskc.xml
import
mk_elem
if
not
self
.
algorithm
and
not
self
.
key
:
return
mac_method
=
mk_elem
(
container
,
'pskc:MACMethod'
,
Algorithm
=
self
.
algorithm
,
empty
=
True
)
mac_key
=
mk_elem
(
mac_method
,
'pskc:MACKey'
,
empty
=
True
)
mk_elem
(
mac_key
,
'xenc:EncryptionMethod'
,
Algorithm
=
self
.
pskc
.
encryption
.
algorithm
)
cipher_data
=
mk_elem
(
mac_key
,
'xenc:CipherData'
,
empty
=
True
)
if
self
.
key_cipher_value
:
mk_elem
(
cipher_data
,
'xenc:CipherValue'
,
base64
.
b64encode
(
self
.
key_cipher_value
)
.
decode
())
elif
self
.
key_plain_value
:
mk_elem
(
cipher_data
,
'xenc:CipherValue'
,
base64
.
b64encode
(
self
.
pskc
.
encryption
.
encrypt_value
(
self
.
key_plain_value
)
)
.
decode
())
@
property
def
key
(
self
):
"""Provides access to the MAC key binary value if available."""
...
...
@@ -112,6 +88,8 @@ class MAC(object):
elif
self
.
key_cipher_value
:
return
self
.
pskc
.
encryption
.
decrypt_value
(
self
.
key_cipher_value
,
self
.
key_algorithm
)
# fall back to encryption key
return
self
.
pskc
.
encryption
.
key
@
key
.
setter
def
key
(
self
,
value
):
...
...
@@ -126,7 +104,7 @@ class MAC(object):
@
algorithm
.
setter
def
algorithm
(
self
,
value
):
from
pskc.
encryption
import
normalise_algorithm
from
pskc.
algorithms
import
normalise_algorithm
self
.
_algorithm
=
normalise_algorithm
(
value
)
@
property
...
...
@@ -142,26 +120,7 @@ class MAC(object):
def
generate_mac
(
self
,
value
):
"""Generate the MAC over the specified value."""
from
pskc.exceptions
import
DecryptionError
key
=
self
.
key