python-pskc branch master updated. 1.0-8-g924e1f3
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
python-pskc branch master updated. 1.0-8-g924e1f3
- From: Commits of the python-pskc project <python-pskc-commits [at] lists.arthurdejong.org>
- To: python-pskc-commits [at] lists.arthurdejong.org
- Reply-to: python-pskc-users [at] lists.arthurdejong.org
- Subject: python-pskc branch master updated. 1.0-8-g924e1f3
- Date: Fri, 9 Feb 2018 15:05:24 +0100 (CET)
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 924e1f38e257ac868a1d8a8adc2b6fa7ed45a339 (commit)
via be2b49fd90236ee16e5da3564caf3a6b227e46c8 (commit)
via e60d7f3356c4808e17e363055fca23fae005f76f (commit)
from 8054c6e6244de9d5d830a7a24b5ef84d60f8c4b2 (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 -----------------------------------------------------------------
https://arthurdejong.org/git/python-pskc/commit/?id=924e1f38e257ac868a1d8a8adc2b6fa7ed45a339
commit 924e1f38e257ac868a1d8a8adc2b6fa7ed45a339
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Thu Feb 8 23:21:33 2018 +0100
Correctly write a PSKC file without a MAC key
In some cases a PSKC file can be written with a MAC algorithm but
without a MAC key. This is possible when the MAC key is not supplied
(allowed in older PSKC versions) and a fallback to the encryption key is
done. If we have not yet decrypted the file the MAC key is not yet
available and so can't be included in the written file.
diff --git a/pskc/serialiser.py b/pskc/serialiser.py
index ca6622c..26bf1c2 100644
--- a/pskc/serialiser.py
+++ b/pskc/serialiser.py
@@ -95,6 +95,8 @@ class PSKCSerialiser(object):
return
mac_method = mk_elem(
container, 'pskc:MACMethod', Algorithm=mac.algorithm, empty=True)
+ if not key_value:
+ return
# encrypt the mac key if needed
if not hasattr(key_value, 'get_value'):
key_value = EncryptedValue.create(mac.pskc, key_value)
diff --git a/tests/test_write.doctest b/tests/test_write.doctest
index 34ddb36..4d980d6 100644
--- a/tests/test_write.doctest
+++ b/tests/test_write.doctest
@@ -257,6 +257,98 @@ providing the encryption key.
</pskc:KeyContainer>
+Read a legacy encrypted PSKC file and write it out as-is. This should convert
+the format to RFC 6030 format as best it can. Note that this does not include
+a MAC key (but does include a MAC algorithm because the MAC key is not
+specified and we assume to use the encryption key as MAC key).
+
+>>> pskc =
PSKC('tests/draft-hoyer-keyprov-portable-symmetric-key-container-01/password-encrypted.pskcxml')
+>>> pskc.write(sys.stdout) #doctest: +ELLIPSIS +REPORT_UDIFF
+<?xml version="1.0" encoding="UTF-8"?>
+<pskc:KeyContainer ... Version="1.0">
+ <pskc:EncryptionKey>
+ <xenc11:DerivedKey>
+ <xenc11:KeyDerivationMethod
Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2">
+ <xenc11:PBKDF2-params>
+ <Salt>
+ <Specified>y6TzckeLRQw=</Specified>
+ </Salt>
+ <IterationCount>999</IterationCount>
+ <KeyLength>16</KeyLength>
+ </xenc11:PBKDF2-params>
+ </xenc11:KeyDerivationMethod>
+ </xenc11:DerivedKey>
+ </pskc:EncryptionKey>
+ <pskc:MACMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
+ <pskc:KeyPackage>
+ <pskc:DeviceInfo>
+ <pskc:Manufacturer>Token Manufacturer</pskc:Manufacturer>
+ <pskc:SerialNo>98765432187</pskc:SerialNo>
+ <pskc:ExpiryDate>2008-01-01T00:00:00</pskc:ExpiryDate>
+ </pskc:DeviceInfo>
+ <pskc:Key Algorithm="HOTP" Id="77654321870">
+ <pskc:Issuer>Credential Issuer</pskc:Issuer>
+ <pskc:AlgorithmParameters>
+ <pskc:ResponseFormat Encoding="DECIMAL" Length="6"/>
+ </pskc:AlgorithmParameters>
+ <pskc:FriendlyName>MySecondToken</pskc:FriendlyName>
+ <pskc:Data>
+ <pskc:Secret>
+ <pskc:EncryptedValue>
+ <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>F/CY93NYc/SvmxT3oB6PzG7p6zpG92/t</xenc:CipherValue>
+ </xenc:CipherData>
+ </pskc:EncryptedValue>
+ <pskc:ValueMAC>hN793ZE7GM6yCM6gz9OKNRzibhg=</pskc:ValueMAC>
+ </pskc:Secret>
+ <pskc:Counter>
+ <pskc:EncryptedValue>
+ <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>VVBYqRF1QSpetvIB2vBAzw==</xenc:CipherValue>
+ </xenc:CipherData>
+ </pskc:EncryptedValue>
+ <pskc:ValueMAC>6clqJvT9l0xIZtWSch2t6zr0IwU=</pskc:ValueMAC>
+ </pskc:Counter>
+ </pskc:Data>
+ </pskc:Key>
+ </pskc:KeyPackage>
+</pskc:KeyContainer>
+
+If we decrypt the file the MAC key will be included in encrypted form.
+
+>>> pskc.encryption.derive_key('qwerty')
+>>> pskc.write(sys.stdout) #doctest: +ELLIPSIS +REPORT_UDIFF
+<?xml version="1.0" encoding="UTF-8"?>
+<pskc:KeyContainer ... Version="1.0">
+ <pskc:EncryptionKey>
+ <xenc11:DerivedKey>
+ <xenc11:KeyDerivationMethod
Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2">
+ <xenc11:PBKDF2-params>
+ <Salt>
+ <Specified>y6TzckeLRQw=</Specified>
+ </Salt>
+ <IterationCount>999</IterationCount>
+ <KeyLength>16</KeyLength>
+ </xenc11:PBKDF2-params>
+ </xenc11:KeyDerivationMethod>
+ </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#tripledes-cbc"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>...</xenc:CipherValue>
+ </xenc:CipherData>
+ </pskc:MACKey>
+ </pskc:MACMethod>
+ <pskc:KeyPackage>
+...
+ </pskc:KeyPackage>
+</pskc:KeyContainer>
+
+
Set up an encrypted PSKC file and generate a pre-shared key for it.
>>> pskc = PSKC()
https://arthurdejong.org/git/python-pskc/commit/?id=be2b49fd90236ee16e5da3564caf3a6b227e46c8
commit be2b49fd90236ee16e5da3564caf3a6b227e46c8
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sun Feb 4 16:08:47 2018 +0100
Correctly write a PSKC file with a global IV
This ensures that the encryption IV, which should be per encrypted value
is written out per encrypted value instead of globally. This is mostly
useful for when reading an old format PSKC file and writing out a RFC
6030 compliant one.
diff --git a/pskc/encryption.py b/pskc/encryption.py
index 35b7c79..e1f56c9 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -402,7 +402,10 @@ class Encryption(object):
def encrypt_value(self, plaintext):
"""Encrypt the provided value and return the cipher_value."""
- return encrypt(self.algorithm, self.key, plaintext, self.iv)
+ cipher_value = encrypt(self.algorithm, self.key, plaintext, self.iv)
+ if self.iv:
+ cipher_value = cipher_value[len(self.iv):]
+ return cipher_value
def remove_encryption(self):
"""Decrypt all values and remove the encryption from the PSKC file."""
diff --git a/pskc/serialiser.py b/pskc/serialiser.py
index 8020f60..ca6622c 100644
--- a/pskc/serialiser.py
+++ b/pskc/serialiser.py
@@ -100,11 +100,14 @@ class PSKCSerialiser(object):
key_value = EncryptedValue.create(mac.pskc, key_value)
# construct encrypted MACKey
algorithm = key_value.algorithm or mac.pskc.encryption.algorithm
+ cipher_value = key_value.cipher_value
+ if mac.pskc.encryption.iv:
+ cipher_value = mac.pskc.encryption.iv + cipher_value
mac_key = mk_elem(mac_method, 'pskc:MACKey', empty=True)
mk_elem(mac_key, 'xenc:EncryptionMethod', Algorithm=algorithm)
cipher_data = mk_elem(mac_key, 'xenc:CipherData', empty=True)
mk_elem(cipher_data, 'xenc:CipherValue',
- base64.b64encode(key_value.cipher_value).decode())
+ base64.b64encode(cipher_value).decode())
@classmethod
def serialise_key_package(cls, device, container):
@@ -195,6 +198,9 @@ class PSKCSerialiser(object):
else:
# encrypted value
algorithm = value.algorithm or pskc.encryption.algorithm
+ cipher_value = value.cipher_value
+ if pskc.encryption.iv:
+ cipher_value = pskc.encryption.iv + cipher_value
encrypted_value = mk_elem(
element, 'pskc:EncryptedValue', empty=True)
mk_elem(encrypted_value, 'xenc:EncryptionMethod',
@@ -202,7 +208,7 @@ class PSKCSerialiser(object):
cipher_data = mk_elem(
encrypted_value, 'xenc:CipherData', empty=True)
mk_elem(cipher_data, 'xenc:CipherValue',
- base64.b64encode(value.cipher_value).decode())
+ base64.b64encode(cipher_value).decode())
if value.mac_value:
mk_elem(element, 'pskc:ValueMAC',
base64.b64encode(value.mac_value).decode())
diff --git a/tests/test_write.doctest b/tests/test_write.doctest
index 1ea806a..34ddb36 100644
--- a/tests/test_write.doctest
+++ b/tests/test_write.doctest
@@ -1,6 +1,6 @@
test_write.doctest - tests for writing PSKC files
-Copyright (C) 2014-2017 Arthur de Jong
+Copyright (C) 2014-2018 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
@@ -563,3 +563,41 @@ set on one key end up being applied to both keys.
</pskc:Key>
</pskc:KeyPackage>
</pskc:KeyContainer>
+
+
+If we specify a global IV it will be used for all encrypted values but will
+be not be written as a global IV in the PSKC file because RFC 6030 does not
+specify this (and re-using an IV is a bad idea).
+
+>>> pskc = PSKC()
+>>> key = pskc.add_key(secret='1234')
+>>>
pskc.encryption.setup_preshared_key(key=a2b_hex('12345678901234567890123456789012'))
+>>> pskc.encryption.iv = a2b_hex('000102030405060708090a0b0c0d0e0f')
+>>> pskc.write(sys.stdout) #doctest: +ELLIPSIS +REPORT_UDIFF
+<?xml version="1.0" encoding="UTF-8"?>
+<pskc:KeyContainer ... Version="1.0">
+ <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>AAECAwQFBgcICQoLDA0OD...</xenc:CipherValue>
+ </xenc:CipherData>
+ </pskc:MACKey>
+ </pskc:MACMethod>
+ <pskc:KeyPackage>
+ <pskc:Key>
+ <pskc:Data>
+ <pskc:Secret>
+ <pskc:EncryptedValue>
+ <xenc:EncryptionMethod
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AAECAwQFBgcICQoLDA0OD...</xenc:CipherValue>
+ </xenc:CipherData>
+ </pskc:EncryptedValue>
+ <pskc:ValueMAC>...</pskc:ValueMAC>
+ </pskc:Secret>
+ </pskc:Data>
+ </pskc:Key>
+ </pskc:KeyPackage>
+</pskc:KeyContainer>
https://arthurdejong.org/git/python-pskc/commit/?id=e60d7f3356c4808e17e363055fca23fae005f76f
commit e60d7f3356c4808e17e363055fca23fae005f76f
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Wed Feb 7 20:04:31 2018 +0100
Also use EncryptedValue for MAC key
This ensures that an encrypted MAC key is hanled in the same way as
normal encrypted data values.
This also ensures consistent fallback to the globally configured
encryption algorithm if no value has been set in the EncryptedValue.
diff --git a/pskc/mac.py b/pskc/mac.py
index 65ec9b3..38552dd 100644
--- a/pskc/mac.py
+++ b/pskc/mac.py
@@ -1,7 +1,7 @@
# mac.py - module for checking value signatures
# coding: utf-8
#
-# Copyright (C) 2014-2017 Arthur de Jong
+# Copyright (C) 2014-2018 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
@@ -81,25 +81,22 @@ class MAC(object):
def __init__(self, pskc):
self.pskc = pskc
self._algorithm = None
- self.key_plain_value = None
- self.key_cipher_value = None
- self.key_algorithm = None
@property
def key(self):
"""Provide access to the MAC key binary value if available."""
- if self.key_plain_value:
- return self.key_plain_value
- elif self.key_cipher_value:
- return self.pskc.encryption.decrypt_value(
- self.key_cipher_value, self.key_algorithm)
- # fall back to encryption key
- return self.pskc.encryption.key
+ value = getattr(self, '_key', None)
+ if hasattr(value, 'get_value'):
+ return value.get_value(self.pskc)
+ elif value:
+ return value
+ else:
+ # fall back to encryption key
+ return self.pskc.encryption.key
@key.setter
def key(self, value):
- self.key_plain_value = value
- self.key_cipher_value = None
+ self._key = value
@property
def algorithm(self):
diff --git a/pskc/parser.py b/pskc/parser.py
index 11486f8..b3e7952 100644
--- a/pskc/parser.py
+++ b/pskc/parser.py
@@ -157,8 +157,8 @@ class PSKCParser(object):
mac_method.get('algorithm'))
mac_key = find(mac_method, 'MACKey')
if mac_key is not None:
- mac.key_algorithm, mac.key_cipher_value = (
- cls.parse_encrypted_value(mac_key))
+ algorithm, cipher_value = cls.parse_encrypted_value(mac_key)
+ mac.key = EncryptedValue(cipher_value, None, algorithm)
@classmethod
def parse_key_package(cls, device, key_package):
diff --git a/pskc/serialiser.py b/pskc/serialiser.py
index c71f6ea..8020f60 100644
--- a/pskc/serialiser.py
+++ b/pskc/serialiser.py
@@ -90,22 +90,21 @@ class PSKCSerialiser(object):
@classmethod
def serialise_mac(cls, mac, container):
- if not mac.algorithm and not mac.key:
+ key_value = getattr(mac, '_key', None) or mac.pskc.encryption.key
+ if not mac.algorithm and not key_value:
return
mac_method = mk_elem(
container, 'pskc:MACMethod', Algorithm=mac.algorithm, empty=True)
+ # encrypt the mac key if needed
+ if not hasattr(key_value, 'get_value'):
+ key_value = EncryptedValue.create(mac.pskc, key_value)
+ # construct encrypted MACKey
+ algorithm = key_value.algorithm or mac.pskc.encryption.algorithm
mac_key = mk_elem(mac_method, 'pskc:MACKey', empty=True)
- mk_elem(
- mac_key, 'xenc:EncryptionMethod',
- Algorithm=mac.pskc.encryption.algorithm)
+ mk_elem(mac_key, 'xenc:EncryptionMethod', Algorithm=algorithm)
cipher_data = mk_elem(mac_key, 'xenc:CipherData', empty=True)
- if mac.key_cipher_value:
- mk_elem(cipher_data, 'xenc:CipherValue',
- base64.b64encode(mac.key_cipher_value).decode())
- elif mac.key_plain_value:
- mk_elem(cipher_data, 'xenc:CipherValue',
- base64.b64encode(mac.pskc.encryption.encrypt_value(
- mac.key_plain_value)).decode())
+ mk_elem(cipher_data, 'xenc:CipherValue',
+ base64.b64encode(key_value.cipher_value).decode())
@classmethod
def serialise_key_package(cls, device, container):
@@ -195,10 +194,11 @@ class PSKCSerialiser(object):
mk_elem(element, 'pskc:PlainValue', value2text(value))
else:
# encrypted value
+ algorithm = value.algorithm or pskc.encryption.algorithm
encrypted_value = mk_elem(
element, 'pskc:EncryptedValue', empty=True)
mk_elem(encrypted_value, 'xenc:EncryptionMethod',
- Algorithm=value.algorithm)
+ Algorithm=algorithm)
cipher_data = mk_elem(
encrypted_value, 'xenc:CipherData', empty=True)
mk_elem(cipher_data, 'xenc:CipherValue',
-----------------------------------------------------------------------
Summary of changes:
pskc/encryption.py | 5 +-
pskc/mac.py | 23 ++++-----
pskc/parser.py | 4 +-
pskc/serialiser.py | 34 +++++++-----
tests/test_write.doctest | 132 ++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 168 insertions(+), 30 deletions(-)
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/
- python-pskc branch master updated. 1.0-8-g924e1f3,
Commits of the python-pskc project