[Python-modules-commits] [python-pskc] 01/09: Import python-pskc_0.3.orig.tar.gz

Arthur de Jong adejong at moszumanska.debian.org
Mon Mar 28 20:06:36 UTC 2016


This is an automated email from the git hooks/post-receive script.

adejong pushed a commit to branch master
in repository python-pskc.

commit e9792624ef7adb550500faeb118bb0c7d9f73e39
Author: Arthur de Jong <adejong at debian.org>
Date:   Mon Mar 28 21:16:07 2016 +0200

    Import python-pskc_0.3.orig.tar.gz
---
 ChangeLog                        | 126 +++++++++++++++++++++++++++++
 MANIFEST.in                      |   2 +-
 NEWS                             |  10 +++
 PKG-INFO                         |  16 ++--
 README                           |   7 +-
 docs/conf.py                     |   2 +-
 docs/encryption.rst              |  12 ++-
 docs/exceptions.rst              |   6 +-
 docs/mac.rst                     |  28 ++++---
 docs/policy.rst                  |  27 +++++--
 docs/usage.rst                   | 151 ++++++++++++++++++++++-------------
 pskc/__init__.py                 |  33 +++++---
 pskc/crypto/__init__.py          |   0
 pskc/{ => crypto}/aeskw.py       |  22 +++---
 pskc/{ => crypto}/tripledeskw.py |  10 ++-
 pskc/encryption.py               |  30 +++----
 pskc/key.py                      | 150 ++++++++++++++++++++++++++---------
 pskc/mac.py                      |   4 +-
 pskc/parse.py                    | 102 ------------------------
 pskc/policy.py                   |  32 +++++++-
 pskc/xml.py                      | 166 +++++++++++++++++++++++++++++++++++++++
 pskc2csv.py                      | 127 ++++++++++++++++++++++++++++++
 python_pskc.egg-info/PKG-INFO    |  16 ++--
 python_pskc.egg-info/SOURCES.txt |  11 ++-
 python_pskc.egg-info/pbr.json    |   1 +
 setup.py                         |  10 ++-
 tests/SampleFullyQualifiedNS.xml | 100 +++++++++++++++++++++++
 tests/test_aeskw.doctest         |  79 ++++++++++---------
 tests/test_draft_keyprov.doctest |  13 +--
 tests/test_encryption.doctest    |  59 ++++++++------
 tests/test_invalid.doctest       |  11 +--
 tests/test_misc.doctest          |  31 +++++++-
 tests/test_rfc6030.doctest       |  33 +++++---
 tests/test_tripledeskw.doctest   |   9 ++-
 tests/test_write.doctest         | 145 ++++++++++++++++++++++++++++++++++
 35 files changed, 1197 insertions(+), 384 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b8a8d1d..6a16e2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,129 @@
+2015-10-07  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [cf0c9e6] README, docs/conf.py, docs/encryption.rst,
+	  docs/exceptions.rst, docs/mac.rst, docs/policy.rst, docs/usage.rst,
+	  pskc/__init__.py: Update documentation
+
+	  This updates the documentation with the new features (writing PSKC
+	  files) as well as many editorial improvements, some rewording
+	  and a few typo fixes. Some things were moved around a little in
+	  order to be more easily readable and easier to find.
+
+2015-10-06  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [671b6e2] pskc/__init__.py, pskc/crypto/aeskw.py,
+	  pskc/crypto/tripledeskw.py, pskc/encryption.py, pskc/key.py,
+	  pskc/policy.py, pskc/xml.py, setup.py, tests/test_aeskw.doctest,
+	  tests/test_draft_keyprov.doctest, tests/test_encryption.doctest,
+	  tests/test_invalid.doctest, tests/test_misc.doctest,
+	  tests/test_rfc6030.doctest, tests/test_tripledeskw.doctest,
+	  tests/test_write.doctest: Support Python 3
+
+	  This enables support for Python 3 together with Python 2 support
+	  with a single codebase.
+
+	  On Python 3 key data is passed around as bytestrings which makes
+	  the doctests a little harder to maintain across Python versions.
+
+2015-10-06  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [68b20e2] pskc/encryption.py, pskc/xml.py,
+	  tests/SampleFullyQualifiedNS.xml, tests/test_misc.doctest:
+	  Fix issue with namespaced PBKDF2 parameters
+
+	  The find() utility functions now allow specifying multiple paths
+	  to be searched where the first match is returned.
+
+	  This allows handling PSKC files where the PBKDF2 salt, iteration
+	  count, key length and PRF elements are prefixed with the xenc11
+	  namespace.
+
+	  A test including such a PSKC file has been included.
+
+	  Thanks to Eric Plet for reporting this.
+
+2014-10-12  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [ebe46f2] pskc2csv.py: Provide a sample pskc2csv script
+
+	  This is a simple command-line utility that reads a PSKC file
+	  and outputs information on keys as CSV.
+
+2014-06-30  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [1363564] pskc/aeskw.py, pskc/crypto/__init__.py,
+	  pskc/crypto/aeskw.py, pskc/crypto/tripledeskw.py,
+	  pskc/encryption.py, pskc/tripledeskw.py, tests/test_aeskw.doctest,
+	  tests/test_tripledeskw.doctest: Move encryption functions in
+	  pskc.crypto package
+
+	  This moves the encryption functions under the pskc.crypto package
+	  to more clearly separate it from the other code. Ideally this
+	  should be replaced by third-party library code.
+
+2014-06-30  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [e468ebe] pskc/__init__.py, pskc/encryption.py, pskc/key.py,
+	  pskc/mac.py, pskc/parse.py, pskc/policy.py, pskc/xml.py: Rename
+	  pskc.parse to pskc.xml
+
+	  This renames the parse module to xml to better reflect the
+	  purpose of the module and it's functions.
+
+	  This also introduces a parse() function that wraps etree.parse().
+
+2014-06-28  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [480e2d0] : Support writing unencrypted PSKC files
+
+2014-06-27  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [37dc64a] tests/test_write.doctest: Add test for writing PSKC files
+
+	  This makes a simple doctest that checks the writing of the XML
+	  representation of the PSKC data.
+
+2014-06-27  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [865a755] pskc/__init__.py, pskc/parse.py: Add function for
+	  writing XML
+
+	  This provides a function for pretty-printing the generated
+	  XML document.
+
+2014-06-27  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [61a192f] pskc/__init__.py, pskc/key.py, pskc/policy.py: Construct
+	  XML document with basic PKSC information
+
+	  This introduces make_xml() functions to build an XML document
+	  that contains the basic PSKC information and keys. This currently
+	  only supports writing unencrypted PSKC files.
+
+2014-06-27  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [69aec9f] pskc/parse.py: Introduce mk_elem() to create elements
+
+	  This introduces the mk_elem() function that can be used to create
+	  ElementTree elements for building XML documents. This function
+	  transparetly handles namespaces, translation of values into
+	  XML etc.
+
+2014-06-27  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [7591271] pskc/key.py: Simplify DataType value handling
+
+	  Only store the native value of the property, not the text
+	  representation. This also results in the BinaryDataType and
+	  IntegerDataType subclasses only needing from_text() and from_bin()
+	  functions.
+
+2014-06-19  Arthur de Jong <arthur at arthurdejong.org>
+
+	* [09eb6b3] ChangeLog, NEWS, docs/changes.rst, docs/index.rst,
+	  docs/usage.rst, pskc/__init__.py, setup.py: Get files ready for
+	  0.2 release
+
 2014-06-19  Arthur de Jong <arthur at arthurdejong.org>
 
 	* [62c9af4] pskc/__init__.py: Only catch normal exceptions
diff --git a/MANIFEST.in b/MANIFEST.in
index 217a0fd..6eb0c88 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,3 @@
 include README NEWS ChangeLog COPYING *.py
-recursive-include tests *.doctest *.py *.pskcxml
+recursive-include tests *.doctest *.py *.pskcxml *.xml
 recursive-include docs *.rst *.py
diff --git a/NEWS b/NEWS
index 4318931..3200bce 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,13 @@
+changes from 0.2 to 0.3
+-----------------------
+
+* support writing unencrypted PSKC files
+* include a sample pskc2csv script in the source code
+* fix an issue with XML namespaces for PBKDF2 parameters
+* support Python 3
+* update documentation
+
+
 changes from 0.1 to 0.2
 -----------------------
 
diff --git a/PKG-INFO b/PKG-INFO
index c001dfc..0b63ca7 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-pskc
-Version: 0.2
+Version: 0.3
 Summary: Python module for handling PSKC files
 Home-page: http://arthurdejong.org/python-pskc/
 Author: Arthur de Jong
@@ -22,23 +22,25 @@ Description: Python module for handling PSKC files
         >>> pskc = PSKC('tests/rfc6030-figure7.pskcxml')
         >>> pskc.encryption.derive_key('qwerty')
         >>> for key in pskc.keys:
-        ...     print key.serial, key.secret
+        ...     print('%s %s' % (key.serial, str(key.secret.decode())))
         987654321 12345678901234567890
         
-        The module should be able to handle most common PSKC files. Checking embedded
-        signatures, asymmetric keys and writing files are on the wishlist (patches
-        welcome).
+        The module should be able to handle most common PSKC files.
         
+Keywords: PSKC,RFC 6030,key container
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
 Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Information Technology
 Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
 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: Topic :: Security :: Cryptography
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Text Processing :: Markup :: XML
diff --git a/README b/README
index 5573c77..7dd7ea0 100644
--- a/README
+++ b/README
@@ -8,8 +8,7 @@ types of crypto modules. The format is commonly used for one-time password
 tokens or other authentication devices.
 
 The goal of this module is mainly to provide parsing of PSKC files in order
-to extract secret keys for use in an OTP authentication system. At a later
-time support for writing files may be added.
+to extract secret keys for use in an OTP authentication system.
 
 http://arthurdejong.org/python-pskc/
 
@@ -20,7 +19,7 @@ API
 The module provides a straightforward API that is mostly geared towards
 parsing existing PSKC files.
 
-Extracting key matarial from PSKC files is as simple as.
+Extracting key matarial from encrypted PSKC files is as simple as.
 
 >>> from pskc import PSKC
 >>> pskc = PSKC('tests/rfc6030-figure7.pskcxml')
@@ -45,7 +44,7 @@ private key material.
 Copyright
 ---------
 
-Copyright (C) 2014 Arthur de Jong
+Copyright (C) 2014-2015 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
diff --git a/docs/conf.py b/docs/conf.py
index 0ab5e14..268d158 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -46,7 +46,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'python-pskc'
-copyright = u'2014, Arthur de Jong'
+copyright = u'2014-2015 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
diff --git a/docs/encryption.rst b/docs/encryption.rst
index e0c8ca0..8b0ed2f 100644
--- a/docs/encryption.rst
+++ b/docs/encryption.rst
@@ -8,26 +8,30 @@ pre-shared keys, passphrase-based keys or asymmetric keys (asymmetric keys
 are currently unimplemented).
 
 Embedded PSKC encryption is handled inside the :class:`Encryption` class that
-defines encryption key and means of deriving keys. It is accessed from the
+defines encryption key or means of deriving keys. It is accessed from the
 :attr:`~pskc.PSKC.encryption` attribute of a :class:`~pskc.PSKC` instance::
 
+   >>> rom binascii import a2b_hex
    >>> from pskc import PSKC
    >>> pskc = PSKC('somefile.pskcxml')
-   >>> pskc.encryption.key = '12345678901234567890123456789012'.decode('hex')
+   >>> pskc.encryption.key = a2b_hex('12345678901234567890123456789012')
 
 or::
 
    >>> pskc.encryption.derive_key('qwerty')
 
-Once the encryption key has been set up any encrypted key values from the
+Once the encryption key has been set up, any encrypted key values from the
 PSKC file are available transparently.
 
-If an incorrect key has been set up, only upon accessing encrypted
+If an incorrect key has been set up, upon accessing encrypted
 information (e.g. the :attr:`~pskc.key.Key.secret` attribute of a
 :class:`~pskc.key.Key` instance) a :exc:`~pskc.exceptions.DecryptionError`
 exception will be raised.
 
 
+The Encryption class
+--------------------
+
 .. class:: Encryption
 
    .. attribute:: id
diff --git a/docs/exceptions.rst b/docs/exceptions.rst
index bf1414f..fbd8e7f 100644
--- a/docs/exceptions.rst
+++ b/docs/exceptions.rst
@@ -22,9 +22,9 @@ Exceptions
 
 .. exception:: DecryptionError
 
-   Raised when decrypting the embedded encrypted value fails due to missing
-   or incorrect key, unsupported decryption or MAC algorithm, failed message
-   authentication check or other error.
+   Raised when decrypting a value fails due to missing or incorrect key,
+   unsupported decryption or MAC algorithm, failed message authentication
+   check or other error.
 
    This exception is generally raised when accessing encrypted information
    (i.e. the :attr:`~pskc.key.Key.secret`, :attr:`~pskc.key.Key.counter`,
diff --git a/docs/mac.rst b/docs/mac.rst
index 6e50626..4847071 100644
--- a/docs/mac.rst
+++ b/docs/mac.rst
@@ -7,6 +7,23 @@ The PSKC format allows for `message authentication and integrity checking
 <https://tools.ietf.org/html/rfc6030#section-6.1.1>`_ for some of the values
 stored within the PSKC file.
 
+Integrity checking is done transparently when accessing attributes that
+are encrypted and contain a ValueMAC.
+
+Once the PSKC encryption key has been set up, key values can be explicitly
+checked using the :func:`~pskc.key.Key.check` method::
+
+   >>> pskc = PSKC('somefile.pskcxml')
+   >>> pskc.encryption.derive_key('qwerty')
+   >>> pskc.mac.algorithm
+   'http://www.w3.org/2000/09/xmldsig#hmac-sha1'
+   >>> all(key.check() for key in pskc.keys)
+   True
+
+
+The MAC class
+-------------
+
 .. class:: MAC
 
    .. attribute:: algorithm
@@ -21,14 +38,3 @@ stored within the PSKC file.
       MAC key is generated specifically for each PSKC file and encrypted with
       the PSKC encryption key, so the PSKC file should be decrypted first
       (see :doc:`encryption`).
-
-
-Once the PSKC encryption key has been set up key values can be explicitly
-checked using the :func:`~pskc.key.Key.check` method::
-
-   >>> pskc = PSKC('somefile.pskcxml')
-   >>> pskc.encryption.derive_key('qwerty')
-   >>> pskc.mac.algorithm
-   'http://www.w3.org/2000/09/xmldsig#hmac-sha1'
-   >>> all(key.check() for key in pskc.keys)
-   True
diff --git a/docs/policy.rst b/docs/policy.rst
index 91c51e2..97f9250 100644
--- a/docs/policy.rst
+++ b/docs/policy.rst
@@ -3,7 +3,8 @@ Key usage policy
 
 .. module:: pskc.policy
 
-The PSKC format allows for specifying `key and pin usage policy <https://tools.ietf.org/html/rfc6030#section-5>`__.
+The PSKC format allows for specifying `key and pin usage policy <https://tools.ietf.org/html/rfc6030#section-5>`__
+per key.
 
 Instances of the :class:`Policy` class provide attributes that describe
 limits that are placed on key usage and requirements for key PIN protection::
@@ -13,6 +14,9 @@ limits that are placed on key usage and requirements for key PIN protection::
    True
 
 
+The Policy class
+----------------
+
 .. class:: Policy
 
    .. attribute:: start_date
@@ -38,13 +42,12 @@ limits that are placed on key usage and requirements for key PIN protection::
       A list of `valid usage scenarios
       <https://www.iana.org/assignments/pskc/#key-usage>`__ for the
       key that the recipient should check against the intended usage of the
-      key. Also see :func:`may_use` and :ref:`the list of key usage constants
-      below <key-use-constants>`.
+      key. Also see :func:`may_use` and :ref:`key-use-constants` below.
 
    .. attribute:: pin_key_id
 
-      The unique `id` value used to reference the key within the PSKC file
-      that contains the value of the PIN that protects this key.
+      The unique `id` of the key within the PSKC file that contains the value
+      of the PIN that protects this key.
 
    .. attribute:: pin_key
 
@@ -58,8 +61,8 @@ limits that are placed on key usage and requirements for key PIN protection::
 
    .. attribute:: pin_usage
 
-      Describe how the PIN is used during the usage of the key. See :ref:`the
-      list of pin usage constants below <pin-use-constants>`.
+      Describe how the PIN is used during the usage of the key. See
+      :ref:`pin-use-constants` below.
 
    .. attribute:: pin_max_failed_attemtps
 
@@ -92,10 +95,14 @@ limits that are placed on key usage and requirements for key PIN protection::
    .. function:: may_use(usage)
 
       Check whether the key may be used for the provided purpose. See
-      :ref:`the list of key usage constants below <key-use-constants>`.
+      :ref:`key-use-constants` below.
+
 
 .. _key-use-constants:
 
+Key usage constants
+-------------------
+
 The :class:`Policy` class provides the following key use constants (see
 :attr:`~Policy.key_usage` and :func:`~Policy.may_use`):
 
@@ -149,8 +156,12 @@ The :class:`Policy` class provides the following key use constants (see
       The key is used to generate a new key based on a random number and the
       previous value of the key.
 
+
 .. _pin-use-constants:
 
+Pin usage constants
+-------------------
+
 The following constants for PIN use are defined  in the :class:`Policy`
 class (see :attr:`~Policy.pin_usage`):
 
diff --git a/docs/usage.rst b/docs/usage.rst
index acbd60e..7a9cdcb 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -10,25 +10,74 @@ contain most of the useful information from the PSKC file.
 Opening a PSKC file
 -------------------
 
-.. module:: pskc
-
-Importing data from a PSKC file can be done by instantiating a
-:class:`~pskc.PSKC` class::
+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', manufacturer='Manufacturer')
+    >>> key.id
+    '456'
+    >>> key.secret = '987654321'
+    >>> key.algorithm = 'urn:ietf:params:xml:ns:keyprov:pskc:hotp'
+    >>> pskc.write('output.pskcxml')
+
+Writing the data in encrypted form in the PSKC file is not yet supported so
+currently opening an encrypted PSKC file, providing the encryption key and
+writing the file should result in the same file but with encryption removed.
+
+
+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 whole file is parsed in one go. Instances of this class provide the
-   following attributes: If parsing the PSKC file fails, a
-   :exc:`~pskc.exceptions.ParseError` exception is raised.
+   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
 
@@ -49,42 +98,35 @@ Importing data from a PSKC file can be done by instantiating a
    .. attribute:: encryption
 
       :class:`~pskc.encryption.Encryption` instance that handles PSKC file
-      encryption.
+      encryption. See :doc:`encryption` for more information.
 
    .. attribute:: mac
 
-      :class:`~pskc.mac.MAC` instance that handles integrity checking.
+      :class:`~pskc.mac.MAC` instance for handling integrity checking.
+      See :doc:`mac` for more information.
 
 
-Examining keys
---------------
+   .. function:: add_key([**kwargs])
 
-.. module:: pskc.key
+      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.
 
-The :attr:`~pskc.PSKC.keys` attribute of a :class:`~pskc.PSKC` instance
-provides access to a list of keys contained in the PSKC file. :class:`Key`
-instances provide access to a number of attributes that provide information
-on the transmitted keys::
+   .. function:: write(filename)
 
-    >>> pskc = PSKC('somefile.pskcxml')
-    >>> first_key = pskc.keys[0]
-    >>> first_key.id
-    'some-id'
-    >>> first_key.algorithm
-    'urn:ietf:params:xml:ns:keyprov:pskc:hotp'
-    >>> first_key.secret
-    'SOME_SECRET_VALUE'
+      Write the PSKC object to the provided file. The `filename` argument can
+      be either the name of a file or a file-like object.
 
-Attribute values will be ``None`` if it the value is not present in the PSKC
-file. If any of 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`
-values are accessed while they are encrypted and decryption is unsuccessful a
-:exc:`~pskc.exceptions.DecryptionError` exception is raised.
 
+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
@@ -97,15 +139,18 @@ values are accessed while they are encrypted and decryption is unsuccessful a
       associates specific semantics to the key. Some `known profiles
       <https://www.iana.org/assignments/pskc/#alg-profiles>`__ are:
 
-      * ``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`` or
-        ``urn:ietf:params:xml:ns:keyprov:pskc:totp``:
-        `OATH time-based OTP <http://tools.ietf.org/html/draft-hoyer-keyprov-pskc-algorithm-profiles-01#section-4>`_
-      * ``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>`_
+      +------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
+      | 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 <http://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
 
@@ -116,28 +161,28 @@ values are accessed while they are encrypted and decryption is unsuccessful a
 
    .. attribute:: counter
 
-      The event counter for event-based OTP algorithms. Will also be
+      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 offset 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
+      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 for time-based OTP algorithms (usually
-      ``30`` or ``60``). Will also be transparently decrypted and may also
-      raise :exc:`~pskc.exceptions.DecryptionError`.
+      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. Will also be transparently decrypted and may also
-      raise :exc:`~pskc.exceptions.DecryptionError`.
+      number of intervals (integer). Will also be transparently decrypted and
+      may also raise :exc:`~pskc.exceptions.DecryptionError`.
 
    .. attribute:: issuer
 
@@ -186,7 +231,7 @@ values are accessed while they are encrypted and decryption is unsuccessful a
 
    .. attribute:: model
 
-      A manufacturer specific description of the model of the device.
+      A manufacturer-specific description of the model of the device.
 
    .. attribute:: issue_no
 
@@ -223,8 +268,8 @@ values are accessed while they are encrypted and decryption is unsuccessful a
 
    .. attribute:: algorithm_suite
 
-      Additional algorithm specific characteristics. For example, in an
-      HMAC-based algorithm it could designate the hash algorithm used (SHA1
+      Additional algorithm-specific characteristics. For example, in an
+      HMAC-based algorithm it could specify the hash algorithm used (SHA1
       or SHA256).
 
    .. attribute:: challenge_encoding
@@ -249,7 +294,7 @@ values are accessed while they are encrypted and decryption is unsuccessful a
    .. attribute:: challenge_check
 
       Boolean that indicates whether the device will check an embedded
-      `Luhn check digit <http://arthurdejong.org/python-stdnum/doc/0.9/stdnum.luhn.html>`_
+      `Luhn check digit <http://arthurdejong.org/python-stdnum/doc/stdnum.luhn.html>`_
       contained in the challenge.
 
    .. attribute:: response_encoding
@@ -264,7 +309,7 @@ values are accessed while they are encrypted and decryption is unsuccessful a
    .. attribute:: response_check
 
       Boolean that indicates whether the device will append a
-      `Luhn check digit <http://arthurdejong.org/python-stdnum/doc/0.9/stdnum.luhn.html>`_
+      `Luhn check digit <http://arthurdejong.org/python-stdnum/doc/stdnum.luhn.html>`_
       to the response.
 
    .. attribute:: policy
diff --git a/pskc/__init__.py b/pskc/__init__.py
index 61fa9fe..685843b 100644
--- a/pskc/__init__.py
+++ b/pskc/__init__.py
@@ -1,7 +1,7 @@
 # __init__.py - main module
 # coding: utf-8
 #
-# Copyright (C) 2014 Arthur de Jong
+# Copyright (C) 2014-2015 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
@@ -34,12 +34,10 @@ The following prints all keys, decrypting using a password:
 >>> pskc = PSKC('tests/rfc6030-figure7.pskcxml')
 >>> pskc.encryption.derive_key('qwerty')
 >>> for key in pskc.keys:
-...     print key.serial, key.secret
+...     print('%s %s' % (key.serial, str(key.secret.decode())))
 987654321 12345678901234567890
 
-The module should be able to handle most common PSKC files. Checking embedded
-signatures, asymmetric keys and writing files are on the wishlist (patches
-welcome).
+The module should be able to handle most common PSKC files.
 """
 
 
@@ -47,7 +45,7 @@ __all__ = ['PSKC', '__version__']
 
 
 # the version number of the library
-__version__ = '0.2'
+__version__ = '0.3'
 
 
 class PSKC(object):
@@ -72,9 +70,9 @@ class PSKC(object):
         self.mac = MAC(self)
         self.keys = []
         if filename is not None:
-            from pskc.parse import etree
+            from pskc.xml import parse
             try:
-                tree = etree.parse(filename)
+                tree = parse(filename)
             except Exception:
                 raise ParseError('Error parsing XML')
             self.parse(tree.getroot())
@@ -85,7 +83,7 @@ class PSKC(object):
         """Read information from the provided <KeyContainer> tree."""
         from pskc.exceptions import ParseError
         from pskc.key import Key
-        from pskc.parse import find, findall
+        from pskc.xml import find, findall
         if not container.tag.endswith('KeyContainer'):
             raise ParseError('Missing KeyContainer')
         # the version of the PSKC schema
@@ -102,6 +100,14 @@ class PSKC(object):
         for key_package in findall(container, 'pskc: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)
+        for key in self.keys:
+            key.make_xml(container)
+        return container
+
     def add_key(self, **kwargs):
         """Create a new key instance for the PSKC file.
 
@@ -116,3 +122,12 @@ class PSKC(object):
                 raise AttributeError()
             setattr(key, k, v)
         return key
+
+    def write(self, filename):
+        """Write the PSKC file to the provided file."""
+        from pskc.xml import tostring
+        if hasattr(filename, 'write'):
+            filename.write(tostring(self.make_xml()))
+        else:
+            with open(filename, 'wb') as output:
+                self.write(output)
diff --git a/pskc/crypto/__init__.py b/pskc/crypto/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pskc/aeskw.py b/pskc/crypto/aeskw.py
similarity index 88%
rename from pskc/aeskw.py
rename to pskc/crypto/aeskw.py
index 24e90b0..eeafed1 100644
--- a/pskc/aeskw.py
+++ b/pskc/crypto/aeskw.py
@@ -1,7 +1,7 @@
 # aeskw.py - implementation of AES key wrapping
 # coding: utf-8
 #
-# Copyright (C) 2014 Arthur de Jong
+# Copyright (C) 2014-2015 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
@@ -20,6 +20,8 @@
 
 """Implement key wrapping as described in RFC 3394 and RFC 5649."""
 
+import binascii
+
 from Crypto.Cipher import AES
 from Crypto.Util.number import bytes_to_long, long_to_bytes
 from Crypto.Util.strxor import strxor
@@ -31,8 +33,8 @@ def _split(value):
     return value[:8], value[8:]
 
 
-RFC3394_IV = 'a6a6a6a6a6a6a6a6'.decode('hex')
-RFC5649_IV = 'a65959a6'.decode('hex')
+RFC3394_IV = binascii.a2b_hex('a6a6a6a6a6a6a6a6')
+RFC5649_IV = binascii.a2b_hex('a65959a6')
 
 
 def wrap(plaintext, key, iv=None, pad=None):
@@ -54,7 +56,7 @@ def wrap(plaintext, key, iv=None, pad=None):
         raise EncryptionError('Plaintext length wrong')
     if mli % 8 != 0 and pad is not False:
         r = (mli + 7) // 8
-        plaintext += ((r * 8) - mli) * '\0'
+        plaintext += ((r * 8) - mli) * b'\0'
 
     if iv is None:
         if len(plaintext) != mli or pad is True:
@@ -63,7 +65,7 @@ def wrap(plaintext, key, iv=None, pad=None):
             iv = RFC3394_IV
 
     encrypt = AES.new(key).encrypt
-    n = len(plaintext) / 8
+    n = len(plaintext) // 8
 
     if n == 1:
         # RFC 5649 shortcut
@@ -76,7 +78,7 @@ def wrap(plaintext, key, iv=None, pad=None):
         for i in range(n):
             A, R[i] = _split(encrypt(A + R[i]))
             A = strxor(A, long_to_bytes(n * j + i + 1, 8))
-    return A + ''.join(R)
+    return A + b''.join(R)
 
 
 def unwrap(ciphertext, key, iv=None, pad=None):
@@ -95,7 +97,7 @@ def unwrap(ciphertext, key, iv=None, pad=None):
         raise DecryptionError('Ciphertext length wrong')
 
     decrypt = AES.new(key).decrypt
-    n = len(ciphertext) / 8 - 1
+    n = len(ciphertext) // 8 - 1
 
     if n == 1:
         A, plaintext = _split(decrypt(ciphertext))
@@ -107,16 +109,16 @@ def unwrap(ciphertext, key, iv=None, pad=None):
             for i in reversed(range(n)):
                 A = strxor(A, long_to_bytes(n * j + i + 1, 8))
                 A, R[i] = _split(decrypt(A + R[i]))
-        plaintext = ''.join(R)
+        plaintext = b''.join(R)
 
     if iv is None:
         if A == RFC3394_IV and pad is not True:
             return plaintext
         elif A[:4] == RFC5649_IV and pad is not False:
             mli = bytes_to_long(A[4:])
-            # check padding length is valid and only contains zeros
+            # check padding length is valid and plaintext only contains zeros
             if 8 * (n - 1) < mli <= 8 * n and \
-               all(x == '\0' for x in plaintext[mli:]):
+               plaintext.endswith((len(plaintext) - mli) * b'\0'):
                 return plaintext[:mli]
     elif A == iv:
         return plaintext
diff --git a/pskc/tripledeskw.py b/pskc/crypto/tripledeskw.py
similarity index 92%
rename from pskc/tripledeskw.py
rename to pskc/crypto/tripledeskw.py
index 47c93f1..a135ebd 100644
--- a/pskc/tripledeskw.py
+++ b/pskc/crypto/tripledeskw.py
@@ -1,7 +1,7 @@
 # tripledeskw.py - implementation of Triple DES key wrapping
 # coding: utf-8
 #
-# Copyright (C) 2014 Arthur de Jong
+# Copyright (C) 2014-2015 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
@@ -20,6 +20,8 @@
 
 """Implement Triple DES key wrapping as described in RFC 3217."""
 
+import binascii
+
 from Crypto import Random
 from Crypto.Cipher import DES3
 from Crypto.Hash import SHA
@@ -32,7 +34,7 @@ def _cms_hash(value):
     return SHA.new(value).digest()[:8]
 
 
-RFC3217_IV = '4adda22c79e82105'.decode('hex')
+RFC3217_IV = binascii.a2b_hex('4adda22c79e82105')
 
 
 def wrap(plaintext, key, iv=None):
@@ -48,7 +50,7 @@ def wrap(plaintext, key, iv=None):
     cipher = DES3.new(key, DES3.MODE_CBC, iv)
     tmp = iv + cipher.encrypt(plaintext + _cms_hash(plaintext))
     cipher = DES3.new(key, DES3.MODE_CBC, RFC3217_IV)
-    return cipher.encrypt(''.join(reversed(tmp)))
+    return cipher.encrypt(tmp[::-1])
 
 
 def unwrap(ciphertext, key):
@@ -59,7 +61,7 @@ def unwrap(ciphertext, key):
     if len(ciphertext) % DES3.block_size != 0:
         raise DecryptionError('Ciphertext length wrong')
     cipher = DES3.new(key, DES3.MODE_CBC, RFC3217_IV)
-    tmp = ''.join(reversed(cipher.decrypt(ciphertext)))
+    tmp = cipher.decrypt(ciphertext)[::-1]
     cipher = DES3.new(key, DES3.MODE_CBC, tmp[:8])
     tmp = cipher.decrypt(tmp[8:])
     if tmp[-8:] == _cms_hash(tmp[:-8]):
diff --git a/pskc/encryption.py b/pskc/encryption.py
index b57053c..4911662 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -1,7 +1,7 @@
 # encryption.py - module for handling encrypted values
 # coding: utf-8
 #
-# Copyright (C) 2014 Arthur de Jong
+# Copyright (C) 2014-2015 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
@@ -30,7 +30,7 @@ The encryption key can be derived using the KeyDerivation class.
 
 def unpad(value):
     """Remove padding from the plaintext."""
-    return value[0:-ord(value[-1])]
+    return value[0:-ord(value[-1:])]
 
 
 class EncryptedValue(object):
@@ -51,7 +51,7 @@ class EncryptedValue(object):
 
     def parse(self, encrypted_value):
         """Read encrypted data from the <EncryptedValue> XML tree."""
-        from pskc.parse import find, findbin
+        from pskc.xml import find, findbin
         if encrypted_value is None:
             return
         encryption_method = find(encrypted_value, 'xenc:EncryptionMethod')
@@ -92,14 +92,14 @@ class EncryptedValue(object):
         elif self.algorithm.endswith('#kw-aes128') or \
                 self.algorithm.endswith('#kw-aes192') or \
                 self.algorithm.endswith('#kw-aes256'):
-            from pskc.aeskw import unwrap
+            from pskc.crypto.aeskw import unwrap
             from Crypto.Cipher import AES
             if len(key) * 8 != int(self.algorithm[-3:]) or \
                len(key) not in AES.key_size:
                 raise DecryptionError('Invalid key length')
             return unwrap(self.cipher_value, key)
         elif self.algorithm.endswith('#kw-tripledes'):
-            from pskc.tripledeskw import unwrap
+            from pskc.crypto.tripledeskw import unwrap
... 1790 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-pskc.git



More information about the Python-modules-commits mailing list