lists.arthurdejong.org
RSS feed

python-pskc branch master updated. 5ab731c78739c95bbc46acbed9a8b4621db7f52e

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

python-pskc branch master updated. 5ab731c78739c95bbc46acbed9a8b4621db7f52e



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  5ab731c78739c95bbc46acbed9a8b4621db7f52e (commit)
       via  a3fd598b985bb9e65dc842498f766065653bca34 (commit)
       via  2ff470fa3b7d8eb0dc0a504e9007ba352584fe69 (commit)
      from  460f335781f8146a04262edb8f2384310118baee (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=5ab731c78739c95bbc46acbed9a8b4621db7f52e

commit 5ab731c78739c95bbc46acbed9a8b4621db7f52e
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Apr 12 23:51:03 2014 +0200

    Add test for Figure 7 from RFC6030
    
    This tests encrypted key derivation using PBKDF2 and a pre-shared
    passphrase.

diff --git a/tests/rfc6030-figure7.pskc b/tests/rfc6030-figure7.pskc
new file mode 100644
index 0000000..b37c575
--- /dev/null
+++ b/tests/rfc6030-figure7.pskc
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Figure 7 example from RFC6030 that has a PSKC document using encryption
+  based on passphrase-based keys. The pre-shared password is 'qwerty', The
+  derived encryption key is 651e63cd57008476af1ff6422cd02e41 hex and the
+  OTP secret is 12345678901234567890 hex.
+-->
+
+<pskc:KeyContainer
+  xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
+  xmlns:xenc11="http://www.w3.org/2009/xmlenc11#";
+  xmlns:pkcs5="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#";
+  xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"; Version="1.0">
+    <pskc:EncryptionKey>
+        <xenc11:DerivedKey>
+            <xenc11:KeyDerivationMethod
+              
Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2";>
+                <pkcs5:PBKDF2-params>
+                    <Salt>
+                        <Specified>Ej7/PEpyEpw=</Specified>
+                    </Salt>
+                    <IterationCount>1000</IterationCount>
+                    <KeyLength>16</KeyLength>
+                    <PRF/>
+                </pkcs5:PBKDF2-params>
+            </xenc11:KeyDerivationMethod>
+            <xenc:ReferenceList>
+                <xenc:DataReference URI="#ED"/>
+            </xenc:ReferenceList>
+            <xenc11:MasterKeyName>My Password 1</xenc11:MasterKeyName>
+        </xenc11:DerivedKey>
+    </pskc:EncryptionKey>
+    <pskc:MACMethod
+        Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1";>
+        <pskc:MACKey>
+            <xenc:EncryptionMethod
+            Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
+            <xenc:CipherData>
+                <xenc:CipherValue>
+2GTTnLwM3I4e5IO5FkufoOEiOhNj91fhKRQBtBJYluUDsPOLTfUvoU2dStyOwYZx
+                </xenc:CipherValue>
+            </xenc:CipherData>
+        </pskc:MACKey>
+    </pskc:MACMethod>
+    <pskc:KeyPackage>
+        <pskc:DeviceInfo>
+            <pskc:Manufacturer>TokenVendorAcme</pskc:Manufacturer>
+            <pskc:SerialNo>987654321</pskc:SerialNo>
+        </pskc:DeviceInfo>
+        <pskc:CryptoModuleInfo>
+            <pskc:Id>CM_ID_001</pskc:Id>
+        </pskc:CryptoModuleInfo>
+        <pskc:Key Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:hotp" 
Id="123456">
+            <pskc:Issuer>Example-Issuer</pskc:Issuer>
+            <pskc:AlgorithmParameters>
+                <pskc:ResponseFormat Length="8" Encoding="DECIMAL"/>
+            </pskc:AlgorithmParameters>
+            <pskc:Data>
+                <pskc:Secret>
+                <pskc:EncryptedValue Id="ED">
+                    <xenc:EncryptionMethod
+                        
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
+                        <xenc:CipherData>
+                            <xenc:CipherValue>
+      oTvo+S22nsmS2Z/RtcoF8Hfh+jzMe0RkiafpoDpnoZTjPYZu6V+A4aEn032yCr4f
+                        </xenc:CipherValue>
+                    </xenc:CipherData>
+                    </pskc:EncryptedValue>
+                    <pskc:ValueMAC>LP6xMvjtypbfT9PdkJhBZ+D6O4w=
+                    </pskc:ValueMAC>
+                </pskc:Secret>
+            </pskc:Data>
+        </pskc:Key>
+    </pskc:KeyPackage>
+</pskc:KeyContainer>
diff --git a/tests/test_rfc6030.doctest b/tests/test_rfc6030.doctest
index de86724..e5854d0 100644
--- a/tests/test_rfc6030.doctest
+++ b/tests/test_rfc6030.doctest
@@ -154,3 +154,21 @@ Figure 6 from RFC6030.
 '3132333435363738393031323334353637383930'
 >>> key.check()
 True
+
+
+This tests a derived master key using PBKDF2 as seen in Figure 7 from
+RFC6030.
+
+>>> pskc = PSKC('tests/rfc6030-figure7.pskc')
+>>> pskc.encryption.key_name
+'My Password 1'
+>>> pskc.encryption.derive_key('qwerty')
+>>> pskc.encryption.key.encode('hex')
+'651e63cd57008476af1ff6422cd02e41'
+>>> pskc.mac.key.encode('hex')
+'bdaab8d648e850d25a3289364f7d7eaaf53ce581'
+>>> key = pskc.keys[0]
+>>> key.secret
+'12345678901234567890'
+>>> key.check()
+True

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

commit a3fd598b985bb9e65dc842498f766065653bca34
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Apr 12 23:51:14 2014 +0200

    Implement PBKDF2 key derivation
    
    This supports deriving the key from a passphrase and information present
    in the DerivedKey and PBKDF2-params XML elements.

diff --git a/pskc/encryption.py b/pskc/encryption.py
index b310715..d98871a 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -21,6 +21,7 @@
 import base64
 
 from Crypto.Cipher import AES
+from Crypto.Protocol.KDF import PBKDF2
 
 
 AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
@@ -67,6 +68,58 @@ class EncryptedValue(object):
             return plaintext[0:-ord(plaintext[-1])]
 
 
+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 derived keys."""
+
+    def __init__(self, key_deriviation=None):
+        self.algorithm = None
+        # PBKDF2 properties
+        self.pbkdf2_salt = None
+        self.pbkdf2_iterations = None
+        self.pbkdf2_key_length = None
+        self.pbkdf2_prf = None
+        self.parse(key_deriviation)
+
+    def parse(self, key_deriviation):
+        from pskc.parse import g_e_v, g_e_i, namespaces
+        if key_deriviation is None:
+            return
+        self.algorithm = key_deriviation.attrib.get('Algorithm')
+        # PBKDF2 properties
+        pbkdf2 = key_deriviation.find(
+            'xenc11:PBKDF2-params', namespaces=namespaces)
+        if pbkdf2 is None:
+            pbkdf2 = key_deriviation.find(
+                'pkcs5:PBKDF2-params', namespaces=namespaces)
+        if pbkdf2 is not None:
+            # get used salt
+            value = g_e_v(pbkdf2, 'Salt/Specified')
+            if value is not None:
+                self.pbkdf2_salt = base64.b64decode(value)
+            # required number of iterations
+            self.pbkdf2_iterations = g_e_i(pbkdf2, 'IterationCount')
+            # key length
+            self.pbkdf2_key_length = g_e_i(pbkdf2, 'KeyLength')
+            # pseudorandom function used
+            prf = pbkdf2.find('PRF', namespaces=namespaces)
+            if prf is not None:
+                self.pbkdf2_prf = prf.attrib.get('Algorithm')
+
+    def generate(self, password):
+        if self.algorithm in PBKDF2_URIS:
+            # TODO: support pseudorandom function (prf)
+            return PBKDF2(
+                password, self.pbkdf2_salt, dkLen=self.pbkdf2_key_length,
+                count=self.pbkdf2_iterations, prf=None)
+
+
 class Encryption(object):
     """Class for handling encryption keys that are used in the PSKC file."""
 
@@ -74,6 +127,7 @@ class Encryption(object):
         self.id = None
         self.key_names = []
         self.key = None
+        self.derivation = KeyDerivation()
         self.parse(key_info)
 
     def parse(self, key_info):
@@ -84,8 +138,18 @@ class Encryption(object):
         self.id = key_info.attrib.get('Id')
         for name in key_info.findall('ds:KeyName', namespaces=namespaces):
             self.key_names.append(g_e_v(name, '.'))
+        for name in key_info.findall(
+                'xenc11:DerivedKey/xenc11:MasterKeyName',
+                namespaces=namespaces):
+            self.key_names.append(g_e_v(name, '.'))
+        self.derivation.parse(key_info.find(
+            'xenc11:DerivedKey/xenc11:KeyDerivationMethod',
+            namespaces=namespaces))
 
     @property
     def key_name(self):
         if self.key_names:
             return self.key_names[0]
+
+    def derive_key(self, password):
+        self.key = self.derivation.generate(password)

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

commit 2ff470fa3b7d8eb0dc0a504e9007ba352584fe69
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Apr 12 22:45:25 2014 +0200

    Add id attribute from EncryptionKey

diff --git a/pskc/encryption.py b/pskc/encryption.py
index 2c06ae6..b310715 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -71,14 +71,17 @@ class Encryption(object):
     """Class for handling encryption keys that are used in the PSKC file."""
 
     def __init__(self, key_info=None):
+        self.id = None
         self.key_names = []
         self.key = None
-        if key_info is not None:
-            self.parse(key_info)
+        self.parse(key_info)
 
     def parse(self, key_info):
         """Read encryption information from the EncryptionKey XML tree."""
         from pskc.parse import g_e_v, namespaces
+        if key_info is None:
+            return
+        self.id = key_info.attrib.get('Id')
         for name in key_info.findall('ds:KeyName', namespaces=namespaces):
             self.key_names.append(g_e_v(name, '.'))
 

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

Summary of changes:
 pskc/encryption.py         |   71 +++++++++++++++++++++++++++++++++++++++--
 tests/rfc6030-figure7.pskc |   76 ++++++++++++++++++++++++++++++++++++++++++++
 tests/test_rfc6030.doctest |   18 +++++++++++
 3 files changed, 163 insertions(+), 2 deletions(-)
 create mode 100644 tests/rfc6030-figure7.pskc


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/