lists.arthurdejong.org
RSS feed

python-pskc branch master updated. 0.1-30-g4d92b93

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

python-pskc branch master updated. 0.1-30-g4d92b93



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  4d92b937bddea136a709bb29b66a2ce6fe0ac943 (commit)
       via  fd71f01a9237c9076d07ac39bf6f18d0ccc4b6fe (commit)
      from  f639318faf742dfecb236c56239ffebe50621a97 (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=4d92b937bddea136a709bb29b66a2ce6fe0ac943

commit 4d92b937bddea136a709bb29b66a2ce6fe0ac943
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat May 31 23:39:17 2014 +0200

    Support kw-tripledes decryption
    
    This adds support for key unwrapping using the RFC 3217 Triple DES key
    wrap algorithm if the PSKC file uses this.

diff --git a/pskc/encryption.py b/pskc/encryption.py
index d1451df..48b9ef5 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -102,6 +102,12 @@ class EncryptedValue(object):
                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 Crypto.Cipher import DES3
+            if len(key) not in DES3.key_size:
+                raise DecryptionError('Invalid key length')
+            return unwrap(self.cipher_value, key)
         else:
             raise DecryptionError('Unsupported algorithm: %r' % self.algorithm)
 
diff --git a/tests/kw-tripledes.pskcxml b/tests/kw-tripledes.pskcxml
new file mode 100644
index 0000000..ffa0264
--- /dev/null
+++ b/tests/kw-tripledes.pskcxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Test that holds an kw-tripledes encrypted value. The pre-shared key is
+  255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f, the plain text value is
+  2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98.
+-->
+
+<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>
+   <Data>
+    <Secret>
+     <EncryptedValue>
+      <xenc:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#kw-tripledes"/>
+      <xenc:CipherData>
+       
<xenc:CipherValue>aQEHYY7wkrO0jKF5ayNK6foz67QVlgQDfbXWqE6zqsJ2jGMndaRn1A==</xenc:CipherValue>
+      </xenc:CipherData>
+     </EncryptedValue>
+    </Secret>
+   </Data>
+  </Key>
+ </KeyPackage>
+</KeyContainer>
diff --git a/tests/test_encryption.doctest b/tests/test_encryption.doctest
index 19ea062..6d39e35 100644
--- a/tests/test_encryption.doctest
+++ b/tests/test_encryption.doctest
@@ -81,3 +81,14 @@ DecryptionError: Invalid key length
 >>> pskc.encryption.key = 
 >>> '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'.decode('hex')
 >>> pskc.keys[0].secret.encode('hex')
 '00112233445566778899aabbccddeeff0001020304050607'
+
+
+>>> pskc = PSKC('tests/kw-tripledes.pskcxml')
+>>> pskc.encryption.key = '255e0d1c07b646dfb3134cc843ba8aa71f'.decode('hex')
+>>> pskc.keys[0].secret
+Traceback (most recent call last):
+    ...
+DecryptionError: Invalid key length
+>>> pskc.encryption.key = 
'255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f'.decode('hex')
+>>> pskc.keys[0].secret.encode('hex')
+'2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98'

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

commit fd71f01a9237c9076d07ac39bf6f18d0ccc4b6fe
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat May 31 22:58:52 2014 +0200

    Implement RFC 3217 Triple DES key wrapping

diff --git a/pskc/tripledeskw.py b/pskc/tripledeskw.py
new file mode 100644
index 0000000..47c93f1
--- /dev/null
+++ b/pskc/tripledeskw.py
@@ -0,0 +1,67 @@
+# tripledeskw.py - implementation of Triple DES key wrapping
+# 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
+
+"""Implement Triple DES key wrapping as described in RFC 3217."""
+
+from Crypto import Random
+from Crypto.Cipher import DES3
+from Crypto.Hash import SHA
+
+from pskc.exceptions import EncryptionError, DecryptionError
+
+
+def _cms_hash(value):
+    """The key checksum algorithm described in RFC 3217 section 2."""
+    return SHA.new(value).digest()[:8]
+
+
+RFC3217_IV = '4adda22c79e82105'.decode('hex')
+
+
+def wrap(plaintext, key, iv=None):
+    """Wrap one key (typically a Triple DES key) with another Triple DES key.
+
+    This uses the algorithm from RFC 3217 to encrypt the plaintext (the key
+    to wrap) using the provided key. If the iv is None, it is randomly
+    generated."""
+    if len(plaintext) % DES3.block_size != 0:
+        raise EncryptionError('Plaintext length wrong')
+    if iv is None:
+        iv = Random.get_random_bytes(8)
+    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)))
+
+
+def unwrap(ciphertext, key):
+    """Unwrap a key (typically Triple DES key ) with another Triple DES key.
+
+    This uses the algorithm from RFC 3217 to decrypt the ciphertext (the
+    previously wrapped key) using the provided 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)))
+    cipher = DES3.new(key, DES3.MODE_CBC, tmp[:8])
+    tmp = cipher.decrypt(tmp[8:])
+    if tmp[-8:] == _cms_hash(tmp[:-8]):
+        return tmp[:-8]
+    raise DecryptionError('CMS key checksum error')
diff --git a/tests/test_tripledeskw.doctest b/tests/test_tripledeskw.doctest
new file mode 100644
index 0000000..6f7629a
--- /dev/null
+++ b/tests/test_tripledeskw.doctest
@@ -0,0 +1,85 @@
+test_tripledeskw.doctest - test keywrap functions
+
+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
+
+>>> import re
+>>> from pskc.tripledeskw import wrap, unwrap
+>>> def fromhex(value):
+...     return re.sub(r'\s', '', value).decode('hex')
+
+
+Example from RFC 3217 section 3.2 wrapping a 192 bit Triple DES key with
+another 192 bit Triple DES key.
+
+>>> plaintext = fromhex('''
+... 2923 bf85 e06d d6ae 5291 49f1 f1ba e9ea b3a7 da3d 860d 3e98
+... ''')
+>>> key = fromhex('''
+... 255e 0d1c 07b6 46df b313 4cc8 43ba 8aa7 1f02 5b7c 0838 251f
+... ''')
+>>> iv = fromhex('5dd4 cbfc 96f5 453b')
+>>> ciphertext = fromhex('''
+... 6901 0761 8ef0 92b3 b48c a179 6b23 4ae9 fa33 ebb4 1596 0403
+... 7db5 d6a8 4eb3 aac2 768c 6327 75a4 67d4
+... ''')
+>>> wrap(plaintext, key, iv=iv) == ciphertext
+True
+>>> unwrap(ciphertext, key) == plaintext
+True
+
+
+Leaving out the iv ensures that a random iv is used.
+
+>>> c = wrap(plaintext, key)
+>>> c == ciphertext
+False
+>>> unwrap(c, key) == plaintext
+True
+
+
+Wrapping is only specified for Triple DES keys but the algorithms works for
+any plaintext that is a multiple of the Triple DES block size but fails
+otherwise.
+
+>>> short_plaintext = fromhex('''
+... 2923 bf85 e06d d6ae 5291 49f1 f1ba e9ea
+... ''')
+>>> unwrap(wrap(short_plaintext, key), key) == short_plaintext
+True
+>>> short_plaintext = fromhex('''
+... 2923 bf85 e06d d6ae 5291 49f1 f1ba e9
+... ''')
+>>> wrap(short_plaintext, key)
+Traceback (most recent call last):
+    ...
+EncryptionError: Plaintext length wrong
+
+
+The ciphertext must have the correct length (multiple of Triple DES block
+size) and unwrapping is also authenticated.
+
+>>> unwrap(ciphertext, key) == plaintext
+True
+>>> unwrap(ciphertext[:-1], key)
+Traceback (most recent call last):
+    ...
+DecryptionError: Ciphertext length wrong
+>>> unwrap(ciphertext[:-1] + 'A', key)
+Traceback (most recent call last):
+    ...
+DecryptionError: CMS key checksum error

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

Summary of changes:
 pskc/encryption.py                                 |    6 ++
 pskc/tripledeskw.py                                |   67 +++++++++++++++
 tests/{aes192-cbc.pskcxml => kw-tripledes.pskcxml} |    9 ++-
 tests/test_encryption.doctest                      |   11 +++
 tests/test_tripledeskw.doctest                     |   85 ++++++++++++++++++++
 5 files changed, 174 insertions(+), 4 deletions(-)
 create mode 100644 pskc/tripledeskw.py
 copy tests/{aes192-cbc.pskcxml => kw-tripledes.pskcxml} (63%)
 create mode 100644 tests/test_tripledeskw.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/