python-pskc branch master updated. 0.5-19-g2c8a9b7
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
python-pskc branch master updated. 0.5-19-g2c8a9b7
- 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. 0.5-19-g2c8a9b7
- Date: Sun, 1 Oct 2017 21:43:40 +0200 (CEST)
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 2c8a9b7b1b87a3cc07aac800d77db4652165d3e1 (commit)
via d0eddf88287bce398cb7a55ee20b384e3f764a4d (commit)
from 4ed4e115469e756b879e4cc788391eca0d656d1c (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=2c8a9b7b1b87a3cc07aac800d77db4652165d3e1
commit 2c8a9b7b1b87a3cc07aac800d77db4652165d3e1
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sat Sep 30 18:28:37 2017 +0200
Replace use of pycrypto utility functions
This uses os.urandom() as a source for random data and replaces other
utility functions. This also removes one import for getting the lengths
of Tripple DES keys.
diff --git a/pskc/crypto/aeskw.py b/pskc/crypto/aeskw.py
index 416d79b..7396f26 100644
--- a/pskc/crypto/aeskw.py
+++ b/pskc/crypto/aeskw.py
@@ -1,7 +1,7 @@
# aeskw.py - implementation of AES key wrapping
# coding: utf-8
#
-# Copyright (C) 2014-2015 Arthur de Jong
+# Copyright (C) 2014-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
@@ -21,14 +21,21 @@
"""Implement key wrapping as described in RFC 3394 and RFC 5649."""
import binascii
+import struct
from Crypto.Cipher import AES
-from Crypto.Util.number import bytes_to_long, long_to_bytes
-from Crypto.Util.strxor import strxor
from pskc.exceptions import DecryptionError, EncryptionError
+def _strxor(a, b):
+ """Return a XOR b."""
+ if isinstance(b'', str): # pragma: no cover (Python 2 specific)
+ return b''.join(chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b))
+ else: # pragma: no cover (Python 3 specific)
+ return bytes(x ^ y for (x, y) in zip(a, b))
+
+
def _split(value):
return value[:8], value[8:]
@@ -60,7 +67,7 @@ def wrap(plaintext, key, iv=None, pad=None):
if iv is None:
if len(plaintext) != mli or pad is True:
- iv = RFC5649_IV + long_to_bytes(mli, 4)
+ iv = RFC5649_IV + struct.pack('>I', mli)
else:
iv = RFC3394_IV
@@ -77,7 +84,7 @@ def wrap(plaintext, key, iv=None, pad=None):
for j in range(6):
for i in range(n):
A, R[i] = _split(encrypt(A + R[i]))
- A = strxor(A, long_to_bytes(n * j + i + 1, 8))
+ A = _strxor(A, struct.pack('>Q', n * j + i + 1))
return A + b''.join(R)
@@ -107,7 +114,7 @@ def unwrap(ciphertext, key, iv=None, pad=None):
for i in range(n)]
for j in reversed(range(6)):
for i in reversed(range(n)):
- A = strxor(A, long_to_bytes(n * j + i + 1, 8))
+ A = _strxor(A, struct.pack('>Q', n * j + i + 1))
A, R[i] = _split(decrypt(A + R[i]))
plaintext = b''.join(R)
@@ -115,7 +122,7 @@ def unwrap(ciphertext, key, iv=None, pad=None):
if A == RFC3394_IV and pad is not True:
return plaintext
elif A[:4] == RFC5649_IV and pad is not False:
- mli = bytes_to_long(A[4:])
+ mli = struct.unpack('>I', A[4:])[0]
# check padding length is valid and plaintext only contains zeros
if 8 * (n - 1) < mli <= 8 * n and \
plaintext.endswith((len(plaintext) - mli) * b'\0'):
diff --git a/pskc/crypto/tripledeskw.py b/pskc/crypto/tripledeskw.py
index 0802141..9494026 100644
--- a/pskc/crypto/tripledeskw.py
+++ b/pskc/crypto/tripledeskw.py
@@ -1,7 +1,7 @@
# tripledeskw.py - implementation of Triple DES key wrapping
# coding: utf-8
#
-# Copyright (C) 2014-2015 Arthur de Jong
+# Copyright (C) 2014-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
@@ -21,8 +21,8 @@
"""Implement Triple DES key wrapping as described in RFC 3217."""
import binascii
+import os
-from Crypto import Random
from Crypto.Cipher import DES3
from Crypto.Hash import SHA
@@ -47,7 +47,7 @@ def wrap(plaintext, key, iv=None):
if len(plaintext) % DES3.block_size != 0:
raise EncryptionError('Plaintext length wrong')
if iv is None:
- iv = Random.get_random_bytes(8)
+ iv = os.urandom(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)
diff --git a/pskc/encryption.py b/pskc/encryption.py
index 0da9f82..5ae31db 100644
--- a/pskc/encryption.py
+++ b/pskc/encryption.py
@@ -27,6 +27,9 @@ The encryption key can be derived using the KeyDerivation
class.
"""
+import os
+
+
def algorithm_key_lengths(algorithm):
"""Return the possible key lengths for the configured algorithm."""
from pskc.exceptions import DecryptionError
@@ -38,8 +41,7 @@ def algorithm_key_lengths(algorithm):
return [int(algorithm[-7:-4]) // 8]
elif algorithm.endswith('#tripledes-cbc') or \
algorithm.endswith('#kw-tripledes'):
- from Crypto.Cipher import DES3
- return list(DES3.key_size)
+ return [16, 24]
elif algorithm.endswith('#kw-aes128') or \
algorithm.endswith('#kw-aes192') or \
algorithm.endswith('#kw-aes256'):
@@ -98,17 +100,15 @@ def encrypt(algorithm, key, plaintext, iv=None):
if algorithm.endswith('#aes128-cbc') or \
algorithm.endswith('#aes192-cbc') or \
algorithm.endswith('#aes256-cbc'):
- from Crypto import Random
from Crypto.Cipher import AES
from pskc.crypto import pad
- iv = iv or Random.get_random_bytes(AES.block_size)
+ iv = iv or os.urandom(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(pad(plaintext, AES.block_size))
elif algorithm.endswith('#tripledes-cbc'):
- from Crypto import Random
from Crypto.Cipher import DES3
from pskc.crypto import pad
- iv = iv or Random.get_random_bytes(DES3.block_size)
+ iv = iv or os.urandom(DES3.block_size)
cipher = DES3.new(key, DES3.MODE_CBC, iv)
return iv + cipher.encrypt(pad(plaintext, DES3.block_size))
elif algorithm.endswith('#kw-aes128') or \
@@ -195,10 +195,9 @@ class KeyDerivation(object):
def setup_pbkdf2(self, password, salt=None, salt_length=16,
key_length=None, iterations=None, prf=None):
- from Crypto import Random
self.algorithm = 'pbkdf2'
if salt is None:
- salt = Random.get_random_bytes(salt_length)
+ salt = os.urandom(salt_length)
self.pbkdf2_salt = salt
if iterations:
self.pbkdf2_iterations = iterations
@@ -298,9 +297,8 @@ class Encryption(object):
self._setup_encryption(kwargs)
self.key = kwargs.pop('key', self.key)
if not self.key:
- from Crypto import Random
- self.key = Random.get_random_bytes(kwargs.pop(
- 'key_length', self.algorithm_key_lengths[-1]))
+ self.key = os.urandom(
+ kwargs.pop('key_length', self.algorithm_key_lengths[-1]))
def setup_pbkdf2(self, password, **kwargs):
"""Configure password-based PSKC encryption when writing the file.
diff --git a/pskc/mac.py b/pskc/mac.py
index 5ac1a92..5f258d0 100644
--- a/pskc/mac.py
+++ b/pskc/mac.py
@@ -29,6 +29,7 @@ with the PSKC encryption key.
"""
+import os
import re
@@ -145,5 +146,4 @@ class MAC(object):
self.algorithm = 'hmac-sha1'
# generate an HMAC key
if not self.key:
- from Crypto import Random
- self.key = Random.get_random_bytes(self.algorithm_key_length)
+ self.key = os.urandom(self.algorithm_key_length)
diff --git a/tests/test_aeskw.doctest b/tests/test_aeskw.doctest
index c6ca659..a238a7f 100644
--- a/tests/test_aeskw.doctest
+++ b/tests/test_aeskw.doctest
@@ -1,6 +1,6 @@
test_keywrap.doctest - test keywrap functions
-Copyright (C) 2014-2016 Arthur de Jong
+Copyright (C) 2014-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
@@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
->>> from Crypto.Util.number import long_to_bytes
+>>> import struct
>>> from binascii import a2b_hex
>>> from pskc.crypto.aeskw import wrap, unwrap
@@ -210,7 +210,7 @@ works because we have padded the plaintext with two 0 bytes.
>>> key = a2b_hex('5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8')
>>> plaintext = a2b_hex('c37b7e6492584340bed1220765460000')
->>> iv = a2b_hex('a65959a6') + long_to_bytes(14, 4)
+>>> iv = a2b_hex('a65959a6') + struct.pack('>I', 14)
>>> ciphertext = wrap(plaintext, key, iv=iv)
>>> unwrap(ciphertext, key, iv=iv) == plaintext
True
@@ -221,7 +221,7 @@ True
If we mangle the IV to look like an RFC 5649 value but with an invalid
padding length we should get an exception.
->>> iv = a2b_hex('a65959a6') + long_to_bytes(12, 4)
+>>> iv = a2b_hex('a65959a6') + struct.pack('>I', 12)
>>> ciphertext = wrap(plaintext, key, iv=iv)
>>> unwrap(ciphertext, key, iv=iv) == plaintext
True
diff --git a/tests/test_write.doctest b/tests/test_write.doctest
index 890c99b..8e847f3 100644
--- a/tests/test_write.doctest
+++ b/tests/test_write.doctest
@@ -21,9 +21,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>> from pskc import PSKC
>>> import datetime
+>>> import os
>>> import sys
>>> import tempfile
->>> from Crypto import Random
>>> from binascii import a2b_hex
>>> from dateutil.tz import tzutc
@@ -412,7 +412,7 @@ decryption combinations.
>>> def test_algorithm(algorithm):
... f = tempfile.NamedTemporaryFile()
... pskc1 = PSKC()
-... pskc1.add_key(secret=Random.get_random_bytes(16))
+... pskc1.add_key(secret=os.urandom(16))
... pskc1.encryption.setup_preshared_key(algorithm=algorithm)
... pskc1.write(f.name)
... pskc2 = PSKC(f.name)
https://arthurdejong.org/git/python-pskc/commit/?id=d0eddf88287bce398cb7a55ee20b384e3f764a4d
commit d0eddf88287bce398cb7a55ee20b384e3f764a4d
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sun Sep 24 21:32:55 2017 +0200
Implement our own XML formatting
This avoids a using xml.dom.minidom to indent the XML tree and keep the
attributes ordered alphabetically. This also allows for customisations
to the XML formatting.
diff --git a/pskc/serialiser.py b/pskc/serialiser.py
index 2dc82d4..6c9a5ab 100644
--- a/pskc/serialiser.py
+++ b/pskc/serialiser.py
@@ -30,7 +30,7 @@ class PSKCSerialiser(object):
@classmethod
def serialise_file(cls, pskc, output):
- xml = tostring(cls.serialise_document(pskc)) + '\n'.encode('UTF-8')
+ xml = tostring(cls.serialise_document(pskc))
try:
output.write(xml)
except TypeError: # pragma: no cover (Python 3 specific)
diff --git a/pskc/xml.py b/pskc/xml.py
index bc10c81..56f45bc 100644
--- a/pskc/xml.py
+++ b/pskc/xml.py
@@ -25,6 +25,8 @@ This module provides some utility functions for parsing XML
files.
from __future__ import absolute_import
+from collections import OrderedDict
+
# try to find a usable ElementTree implementation
try: # pragma: no cover (different implementations)
from lxml.etree import parse as xml_parse, tostring as xml_tostring
@@ -176,9 +178,9 @@ def mk_elem(parent, tag=None, text=None, empty=False,
**kwargs):
ns, name = tag.split(':', 1)
tag = '{%s}%s' % (namespaces[ns], name)
if parent is None:
- element = Element(tag)
+ element = Element(tag, OrderedDict())
else:
- element = SubElement(parent, tag)
+ element = SubElement(parent, tag, OrderedDict())
# set text of element
if text is not None:
element.text = _format(text)
@@ -189,9 +191,28 @@ def mk_elem(parent, tag=None, text=None, empty=False,
**kwargs):
return element
+def reformat(element, indent=''):
+ """Reformat the XML tree to have nice wrapping and indenting."""
+ # re-order attributes by alphabet
+ attrib = sorted(element.attrib.items())
+ element.attrib.clear()
+ element.attrib.update(attrib)
+ if len(element) == 0:
+ # clean up inner text
+ if element.text:
+ element.text = element.text.strip()
+ else:
+ # indent children
+ element.text = '\n ' + indent
+ childred = list(element)
+ for child in childred:
+ reformat(child, indent + ' ')
+ childred[-1].tail = '\n' + indent
+ element.tail = '\n' + indent
+
+
def tostring(element):
"""Return a serialised XML document for the element tree."""
- from xml.dom import minidom
# if we are using lxml.etree move namespaces to toplevel element
if hasattr(element, 'nsmap'): # pragma: no cover (only on lxml)
# get all used namespaces
@@ -203,6 +224,11 @@ def tostring(element):
for a in element:
e.append(a)
element = e
+ reformat(element)
xml = xml_tostring(element, encoding='UTF-8')
- return minidom.parseString(xml).toprettyxml(
- indent=' ', encoding='UTF-8').strip()
+ xml_decl = b"<?xml version='1.0' encoding='UTF-8'?>\n"
+ if xml.startswith(xml_decl): # pragma: no cover (only a few cases)
+ xml = xml[len(xml_decl):]
+ return (
+ b'<?xml version="1.0" encoding="UTF-8"?>\n' +
+ xml.replace(b' />', b'/>').strip() + b'\n')
diff --git a/tests/test_write.doctest b/tests/test_write.doctest
index 1bcad0f..890c99b 100644
--- a/tests/test_write.doctest
+++ b/tests/test_write.doctest
@@ -103,7 +103,7 @@ argument).
>>> with open(f.name, 'r') as r:
... x = sys.stdout.write(r.read()) #doctest: +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc">
+<pskc:KeyContainer xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
Version="1.0">
<pskc:KeyPackage>
<pskc:DeviceInfo>
<pskc:Manufacturer>Manufacturer</pskc:Manufacturer>
@@ -197,7 +197,7 @@ Read an encrypted PSKC file and write it out as an
unencrypted file.
>>> pskc.encryption.key_name = None
>>> pskc.write(sys.stdout) #doctest: +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc">
+<pskc:KeyContainer xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
Version="1.0">
<pskc:KeyPackage>
<pskc:Key>
<pskc:Data>
@@ -216,7 +216,7 @@ providing the encryption key.
>>> pskc = PSKC('tests/rfc6030/figure6.pskcxml')
>>> pskc.write(sys.stdout) #doctest: +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+<pskc:KeyContainer xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Version="1.0">
<pskc:EncryptionKey>
<ds:KeyName>Pre-shared-key</ds:KeyName>
</pskc:EncryptionKey>
@@ -274,7 +274,7 @@ Set up an encrypted PSKC file and generate a pre-shared key
for it.
>>> with open(f.name, 'r') as r:
... x = sys.stdout.write(r.read()) #doctest: +ELLIPSIS +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+<pskc:KeyContainer xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Version="1.0">
<pskc:EncryptionKey>
<ds:KeyName>Pre-shared KEY</ds:KeyName>
</pskc:EncryptionKey>
@@ -343,7 +343,7 @@ Use PBKDF2 to derive a key instead of using a pre-shared
key.
>>> with open(f.name, 'r') as r:
... x = sys.stdout.write(r.read()) #doctest: +ELLIPSIS +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:xenc11="http://www.w3.org/2009/xmlenc11#">
+<pskc:KeyContainer xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:xenc11="http://www.w3.org/2009/xmlenc11#" Version="1.0">
<pskc:EncryptionKey>
<xenc11:DerivedKey>
<xenc11:KeyDerivationMethod
Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2">
@@ -488,7 +488,7 @@ result in an empty KeyDerivation element.
>>> pskc.encryption.derivation.algorithm = 'unknown'
>>> pskc.write(sys.stdout) #doctest: +ELLIPSIS +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:xenc11="http://www.w3.org/2009/xmlenc11#">
+<pskc:KeyContainer xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:xenc11="http://www.w3.org/2009/xmlenc11#" Version="1.0">
<pskc:EncryptionKey>
<xenc11:DerivedKey>
<xenc11:KeyDerivationMethod Algorithm="unknown"/>
@@ -511,7 +511,7 @@ We can make the PKKDF2 salt have to be transmitted
out-of-bounds:
>>> pskc.encryption.derivation.pbkdf2_salt = None
>>> pskc.write(sys.stdout) #doctest: +ELLIPSIS +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:xenc11="http://www.w3.org/2009/xmlenc11#">
+<pskc:KeyContainer xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:xenc11="http://www.w3.org/2009/xmlenc11#" Version="1.0">
<pskc:EncryptionKey>
<xenc11:DerivedKey>
<xenc11:KeyDerivationMethod
Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2">
@@ -541,7 +541,7 @@ set on one key end up being applied to both keys.
>>> key = device.add_key(id='pin0', secret='5678')
>>> pskc.write(sys.stdout) #doctest: +ELLIPSIS +REPORT_UDIFF
<?xml version="1.0" encoding="UTF-8"?>
-<pskc:KeyContainer Version="1.0"
xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc">
+<pskc:KeyContainer xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
Version="1.0">
<pskc:KeyPackage>
<pskc:DeviceInfo>
<pskc:Manufacturer>TokenVendorAcme</pskc:Manufacturer>
-----------------------------------------------------------------------
Summary of changes:
pskc/crypto/aeskw.py | 21 ++++++++++++++-------
pskc/crypto/tripledeskw.py | 6 +++---
pskc/encryption.py | 20 +++++++++-----------
pskc/mac.py | 4 ++--
pskc/serialiser.py | 2 +-
pskc/xml.py | 36 +++++++++++++++++++++++++++++++-----
tests/test_aeskw.doctest | 8 ++++----
tests/test_write.doctest | 20 ++++++++++----------
8 files changed, 74 insertions(+), 43 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. 0.5-19-g2c8a9b7,
Commits of the python-pskc project