lists.arthurdejong.org
RSS feed

python-pskc branch master updated. 96b4b54546a33b580b4c367f26d02955782b451d

[Date Prev][Date Next] [Thread Prev][Thread Next]

python-pskc branch master updated. 96b4b54546a33b580b4c367f26d02955782b451d



This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-pskc".

The branch, master has been updated
       via  96b4b54546a33b580b4c367f26d02955782b451d (commit)
       via  d662cf279e60d94aa6885efc296e76785ae66570 (commit)
       via  550630d2d38f494d3e2b3f9ea7247e072088c885 (commit)
       via  bf8e7f69fa329d073e8c91037d41f8ac0ca3fb16 (commit)
      from  9803dfca834770800e32b3c688b8b47da8443be2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://arthurdejong.org/git/python-pskc/commit/?id=96b4b54546a33b580b4c367f26d02955782b451d

commit 96b4b54546a33b580b4c367f26d02955782b451d
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Mon Apr 7 21:09:24 2014 +0200

    Add test for example from RFC6030
    
    This tests Figure 2 from RFC6030 with a very basic plain text secret
    key.

diff --git a/tests/rfc6030-figure2.pskc b/tests/rfc6030-figure2.pskc
new file mode 100644
index 0000000..40cefa5
--- /dev/null
+++ b/tests/rfc6030-figure2.pskc
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Basic PSKC Key Container example from RFC6030 (Figure 2).
+-->
+
+<KeyContainer Version="1.0"
+    Id="exampleID1"
+    xmlns="urn:ietf:params:xml:ns:keyprov:pskc">
+    <KeyPackage>
+        <Key Id="12345678"
+            Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:hotp">
+            <Issuer>Issuer-A</Issuer>
+            <Data>
+                <Secret>
+                    <PlainValue>MTIzNA==
+                    </PlainValue>
+                </Secret>
+            </Data>
+        </Key>
+    </KeyPackage>
+</KeyContainer>
diff --git a/tests/test-rfc6030.doctest b/tests/test-rfc6030.doctest
new file mode 100644
index 0000000..59d9829
--- /dev/null
+++ b/tests/test-rfc6030.doctest
@@ -0,0 +1,38 @@
+test_rfc6030.doctest - test for examples from RFC6030
+
+Copyright (C) 2014 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
+
+
+>>> from pskc import PSKC
+
+
+This tests Figure 2 from RFC6030. It is a basic key container example with
+a simple plain text secret key.
+
+>>> pskc = PSKC('tests/rfc6030-figure2.pskc')
+>>> [key.secret for key in pskc.keys]
+['1234']
+>>> key = pskc.keys[0]
+>>> key.id
+'12345678'
+>>> key.algorithm
+'urn:ietf:params:xml:ns:keyprov:pskc:hotp'
+>>> key.issuer
+'Issuer-A'
+>>> key.secret
+'1234'

http://arthurdejong.org/git/python-pskc/commit/?id=d662cf279e60d94aa6885efc296e76785ae66570

commit d662cf279e60d94aa6885efc296e76785ae66570
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Mon Apr 7 21:20:44 2014 +0200

    Support getting plaintext key

diff --git a/pskc/parse.py b/pskc/parse.py
index 7337f0a..f64ad14 100644
--- a/pskc/parse.py
+++ b/pskc/parse.py
@@ -43,6 +43,41 @@ def g_e_v(element, match):
         return value.text.strip()
 
 
+class DataType(object):
+
+    def __init__(self, element, t=str):
+        self.element = element
+        self.t = t
+
+    @property
+    def plain_value(self):
+        if self.element is None:
+            return
+        plain_value = self.element.find('pskc:PlainValue', 
namespaces=namespaces)
+        if plain_value is not None:
+            return plain_value.text.strip()
+
+
+class BinaryDataType(DataType):
+
+    @property
+    def value(self):
+        plain_value = self.plain_value
+        if plain_value:
+            return base64.b64decode(plain_value)
+        # TODO: else: see if EncryptedValue is present and decode
+
+
+class IntegerDataType(DataType):
+
+    @property
+    def value(self):
+        plain_value = self.plain_value
+        if plain_value:
+            return int(plain_value)
+        # TODO: else: see if EncryptedValue is present and decode
+
+
 class Key(object):
 
     def __init__(self, key_package):
@@ -67,6 +102,29 @@ class Key(object):
             self.algorithm = key.attrib.get('Algorithm')
 
         self.issuer = g_e_v(key_package, 'pskc:Key/pskc:Issuer')
+        self.secret = None
+        self.counter = None
+        self.time_offset = None
+        self.time_interval = None
+        self.time_drift = None
+
+        data = key_package.find('pskc:Key/pskc:Data', namespaces=namespaces)
+        if data is not None:
+            # the secret key itself
+            secret = BinaryDataType(data.find('pskc:Secret', 
namespaces=namespaces))
+            self.secret = secret.value
+            # event counter for event-based OTP
+            counter = IntegerDataType(data.find('pskc:Counter', 
namespaces=namespaces))
+            self.counter = counter.value
+            # time offset for time-based OTP (number of intervals)
+            time_offset = IntegerDataType(data.find('pskc:Time', 
namespaces=namespaces))
+            self.time_offset = time_offset.value
+            # time interval in seconds
+            time_interval = IntegerDataType(data.find('pskc:TimeInterval', 
namespaces=namespaces))
+            self.time_interval = time_interval.value
+            # device clock drift value (number of time intervals)
+            time_drift = IntegerDataType(data.find('pskc:TimeDrift', 
namespaces=namespaces))
+            self.time_drift = time_drift
 
 
 class PSKC(object):

http://arthurdejong.org/git/python-pskc/commit/?id=550630d2d38f494d3e2b3f9ea7247e072088c885

commit 550630d2d38f494d3e2b3f9ea7247e072088c885
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Mon Apr 7 21:05:21 2014 +0200

    Minimal test
    
    This adds a doctest for the absolute minimum PSKC file that does not
    contain any useful information.

diff --git a/tests/test_minimal.doctest b/tests/test_minimal.doctest
new file mode 100644
index 0000000..358bc0e
--- /dev/null
+++ b/tests/test_minimal.doctest
@@ -0,0 +1,35 @@
+test_minimal.doctest - very basic test of pskc module
+
+Copyright (C) 2014 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
+
+
+>>> from pskc import PSKC
+
+
+This tests the most minimal valid PSKC file with one empty key.
+
+>>> import StringIO
+>>> minimal_pskc = StringIO.StringIO('''
+... <?xml version="1.0"?>
+... <KeyContainer xmlns="urn:ietf:params:xml:ns:keyprov:pskc" Version="1.0">
+...   <KeyPackage/>
+... </KeyContainer>
+... '''.strip())
+>>> pskc = PSKC(minimal_pskc)
+>>> [key.id for key in pskc.keys]
+[None]

http://arthurdejong.org/git/python-pskc/commit/?id=bf8e7f69fa329d073e8c91037d41f8ac0ca3fb16

commit bf8e7f69fa329d073e8c91037d41f8ac0ca3fb16
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Mon Apr 7 21:03:46 2014 +0200

    Basic implementation of PSKC class
    
    This class is used for handling PSKC files. It will parse the file and
    store relevant properties for easy access. The Key class corresponds to
    a single key defined in the PSKC file.
    
    This is a very minimal implementation that only provides some meta-data
    from the file and keys (work in progress).

diff --git a/pskc/__init__.py b/pskc/__init__.py
index 07080db..edc0977 100644
--- a/pskc/__init__.py
+++ b/pskc/__init__.py
@@ -24,5 +24,11 @@ TBD: more documentation
 """
 
 
+from pskc.parse import PSKC
+
+
+__all__ = ['PSKC', '__version__']
+
+
 # the version number of the library
 __version__ = '0.1'
diff --git a/pskc/parse.py b/pskc/parse.py
new file mode 100644
index 0000000..7337f0a
--- /dev/null
+++ b/pskc/parse.py
@@ -0,0 +1,84 @@
+# parse.py - module for reading PSKC files
+# coding: utf-8
+#
+# Copyright (C) 2014 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
+
+from xml.etree import ElementTree
+import base64
+
+
+# the relevant XML namespaces for PSKC
+namespaces = dict(
+    # the XML namespace URI for version 1.0 of PSKC
+    pskc='urn:ietf:params:xml:ns:keyprov:pskc',
+    # the XML Signature namespace
+    ds='http://www.w3.org/2000/09/xmldsig#',
+    # the XML Encryption namespace
+    xenc='http://www.w3.org/2001/04/xmlenc#',
+    # the XML Encryption version 1.1 namespace
+    xenc11='http://www.w3.org/2009/xmlenc11#',
+    # the PKCS #5 namespace
+    pkcs5='http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#',
+)
+
+
+def g_e_v(element, match):
+    value = element.find(match, namespaces=namespaces)
+    if value is not None:
+        return value.text.strip()
+
+
+class Key(object):
+
+    def __init__(self, key_package):
+
+        self.manufacturer = g_e_v(key_package, 
'pskc:DeviceInfo/pskc:Manufacturer')
+        self.serial = g_e_v(key_package, 'pskc:DeviceInfo/pskc:SerialNo')
+        self.model = g_e_v(key_package, 'pskc:DeviceInfo/pskc:Model')
+        self.issue_no = g_e_v(key_package, 'pskc:DeviceInfo/pskc:IssueNo')
+        self.device_binding = g_e_v(key_package, 
'pskc:DeviceInfo/pskc:DeviceBinding')
+        self.start_date = g_e_v(key_package, 'pskc:DeviceInfo/pskc:StartDate')
+        # TODO: handle <StartDate> as datetime
+        self.expiry_date = g_e_v(key_package, 
'pskc:DeviceInfo/pskc:ExpiryDate')
+        # TODO: handle <ExpiryDate> as datetime
+        self.device_userid = g_e_v(key_package, 'pskc:DeviceInfo/pskc:UserId')
+
+        self.id = None
+        self.algorithm = None
+
+        key = key_package.find('pskc:Key', namespaces=namespaces)
+        if key is not None:
+            self.id = key.attrib.get('Id')
+            self.algorithm = key.attrib.get('Algorithm')
+
+        self.issuer = g_e_v(key_package, 'pskc:Key/pskc:Issuer')
+
+
+class PSKC(object):
+
+    def __init__(self, filename):
+        tree = ElementTree.parse(filename)
+        container = tree.getroot()
+        # the version of the PSKC schema
+        self.version = container.attrib.get('Version')
+        # unique identifier for the container
+        self.id = container.attrib.get('Id')
+        # handle KeyPackage entries
+        self.keys = []
+        for package in container.findall('pskc:KeyPackage', 
namespaces=namespaces):
+            self.keys.append(Key(package))

-----------------------------------------------------------------------

Summary of changes:
 pskc/__init__.py           |    6 ++
 pskc/parse.py              |  142 ++++++++++++++++++++++++++++++++++++++++++++
 tests/rfc6030-figure2.pskc |   22 +++++++
 tests/test-rfc6030.doctest |   38 ++++++++++++
 tests/test_minimal.doctest |   35 +++++++++++
 5 files changed, 243 insertions(+)
 create mode 100644 pskc/parse.py
 create mode 100644 tests/rfc6030-figure2.pskc
 create mode 100644 tests/test-rfc6030.doctest
 create mode 100644 tests/test_minimal.doctest


hooks/post-receive
-- 
python-pskc
-- 
To unsubscribe send an email to
python-pskc-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/python-pskc-commits/