lists.arthurdejong.org
RSS feed

python-pskc branch master updated. 0.1-10-gbef2f7d

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

python-pskc branch master updated. 0.1-10-gbef2f7d



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  bef2f7db8590004f5a4dd7cca75f995a545ab89a (commit)
       via  46f5749981e2937e376a3bc624fed76ef117ec0f (commit)
       via  83f5a4bf1405af90882b09685cf9136d05a70a02 (commit)
       via  820c83c3377adb7b4a5678338d50faed920bbf4a (commit)
       via  02bde47c9f9b0f4b57730b1bb30efafdbb807a33 (commit)
       via  b62fec85e080feaef3e7304f867e11e164b2f537 (commit)
       via  7bc2e6be6443fb35834c2f3908d1b3ee16147ece (commit)
       via  714f38744e1dd294e78cf1a6be7c6b520f3f3750 (commit)
       via  803d24c4e0483b825d4ca37ef786a778cff61bd4 (commit)
       via  8c37e26a826ab92b94a59eb974f9c8523e81517d (commit)
      from  8e1729e4fe4f058c8b28dbcad2bfa66c2e8b04ce (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=bef2f7db8590004f5a4dd7cca75f995a545ab89a

commit bef2f7db8590004f5a4dd7cca75f995a545ab89a
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 22:00:32 2014 +0200

    Add a function for adding a new key

diff --git a/pskc/__init__.py b/pskc/__init__.py
index 3a55cca..60a5e3b 100644
--- a/pskc/__init__.py
+++ b/pskc/__init__.py
@@ -106,3 +106,18 @@ class PSKC(object):
         for key_package in container.findall(
                 'pskc:KeyPackage', namespaces=namespaces):
             self.keys.append(Key(self, key_package))
+
+    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)
+        # 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
diff --git a/pskc/key.py b/pskc/key.py
index 80fbbc5..3a5de99 100644
--- a/pskc/key.py
+++ b/pskc/key.py
@@ -136,7 +136,7 @@ class Key(object):
       policy: reference to policy information (see Policy class)
     """
 
-    def __init__(self, pskc, key_package):
+    def __init__(self, pskc, key_package=None):
 
         self.pskc = pskc
 
diff --git a/tests/test_minimal.doctest b/tests/test_minimal.doctest
index 8987d8b..ef54e59 100644
--- a/tests/test_minimal.doctest
+++ b/tests/test_minimal.doctest
@@ -35,6 +35,15 @@ This tests the most minimal valid PSKC file with one empty 
key.
 [None]
 
 
-Check creation of empty PSKC structure.
+Check creation of empty PSKC structure and adding an empty key to the list.
 
 >>> pskc = PSKC()
+>>> key = pskc.add_key(id='123')
+>>> key.id
+'123'
+
+Adding a key with unknown attributes raises an error.
+>>> key = pskc.add_key(foo='bar')
+Traceback (most recent call last):
+    ...
+AttributeError

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

commit 46f5749981e2937e376a3bc624fed76ef117ec0f
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 21:57:48 2014 +0200

    Consistency improvement

diff --git a/pskc/__init__.py b/pskc/__init__.py
index 8c8fe39..3a55cca 100644
--- a/pskc/__init__.py
+++ b/pskc/__init__.py
@@ -103,6 +103,6 @@ class PSKC(object):
         self.mac.parse(container.find(
             'pskc:MACMethod', namespaces=namespaces))
         # handle KeyPackage entries
-        for package in container.findall(
+        for key_package in container.findall(
                 'pskc:KeyPackage', namespaces=namespaces):
-            self.keys.append(Key(self, package))
+            self.keys.append(Key(self, key_package))

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

commit 83f5a4bf1405af90882b09685cf9136d05a70a02
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 21:57:23 2014 +0200

    Support creating an empty PSKC instance

diff --git a/pskc/__init__.py b/pskc/__init__.py
index 491fda4..8c8fe39 100644
--- a/pskc/__init__.py
+++ b/pskc/__init__.py
@@ -64,7 +64,7 @@ class PSKC(object):
       keys: list of keys (Key instances)
     """
 
-    def __init__(self, filename):
+    def __init__(self, filename=None):
         from xml.etree import ElementTree
         from pskc.encryption import Encryption
         from pskc.exceptions import ParseError
@@ -74,11 +74,14 @@ class PSKC(object):
         self.encryption = Encryption()
         self.mac = MAC(self)
         self.keys = []
-        try:
-            tree = ElementTree.parse(filename)
-        except ElementTree.ParseError:
-            raise ParseError('Error parsing XML')
-        self.parse(tree.getroot())
+        if filename is not None:
+            try:
+                tree = ElementTree.parse(filename)
+            except ElementTree.ParseError:
+                raise ParseError('Error parsing XML')
+            self.parse(tree.getroot())
+        else:
+            self.version = '1.0'
 
     def parse(self, container):
         """Read information from the provided <KeyContainer> tree."""
diff --git a/tests/test_minimal.doctest b/tests/test_minimal.doctest
index 358bc0e..8987d8b 100644
--- a/tests/test_minimal.doctest
+++ b/tests/test_minimal.doctest
@@ -33,3 +33,8 @@ This tests the most minimal valid PSKC file with one empty 
key.
 >>> pskc = PSKC(minimal_pskc)
 >>> [key.id for key in pskc.keys]
 [None]
+
+
+Check creation of empty PSKC structure.
+
+>>> pskc = PSKC()

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

commit 820c83c3377adb7b4a5678338d50faed920bbf4a
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 16:49:27 2014 +0200

    Be more lenient in accepting algorithms

diff --git a/pskc/encryption.py b/pskc/encryption.py
index f13b853..a185871 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -34,9 +34,6 @@ from Crypto.Cipher import AES
 from Crypto.Protocol.KDF import PBKDF2
 
 
-AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
-
-
 def unpad(value):
     """Remove padding from the plaintext."""
     return value[0:-ord(value[-1])]
@@ -78,7 +75,7 @@ class EncryptedValue(object):
         key = self.encryption.key
         if key is None:
             raise DecryptionError('No key available')
-        if self.algorithm == AES128_CBC:
+        if self.algorithm.endswith('#aes128-cbc'):
             iv = self.cipher_value[:AES.block_size]
             ciphertext = self.cipher_value[AES.block_size:]
             cipher = AES.new(key, AES.MODE_CBC, iv)
@@ -87,13 +84,6 @@ class EncryptedValue(object):
             raise DecryptionError('Unsupported algorithm: %r' % self.algorithm)
 
 
-PBKDF2_URIS = [
-    'http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5#pbkdf2',
-    'http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2',
-    'http://www.w3.org/2009/xmlenc11#pbkdf2',
-]
-
-
 class KeyDerivation(object):
     """Handle key derivation.
 
@@ -143,7 +133,7 @@ class KeyDerivation(object):
 
     def generate(self, password):
         """Derive a key from the password."""
-        if self.algorithm in PBKDF2_URIS:
+        if self.algorithm.endswith('#pbkdf2'):
             # TODO: support pseudorandom function (prf)
             return PBKDF2(
                 password, self.pbkdf2_salt, dkLen=self.pbkdf2_key_length,
diff --git a/pskc/mac.py b/pskc/mac.py
index ad7c27c..3e7f248 100644
--- a/pskc/mac.py
+++ b/pskc/mac.py
@@ -36,9 +36,6 @@ import hmac
 from pskc.encryption import EncryptedValue
 
 
-HMAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1'
-
-
 class ValueMAC(object):
     """Provide MAC checking ability to PSKC data values."""
 
@@ -66,7 +63,7 @@ class ValueMAC(object):
             return
         algorithm = self.mac.algorithm
         key = self.mac.key
-        if algorithm == HMAC_SHA1 and key is not None:
+        if algorithm.endswith('#hmac-sha1') and key is not None:
             h = hmac.new(key, value, hashlib.sha1).digest()
             return h == self._value_mac
 

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

commit 02bde47c9f9b0f4b57730b1bb30efafdbb807a33
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 16:31:56 2014 +0200

    Code simplification

diff --git a/pskc/key.py b/pskc/key.py
index 6fc41bb..80fbbc5 100644
--- a/pskc/key.py
+++ b/pskc/key.py
@@ -74,13 +74,10 @@ class BinaryDataType(DataType):
     def value(self):
         """Provide the raw binary value."""
         # plain value is base64 encoded
-        value = self.plain_value
-        if value is not None:
-            return base64.b64decode(value)
+        if self.plain_value is not None:
+            return base64.b64decode(self.plain_value)
         # encrypted value is in correct format
-        value = self.encrypted_value.decrypt()
-        if value is not None:
-            return value
+        return self.encrypted_value.decrypt()
 
 
 class IntegerDataType(DataType):
@@ -90,9 +87,8 @@ class IntegerDataType(DataType):
     def value(self):
         """Provide the raw integer value."""
         # plain value is a string representation of the number
-        value = self.plain_value
-        if value:
-            return int(value)
+        if self.plain_value:
+            return int(self.plain_value)
         # decrypted value is big endian encoded
         value = self.encrypted_value.decrypt()
         if value is not None:

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

commit b62fec85e080feaef3e7304f867e11e164b2f537
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 16:31:42 2014 +0200

    Raise an exception if decryption fails

diff --git a/pskc/encryption.py b/pskc/encryption.py
index 92c02e4..f13b853 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -72,14 +72,19 @@ class EncryptedValue(object):
 
     def decrypt(self):
         """Decrypt the linked value and return the plaintext value."""
-        key = self.encryption.key
-        if key is None or self.cipher_value is None:
+        from pskc.exceptions import DecryptionError
+        if self.cipher_value is None:
             return
+        key = self.encryption.key
+        if key is None:
+            raise DecryptionError('No key available')
         if self.algorithm == AES128_CBC:
             iv = self.cipher_value[:AES.block_size]
             ciphertext = self.cipher_value[AES.block_size:]
             cipher = AES.new(key, AES.MODE_CBC, iv)
             return unpad(cipher.decrypt(ciphertext))
+        else:
+            raise DecryptionError('Unsupported algorithm: %r' % self.algorithm)
 
 
 PBKDF2_URIS = [
diff --git a/pskc/exceptions.py b/pskc/exceptions.py
index 006bed9..9203dfe 100644
--- a/pskc/exceptions.py
+++ b/pskc/exceptions.py
@@ -29,3 +29,13 @@ class ParseError(Exception):
 
     def __str__(self):
         return getattr(self, 'message', '')
+
+
+class DecryptionError(Exception):
+    """There was a problem decrypting the value.
+
+    The encrypted value as available but something went wrong with decrypting
+    it."""
+
+    def __str__(self):
+        return getattr(self, 'message', '')
diff --git a/tests/invalid-encryption.pskcxml b/tests/invalid-encryption.pskcxml
new file mode 100644
index 0000000..18ee5f1
--- /dev/null
+++ b/tests/invalid-encryption.pskcxml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Based on the Figure 6 example, this file includes an unknown encryption
+  algorithm.
+-->
+
+<KeyContainer Version="1.0"
+  xmlns="urn:ietf:params:xml:ns:keyprov:pskc"
+  xmlns:ds="http://www.w3.org/2000/09/xmldsig#";
+  xmlns:xenc="http://www.w3.org/2001/04/xmlenc#";>
+  <EncryptionKey>
+    <ds:KeyName>Pre-shared-key</ds:KeyName>
+  </EncryptionKey>
+  <KeyPackage>
+    <Key Id="12345678" Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:hotp">
+      <Data>
+        <Secret>
+          <EncryptedValue>
+            <xenc:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#unknown"/>
+            <xenc:CipherData>
+              <xenc:CipherValue>
+AAECAwQFBgcICQoLDA0OD+cIHItlB3Wra1DUpxVvOx2lef1VmNPCMl8jwZqIUqGv
+                </xenc:CipherValue>
+            </xenc:CipherData>
+          </EncryptedValue>
+        </Secret>
+      </Data>
+    </Key>
+  </KeyPackage>
+</KeyContainer>
diff --git a/tests/test_invalid.doctest b/tests/test_invalid.doctest
index 9ba666f..2665bae 100644
--- a/tests/test_invalid.doctest
+++ b/tests/test_invalid.doctest
@@ -40,3 +40,18 @@ ParseError: Missing KeyContainer
 Traceback (most recent call last):
     ...
 ParseError: Unsupported version
+
+
+>>> pskc = PSKC('tests/invalid-encryption.pskcxml')
+>>> key = pskc.keys[0]
+>>> key.id
+'12345678'
+>>> key.secret
+Traceback (most recent call last):
+    ...
+DecryptionError: No key available
+>>> pskc.encryption.key = '12345678901234567890123456789012'.decode('hex')
+>>> key.secret
+Traceback (most recent call last):
+    ...
+DecryptionError: Unsupported algorithm: ...
diff --git a/tests/test_rfc6030.doctest b/tests/test_rfc6030.doctest
index 6a6028f..776321d 100644
--- a/tests/test_rfc6030.doctest
+++ b/tests/test_rfc6030.doctest
@@ -148,8 +148,10 @@ due to the encryption.
 >>> key = pskc.keys[0]
 >>> key.id
 '12345678'
->>> key.secret is None
-True
+>>> key.secret
+Traceback (most recent call last):
+    ...
+DecryptionError: No key available
 >>> pskc.encryption.key_name
 'Pre-shared-key'
 >>> pskc.encryption.key = '12345678901234567890123456789012'.decode('hex')

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

commit 7bc2e6be6443fb35834c2f3908d1b3ee16147ece
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun May 25 16:10:36 2014 +0200

    Make decryption code better readable

diff --git a/pskc/encryption.py b/pskc/encryption.py
index a1412d1..92c02e4 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -37,6 +37,11 @@ from Crypto.Protocol.KDF import PBKDF2
 AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
 
 
+def unpad(value):
+    """Remove padding from the plaintext."""
+    return value[0:-ord(value[-1])]
+
+
 class EncryptedValue(object):
     """Wrapper class to handle encrypted values.
 
@@ -68,14 +73,13 @@ class EncryptedValue(object):
     def decrypt(self):
         """Decrypt the linked value and return the plaintext value."""
         key = self.encryption.key
-        ciphertext = self.cipher_value
-        if key is None or ciphertext is None:
+        if key is None or self.cipher_value is None:
             return
         if self.algorithm == AES128_CBC:
-            iv = ciphertext[:AES.block_size]
+            iv = self.cipher_value[:AES.block_size]
+            ciphertext = self.cipher_value[AES.block_size:]
             cipher = AES.new(key, AES.MODE_CBC, iv)
-            plaintext = cipher.decrypt(ciphertext[AES.block_size:])
-            return plaintext[0:-ord(plaintext[-1])]
+            return unpad(cipher.decrypt(ciphertext))
 
 
 PBKDF2_URIS = [

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

commit 714f38744e1dd294e78cf1a6be7c6b520f3f3750
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri May 23 17:34:32 2014 +0200

    Add tests for invalid PSKC files

diff --git a/setup.cfg b/setup.cfg
index 9f5c618..3763f8d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,7 +5,7 @@ group=root
 [nosetests]
 with-doctest=true
 doctest-extension=doctest
-#doctest-options=+IGNORE_EXCEPTION_DETAIL
+doctest-options=+IGNORE_EXCEPTION_DETAIL
 with-coverage=true
 cover-package=pskc
 cover-erase=true
diff --git a/tests/invalid-notxml.pskcxml b/tests/invalid-notxml.pskcxml
new file mode 100644
index 0000000..b9d2621
--- /dev/null
+++ b/tests/invalid-notxml.pskcxml
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<InValidXML>
+</InValidCloseTag>
diff --git a/tests/invalid-wrongelement.pskcxml 
b/tests/invalid-wrongelement.pskcxml
new file mode 100644
index 0000000..688e347
--- /dev/null
+++ b/tests/invalid-wrongelement.pskcxml
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<SomethingElse>
+</SomethingElse>
diff --git a/tests/invalid-wrongversion.pskcxml 
b/tests/invalid-wrongversion.pskcxml
new file mode 100644
index 0000000..fdd53fb
--- /dev/null
+++ b/tests/invalid-wrongversion.pskcxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<KeyContainer Version="1.2"
+    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_invalid.doctest b/tests/test_invalid.doctest
new file mode 100644
index 0000000..9ba666f
--- /dev/null
+++ b/tests/test_invalid.doctest
@@ -0,0 +1,42 @@
+test_invalid.doctest - test for invalid PSKC file
+
+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
+
+
+Load a number of invalid files.
+
+
+>>> pskc = PSKC('tests/invalid-notxml.pskcxml')
+Traceback (most recent call last):
+    ...
+ParseError: Error parsing XML
+
+
+>>> pskc = PSKC('tests/invalid-wrongelement.pskcxml')
+Traceback (most recent call last):
+    ...
+ParseError: Missing KeyContainer
+
+
+>>> pskc = PSKC('tests/invalid-wrongversion.pskcxml')
+Traceback (most recent call last):
+    ...
+ParseError: Unsupported version

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

commit 803d24c4e0483b825d4ca37ef786a778cff61bd4
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri May 23 17:25:20 2014 +0200

    Raise exceptions on some parsing problems

diff --git a/pskc/__init__.py b/pskc/__init__.py
index 13622e4..491fda4 100644
--- a/pskc/__init__.py
+++ b/pskc/__init__.py
@@ -42,6 +42,8 @@ embedded signatures, asymmetric keys and writing files are on 
the wishlist
 (patches welcome).
 """
 
+import sys
+
 
 __all__ = ['PSKC', '__version__']
 
@@ -65,21 +67,30 @@ class PSKC(object):
     def __init__(self, filename):
         from xml.etree import ElementTree
         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.mac = MAC(self)
         self.keys = []
-        tree = ElementTree.parse(filename)
+        try:
+            tree = ElementTree.parse(filename)
+        except ElementTree.ParseError:
+            raise ParseError('Error parsing XML')
         self.parse(tree.getroot())
 
     def parse(self, container):
         """Read information from the provided <KeyContainer> tree."""
-        from pskc.parse import namespaces
+        from pskc.exceptions import ParseError
         from pskc.key import Key
+        from pskc.parse import namespaces
+        if not container.tag.endswith('KeyContainer'):
+            raise ParseError('Missing KeyContainer')
         # the version of the PSKC schema
         self.version = container.attrib.get('Version')
+        if self.version != '1.0':
+            raise ParseError('Unsupported version %r' % self.version)
         # unique identifier for the container
         self.id = container.attrib.get('Id')
         # handle EncryptionKey entries
diff --git a/pskc/exceptions.py b/pskc/exceptions.py
new file mode 100644
index 0000000..006bed9
--- /dev/null
+++ b/pskc/exceptions.py
@@ -0,0 +1,31 @@
+# exceptions.py - collection of pskc exceptions
+# 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
+
+"""Collection of exceptions."""
+
+
+class ParseError(Exception):
+    """Something went wrong with parsing the PSKC file.
+
+    Either the file is invalid XML or required elements or attributes are
+    missing."""
+
+    def __str__(self):
+        return getattr(self, 'message', '')

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

commit 8c37e26a826ab92b94a59eb974f9c8523e81517d
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri May 23 16:52:19 2014 +0200

    Fix install_requires

diff --git a/setup.py b/setup.py
index a910e23..7547058 100755
--- a/setup.py
+++ b/setup.py
@@ -53,5 +53,5 @@ setup(
         'Topic :: Software Development :: Libraries :: Python Modules',
     ],
     packages=find_packages(),
-    install_requires=['distribute', 'Crypto', 'python-dateutil'],
+    install_requires=['pycrypto', 'python-dateutil'],
 )

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

Summary of changes:
 pskc/__init__.py                                   |   41 +++++++++++---
 pskc/encryption.py                                 |   31 ++++++-----
 pskc/exceptions.py                                 |   41 ++++++++++++++
 pskc/key.py                                        |   16 +++---
 pskc/mac.py                                        |    5 +-
 setup.cfg                                          |    2 +-
 setup.py                                           |    2 +-
 tests/invalid-encryption.pskcxml                   |   31 +++++++++++
 tests/invalid-notxml.pskcxml                       |    3 ++
 tests/invalid-wrongelement.pskcxml                 |    3 ++
 ...igure2.pskcxml => invalid-wrongversion.pskcxml} |    7 +--
 tests/test_invalid.doctest                         |   57 ++++++++++++++++++++
 tests/test_minimal.doctest                         |   14 +++++
 tests/test_rfc6030.doctest                         |    6 ++-
 14 files changed, 213 insertions(+), 46 deletions(-)
 create mode 100644 pskc/exceptions.py
 create mode 100644 tests/invalid-encryption.pskcxml
 create mode 100644 tests/invalid-notxml.pskcxml
 create mode 100644 tests/invalid-wrongelement.pskcxml
 copy tests/{rfc6030-figure2.pskcxml => invalid-wrongversion.pskcxml} (82%)
 create mode 100644 tests/test_invalid.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/