lists.arthurdejong.org
RSS feed

python-pskc branch master updated. 0.4-33-g29a183d

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

python-pskc branch master updated. 0.4-33-g29a183d



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  29a183d37476279a81e43fa7c3d19bc6953e1ea5 (commit)
       via  02eb520efa1fa8c3c2c7c8bf6a2b6616fbd202b2 (commit)
       via  12dfa64a6783371542d0991ec46645d90190a5e1 (commit)
      from  a5e23430c1e96e773c087b5f9683f021954413d1 (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=29a183d37476279a81e43fa7c3d19bc6953e1ea5

commit 29a183d37476279a81e43fa7c3d19bc6953e1ea5
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Jan 15 23:31:20 2017 +0100

    Split vendor tests
    
    Have one doctest file per vendor to make tests a little more manageable.

diff --git a/tests/test_vendors.doctest b/tests/test_feitian.doctest
similarity index 75%
rename from tests/test_vendors.doctest
rename to tests/test_feitian.doctest
index 006338f..377de1b 100644
--- a/tests/test_vendors.doctest
+++ b/tests/test_feitian.doctest
@@ -1,4 +1,4 @@
-test_vendors.doctest - test for PSKC files provided by vendors
+test_feitian.doctest - tests for Feitian PSKC files
 
 Copyright (C) 2016 Arthur de Jong
 
@@ -76,29 +76,3 @@ datetime.datetime(2022, 9, 1, 0, 0, tzinfo=tzutc())
 datetime.datetime(2012, 9, 19, 0, 0, tzinfo=tzutc())
 >>> key.policy.expiry_date
 datetime.datetime(2022, 9, 1, 0, 0, tzinfo=tzutc())
-
-
-This tests a simple PSKC file from NagraID which is protected by a pre-shared
-key. The file contains three OCRA keys.
-
->>> pskc = PSKC('tests/nagraid/file1.pskcxml')
->>> print('\n'.join(key.serial for key in pskc.keys))  #doctest: +REPORT_UDIFF
-306EUO4-00960
-306EUO4-00954
-306EUO4-00958
->>> key = pskc.keys[0]
->>> bool(key.secret)  # doctest: +IGNORE_EXCEPTION_DETAIL
-Traceback (most recent call last):
-    ...
-DecryptionError: No key available
->>> pskc.encryption.key_name
-'Pre-shared-key'
->>> pskc.encryption.key = a2b_hex('4A057F6AB6FCB57AB5408E46A9835E68')
->>> bool(key.secret)
-True
->>> key.check()
-True
->>> print('\n'.join(key.algorithm_suite for key in pskc.keys))  #doctest: 
+REPORT_UDIFF
-OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1
-OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1
-OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1
diff --git a/tests/test_nagraid.doctest b/tests/test_nagraid.doctest
new file mode 100644
index 0000000..a36c74e
--- /dev/null
+++ b/tests/test_nagraid.doctest
@@ -0,0 +1,54 @@
+test_vendors.doctest - tests for NagraID PSKC files
+
+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
+
+
+>>> from binascii import a2b_hex, b2a_hex
+>>> def tostr(x):
+...     return str(x.decode())
+>>> def decode(f):
+...     return lambda x: tostr(f(x))
+>>> b2a_hex = decode(b2a_hex)
+
+>>> from pskc import PSKC
+
+
+This tests a simple PSKC file from NagraID which is protected by a pre-shared
+key. The file contains three OCRA keys.
+
+>>> pskc = PSKC('tests/nagraid/file1.pskcxml')
+>>> print('\n'.join(key.serial for key in pskc.keys))  #doctest: +REPORT_UDIFF
+306EUO4-00960
+306EUO4-00954
+306EUO4-00958
+>>> key = pskc.keys[0]
+>>> bool(key.secret)  # doctest: +IGNORE_EXCEPTION_DETAIL
+Traceback (most recent call last):
+    ...
+DecryptionError: No key available
+>>> pskc.encryption.key_name
+'Pre-shared-key'
+>>> pskc.encryption.key = a2b_hex('4A057F6AB6FCB57AB5408E46A9835E68')
+>>> bool(key.secret)
+True
+>>> key.check()
+True
+>>> print('\n'.join(key.algorithm_suite for key in pskc.keys))  #doctest: 
+REPORT_UDIFF
+OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1
+OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1
+OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1

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

commit 02eb520efa1fa8c3c2c7c8bf6a2b6616fbd202b2
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Jan 14 23:56:52 2017 +0100

    Add tests for Yubikey files
    
    This adds tests from draft-josefsson-keyprov-pskc-yubikey-00.

diff --git a/tests/test_yubico.doctest b/tests/test_yubico.doctest
new file mode 100644
index 0000000..d3ed4e5
--- /dev/null
+++ b/tests/test_yubico.doctest
@@ -0,0 +1,149 @@
+test_yubico.doctest - tests for Yubico PSKC files
+
+Copyright (C) 2017 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 binascii import a2b_hex, b2a_hex
+>>> def tostr(x):
+...     return str(x.decode())
+>>> def decode(f):
+...     return lambda x: tostr(f(x))
+>>> b2a_hex = decode(b2a_hex)
+
+>>> from pskc import PSKC
+
+
+This tests the first example from draft-josefsson-keyprov-pskc-yubikey-00.
+
+>>> pskc = PSKC('tests/yubico/example1.pskcxml')
+>>> pskc.id
+'yk-pskc-283599'
+>>> len(pskc.keys)
+1
+>>> key = pskc.keys[0]
+>>> key.manufacturer
+'oath.UB'
+>>> key.serial
+'283599'
+>>> key.start_date
+datetime.datetime(2009, 1, 22, 0, 25, 11, tzinfo=tzutc())
+>>> key.crypto_module
+'1'
+>>> key.id
+'283599:1'
+>>> key.algorithm
+'http://www.yubico.com/#yubikey-aes'
+>>> key.issuer
+'ACME Inc.'
+>>> key.response_encoding
+'ALPHANUMERIC'
+>>> key.response_length
+44
+>>> b2a_hex(key.secret)
+'2b7e151628aed2a6abf7158809cf4f3c'
+>>> key.key_userid
+'CN=ekhgjhbctrgn, UID=ca62baca62ba'
+
+
+This tests the second example from draft-josefsson-keyprov-pskc-yubikey-00.
+
+>>> pskc = PSKC('tests/yubico/example2.pskcxml')
+>>> pskc.id
+'yk-pskc-283598'
+>>> len(pskc.keys)
+2
+>>> key = pskc.keys[0]  # first key
+>>> key.manufacturer
+'oath.UB'
+>>> key.serial
+'283598'
+>>> key.start_date
+datetime.datetime(2009, 1, 22, 0, 25, 10, tzinfo=tzutc())
+>>> key.crypto_module
+'1'
+>>> key.id
+'283598:1'
+>>> key.algorithm
+'http://www.yubico.com/#yubikey-aes'
+>>> key.issuer
+'ACME Inc.'
+>>> key.response_encoding
+'ALPHANUMERIC'
+>>> key.response_length
+44
+>>> b2a_hex(key.secret)
+'5698356d30868c4201e26f66c582bb45'
+>>> key.key_userid
+'CN=ekhgjhbctrgn, UID=ca62baca62ba'
+>>> key = pskc.keys[1]  # second key
+>>> key.manufacturer
+'oath.UB'
+>>> key.serial
+'283598'
+>>> key.start_date
+datetime.datetime(2009, 1, 22, 0, 25, 10, tzinfo=tzutc())
+>>> key.crypto_module
+'2'
+>>> key.id
+'283598:2'
+>>> key.algorithm
+'http://www.yubico.com/#yubikey-aes'
+>>> key.issuer
+'ACME Inc.'
+>>> key.response_encoding
+'ALPHANUMERIC'
+>>> key.response_length
+44
+>>> b2a_hex(key.secret)
+'38892b82abf1807788458fc5a5165c80'
+>>> key.key_userid
+'CN=ekhgjhbctrgn, UID=ca62baca62ba'
+
+
+This tests the third example from draft-josefsson-keyprov-pskc-yubikey-00.
+
+>>> pskc = PSKC('tests/yubico/example3.pskcxml')
+>>> pskc.id
+'yk-pskc-283597'
+>>> len(pskc.keys)
+1
+>>> key = pskc.keys[0]
+>>> key.manufacturer
+'oath.UB'
+>>> key.serial
+'283597'
+>>> key.start_date
+datetime.datetime(2009, 1, 22, 0, 25, 9, tzinfo=tzutc())
+>>> key.crypto_module
+'1'
+>>> key.id
+'283597:1'
+>>> key.algorithm
+'http://www.yubico.com/#yubikey-aes'
+>>> key.issuer
+'ACME Inc.'
+>>> key.response_encoding
+'ALPHANUMERIC'
+>>> key.response_length
+40
+>>> b2a_hex(key.secret)
+'2b7e151628aed2a6abf7158809cf4f3c'
+>>> key.key_userid
+'CN=ekhgjhbctrgn, UID=ca62baca62ba'
+
+# TODO: support extensions
diff --git a/tests/yubico/example1.pskcxml b/tests/yubico/example1.pskcxml
new file mode 100644
index 0000000..2adb1be
--- /dev/null
+++ b/tests/yubico/example1.pskcxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  First example from draft-josefsson-keyprov-pskc-yubikey-00 illustrating how
+  slot 1 of the YubiKey with serial number 283599 is provisioned with public
+  identifier "ekhgjhbctrgn", internal identity "ca62baca62ba" and the
+  indicated encryption key.
+-->
+
+<KeyContainer Version="1.0"
+              Id="yk-pskc-283599"
+              xmlns="urn:ietf:params:xml:ns:keyprov:pskc">
+  <KeyPackage>
+    <DeviceInfo>
+      <Manufacturer>oath.UB</Manufacturer>
+      <SerialNo>283599</SerialNo>
+      <StartDate>2009-01-22T00:25:11Z</StartDate>
+    </DeviceInfo>
+    <CryptoModuleInfo>
+      <Id>1</Id>
+    </CryptoModuleInfo>
+    <Key Id="283599:1"
+         Algorithm="http://www.yubico.com/#yubikey-aes";>
+      <Issuer>ACME Inc.</Issuer>
+      <AlgorithmParameters>
+        <ResponseFormat Encoding="ALPHANUMERIC" Length="44"/>
+      </AlgorithmParameters>
+      <Data>
+        <Secret>
+          <PlainValue>
+            K34VFiiu0qar9xWICc9PPA==
+          </PlainValue>
+        </Secret>
+      </Data>
+      <UserId>CN=ekhgjhbctrgn, UID=ca62baca62ba</UserId>
+    </Key>
+  </KeyPackage>
+</KeyContainer>
diff --git a/tests/yubico/example2.pskcxml b/tests/yubico/example2.pskcxml
new file mode 100644
index 0000000..31c52bc
--- /dev/null
+++ b/tests/yubico/example2.pskcxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Second example from draft-josefsson-keyprov-pskc-yubikey-00 illustrating
+  how both slots can be programmed at the same time.
+-->
+
+<KeyContainer Version="1.0"
+              Id="yk-pskc-283598"
+              xmlns="urn:ietf:params:xml:ns:keyprov:pskc">
+  <KeyPackage>
+    <DeviceInfo>
+      <Manufacturer>oath.UB</Manufacturer>
+      <SerialNo>283598</SerialNo>
+      <StartDate>2009-01-22T00:25:10Z</StartDate>
+    </DeviceInfo>
+    <CryptoModuleInfo>
+      <Id>1</Id>
+    </CryptoModuleInfo>
+    <Key Id="283598:1"
+         Algorithm="http://www.yubico.com/#yubikey-aes";>
+      <Issuer>ACME Inc.</Issuer>
+      <AlgorithmParameters>
+        <ResponseFormat Encoding="ALPHANUMERIC" Length="44"/>
+      </AlgorithmParameters>
+      <Data>
+        <Secret>
+          <PlainValue>
+            Vpg1bTCGjEIB4m9mxYK7RQ==
+          </PlainValue>
+        </Secret>
+      </Data>
+      <UserId>CN=ekhgjhbctrgn, UID=ca62baca62ba</UserId>
+    </Key>
+  </KeyPackage>
+  <KeyPackage>
+    <DeviceInfo>
+      <Manufacturer>oath.UB</Manufacturer>
+      <SerialNo>283598</SerialNo>
+      <StartDate>2009-01-22T00:25:10Z</StartDate>
+    </DeviceInfo>
+    <CryptoModuleInfo>
+      <Id>2</Id>
+    </CryptoModuleInfo>
+    <Key Id="283598:2"
+         Algorithm="http://www.yubico.com/#yubikey-aes";>
+      <Issuer>ACME Inc.</Issuer>
+      <AlgorithmParameters>
+        <ResponseFormat Encoding="ALPHANUMERIC" Length="44"/>
+      </AlgorithmParameters>
+      <Data>
+        <Secret>
+          <PlainValue>
+            OIkrgqvxgHeIRY/FpRZcgA==
+          </PlainValue>
+        </Secret>
+      </Data>
+      <UserId>CN=ekhgjhbctrgn, UID=ca62baca62ba</UserId>
+    </Key>
+  </KeyPackage>
+</KeyContainer>
diff --git a/tests/yubico/example3.pskcxml b/tests/yubico/example3.pskcxml
new file mode 100644
index 0000000..646abf3
--- /dev/null
+++ b/tests/yubico/example3.pskcxml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Third example from draft-josefsson-keyprov-pskc-yubikey-00 illustrating how
+  additional parameters, locking code and unlocking code, can be provided
+  through an extension. Note that python-pskc does not expose these
+  extensions through its API.
+-->
+
+<KeyContainer Version="1.0"
+              Id="yk-pskc-283597"
+              xmlns="urn:ietf:params:xml:ns:keyprov:pskc">
+  <KeyPackage>
+    <DeviceInfo>
+      <Manufacturer>oath.UB</Manufacturer>
+      <SerialNo>283597</SerialNo>
+      <StartDate>2009-01-22T00:25:09Z</StartDate>
+    </DeviceInfo>
+    <CryptoModuleInfo>
+      <Id>1</Id>
+    </CryptoModuleInfo>
+    <Key Id="283597:1"
+         Algorithm="http://www.yubico.com/#yubikey-aes";>
+      <Issuer>ACME Inc.</Issuer>
+      <AlgorithmParameters>
+        <ResponseFormat Encoding="ALPHANUMERIC" Length="40"/>
+      </AlgorithmParameters>
+      <Data>
+        <Secret>
+          <PlainValue>
+            K34VFiiu0qar9xWICc9PPA==
+          </PlainValue>
+        </Secret>
+      </Data>
+      <UserId>CN=ekhgjhbctrgn, UID=ca62baca62ba</UserId>
+      <Extensions>
+        <YubiKey xmlns="http://www.yubico.com/#yubikey-aes-ext";>
+          <YubiKeyConfig Flag="TKTFLAG_APPEND_DELAY1"/>
+          <YubiKeyConfig Flag="TKTFLAG_APPEND_CR"/>
+          <YubiKeyConfig Flag="CFGFLAG_PACING_10MS"/>
+          <YubiKeyLock Code="98566d358630"/>
+          <YubiKeyUnlock Code="45bb428ce201"/>
+        </YubiKey>
+      </Extensions>
+    </Key>
+  </KeyPackage>
+</KeyContainer>

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

commit 12dfa64a6783371542d0991ec46645d90190a5e1
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri Jan 13 21:33:50 2017 +0100

    Support legacy ActivIdentity files
    
    This adds support for parsing ActivIdentity files that conform to a very
    old version of an Internet Draft. The implementation and test were based
    on a file provided by Jaap Ruijgrok.

diff --git a/pskc/parser.py b/pskc/parser.py
index 5ba014f..98359ca 100644
--- a/pskc/parser.py
+++ b/pskc/parser.py
@@ -52,9 +52,11 @@ class PSKCParser(object):
         pskc.id = (
             container.get('Id') or container.get('ID') or container.get('id'))
         # handle EncryptionKey entries
-        cls.parse_encryption(pskc.encryption, find(container, 'EncryptionKey'))
+        cls.parse_encryption(pskc.encryption, find(
+            container, 'EncryptionKey', 'EncryptionMethod'))
         # handle MACMethod entries
-        cls.parse_mac_method(pskc.mac, find(container, 'MACMethod'))
+        cls.parse_mac_method(pskc.mac, find(
+            container, 'MACMethod', 'DigestMethod'))
         # fall back to MACAlgorithm
         mac_algorithm = findtext(container, 'MACAlgorithm')
         if mac_algorithm:
@@ -69,10 +71,13 @@ class PSKCParser(object):
         if key_info is None:
             return
         encryption.id = key_info.get('Id')
+        encryption.algorithm = (
+            key_info.get('Algorithm') or encryption.algorithm)
         for name in findall(key_info,
                             'KeyName', 'DerivedKey/MasterKeyName',
                             'DerivedKey/CarriedKeyName'):
             encryption.key_names.append(findtext(name, '.'))
+        encryption.iv = findbin(key_info, 'IV') or encryption.iv
         cls.parse_key_derivation(encryption.derivation, find(
             key_info, 'DerivedKey/KeyDerivationMethod'))
 
@@ -112,15 +117,16 @@ class PSKCParser(object):
     def parse_key_package(cls, device, key_package):
         """Read key information from the provided <KeyPackage> tree."""
 
-        device.manufacturer = findtext(key_package, 'DeviceInfo/Manufacturer')
-        device.serial = findtext(key_package, 'DeviceInfo/SerialNo')
-        device.model = findtext(key_package, 'DeviceInfo/Model')
-        device.issue_no = findtext(key_package, 'DeviceInfo/IssueNo')
-        device.device_binding = findtext(
-            key_package, 'DeviceInfo/DeviceBinding')
-        device.start_date = findtime(key_package, 'DeviceInfo/StartDate')
-        device.expiry_date = findtime(key_package, 'DeviceInfo/ExpiryDate')
-        device.device_userid = findtext(key_package, 'DeviceInfo/UserId')
+        info = find(key_package, 'DeviceInfo', 'DeviceId')
+        if info is not None:
+            device.manufacturer = findtext(info, 'Manufacturer')
+            device.serial = findtext(info, 'SerialNo')
+            device.model = findtext(info, 'Model')
+            device.issue_no = findtext(info, 'IssueNo')
+            device.device_binding = findtext(info, 'DeviceBinding')
+            device.start_date = findtime(info, 'StartDate')
+            device.expiry_date = findtime(info, 'ExpiryDate')
+            device.device_userid = findtext(info, 'UserId')
 
         device.crypto_module = findtext(key_package, 'CryptoModuleInfo/Id')
 
@@ -142,6 +148,14 @@ class PSKCParser(object):
             cls.parse_datatype(key._time_interval, find(data, 'TimeInterval'))
             cls.parse_datatype(key._time_drift, find(data, 'TimeDrift'))
 
+        for data in findall(key_elm, 'Data'):
+            name = data.get('Name')
+            if name:
+                cls.parse_datatype(dict(
+                    secret=key._secret, counter=key._counter,
+                    time=key._time_offset, time_interval=key._time_interval
+                ).get(name.lower()), data)
+
         key.issuer = findtext(key_elm, 'Issuer')
         key.key_profile = findtext(key_elm, 'KeyProfileId')
         key.key_reference = findtext(key_elm, 'KeyReference')
@@ -225,9 +239,16 @@ class PSKCParser(object):
             if not dt.pskc.encryption.algorithm and dt.algorithm:
                 dt.pskc.encryption.algorithm = dt.algorithm
         # read MAC information from <ValueMAC>
-        value_mac = findbin(element, 'ValueMAC')
+        value_mac = findbin(element, 'ValueMAC', 'ValueDigest')
         if value_mac is not None:
             dt.value_mac = value_mac
+        # read legacy <Value> elements (can be plain or encrypted)
+        value = find(element, 'Value')
+        if value is not None:
+            if dt.pskc.encryption.algorithm and dt.value_mac:
+                dt.cipher_value = findbin(element, 'Value')
+            else:
+                dt.value = dt._from_text(findtext(element, 'Value'))
 
     @classmethod
     def parse_policy(cls, policy, policy_elm):
diff --git a/tests/actividentity/test.pskc b/tests/actividentity/test.pskc
new file mode 100644
index 0000000..63a324e
--- /dev/null
+++ b/tests/actividentity/test.pskc
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Test file provided by a customer of ActivIdentity. The file has been
+  modified to include only one token and all secret values have been modified
+  to not leak any actual data. Note that the MAC uses the same key as was
+  used for encryption and is over the plaintext.
+-->
+
+<KeyContainer xmlns="urn:ietf:params:xml:ns:keyprov:container:1.0" 
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="urn:ietf:params:xml:ns:keyprov:container:1.0:keyprov-pskc-1.0.xsd"
 version="1.0">
+<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc";>
+<IV>Xus0lsc+rJLi0nc/ANE0Xg==</IV>
+</EncryptionMethod>
+<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
+<Device>
+<DeviceId>
+<Manufacturer>ActivIdentity</Manufacturer>
+<SerialNo>0950380269</SerialNo>
+</DeviceId>
+<Key KeyAlgorithm="http://www.ietf.org/keyprov/pskc#hotp"; KeyId="0950380269">
+<Issuer>ActivIdentity</Issuer>
+<Usage OTP="true">
+<ResponseFormat Format="DECIMAL" Length="8"/>
+</Usage>
+<Data Name="SECRET">
+<Value>1HBJThmzYDCU7YCrML6OZKMsRQriSvZpoqeMfBui9dI=</Value>
+<ValueDigest>SlinEB9YUzcR04MUZDF5dBLtK1c=</ValueDigest>
+</Data>
+<Data Name="COUNTER">
+<Value>AAAAADHwRgM=</Value>
+</Data>
+</Key>
+</Device>
+</KeyContainer>
diff --git a/tests/test_actividentity.doctest b/tests/test_actividentity.doctest
new file mode 100644
index 0000000..734b028
--- /dev/null
+++ b/tests/test_actividentity.doctest
@@ -0,0 +1,62 @@
+test_actividentity.doctest - tests for ActivIdentity PSKC files
+
+Copyright (C) 2017 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 binascii import a2b_hex, b2a_hex
+>>> def tostr(x):
+...     return str(x.decode())
+>>> def decode(f):
+...     return lambda x: tostr(f(x))
+>>> b2a_hex = decode(b2a_hex)
+
+>>> from pskc import PSKC
+
+
+This tests an ActivIdentity PSKC file that was found in the wild. It does not
+follow the RFC 6030 spec but is handled nonetheless.
+
+>>> pskc = PSKC('tests/actividentity/test.pskc')
+>>> pskc.encryption.algorithm
+'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
+>>> b2a_hex(pskc.encryption.iv)
+'5eeb3496c73eac92e2d2773f00d1345e'
+>>> pskc.encryption.key = a2b_hex('fe0de6b806c09b762c4b49a666a27b72')
+>>> pskc.mac.algorithm
+'http://www.w3.org/2000/09/xmldsig#hmac-sha1'
+>>> key = pskc.keys[0]
+>>> key.manufacturer
+'ActivIdentity'
+>>> key.serial
+'0950380269'
+>>> key.algorithm
+'http://www.ietf.org/keyprov/pskc#hotp'
+>>> key.id
+'0950380269'
+>>> key.issuer
+'ActivIdentity'
+>>> key.policy.key_usage
+['OTP']
+>>> key.response_encoding
+'DECIMAL'
+>>> key.response_length
+8
+>>> b2a_hex(key.secret)
+'dce70c2a0c1f5806f316ca8d09456eb4765ad053'
+>>> key.counter
+837830147

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

Summary of changes:
 pskc/parser.py                                     |  45 +++++--
 tests/actividentity/test.pskc                      |  34 +++++
 tests/test_actividentity.doctest                   |  62 +++++++++
 .../{test_vendors.doctest => test_feitian.doctest} |  28 +---
 tests/test_nagraid.doctest                         |  54 ++++++++
 tests/test_yubico.doctest                          | 149 +++++++++++++++++++++
 tests/yubico/example1.pskcxml                      |  38 ++++++
 tests/yubico/example2.pskcxml                      |  61 +++++++++
 tests/yubico/example3.pskcxml                      |  47 +++++++
 9 files changed, 479 insertions(+), 39 deletions(-)
 create mode 100644 tests/actividentity/test.pskc
 create mode 100644 tests/test_actividentity.doctest
 rename tests/{test_vendors.doctest => test_feitian.doctest} (75%)
 create mode 100644 tests/test_nagraid.doctest
 create mode 100644 tests/test_yubico.doctest
 create mode 100644 tests/yubico/example1.pskcxml
 create mode 100644 tests/yubico/example2.pskcxml
 create mode 100644 tests/yubico/example3.pskcxml


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