summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Collins <elic@assurancetechnologies.com>2011-06-17 00:17:40 -0400
committerEli Collins <elic@assurancetechnologies.com>2011-06-17 00:17:40 -0400
commit3f7c43556e647df2b2993fc4cf47a87933e276cc (patch)
tree03c9005da2e56c7fe02b1cde674ff10f95541304
parent96e8745f3673c99a31e03b30a75825a934b22507 (diff)
downloadpasslib-3f7c43556e647df2b2993fc4cf47a87933e276cc.tar.gz
utils.des now py3 compat; fixed some other utils as well
-rw-r--r--passlib/tests/test_utils.py6
-rw-r--r--passlib/utils/__init__.py23
-rw-r--r--passlib/utils/des.py31
3 files changed, 40 insertions, 20 deletions
diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py
index bed90aa..e43b181 100644
--- a/passlib/tests/test_utils.py
+++ b/passlib/tests/test_utils.py
@@ -96,7 +96,7 @@ class DesTest(TestCase):
test_des_vectors = [
(line[4:20], line[21:37], line[38:54])
for line in
- """ 0000000000000000 0000000000000000 8CA64DE9C1B123A7
+b(""" 0000000000000000 0000000000000000 8CA64DE9C1B123A7
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58
3000000000000000 1000000000000001 958E6E627A05557B
1111111111111111 1111111111111111 F40379AB9E0EC533
@@ -130,7 +130,7 @@ class DesTest(TestCase):
FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE
0123456789ABCDEF 0000000000000000 D5D44FF720683D0D
FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2
- """.split("\n") if line.strip()
+ """).split(b("\n")) if line.strip()
]
def test_des_encrypt_block(self):
@@ -143,7 +143,7 @@ class DesTest(TestCase):
#test 7 byte key
#FIXME: use a better key
- k,p,c = '00000000000000', 'FFFFFFFFFFFFFFFF', '355550B2150E2451'
+ k,p,c = b('00000000000000'), b('FFFFFFFFFFFFFFFF'), b('355550B2150E2451')
k = unhexlify(k)
p = unhexlify(p)
c = unhexlify(c)
diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py
index fa37035..bebf7a8 100644
--- a/passlib/utils/__init__.py
+++ b/passlib/utils/__init__.py
@@ -372,13 +372,20 @@ bord = ord
# end Py2k #
def bchrs(*values):
- "takes series of ints, returns bytes"
+ "takes series of ints, returns bytes; like chr() but for bytes, and w/ multi args"
# Py2k #
return bjoin(chr(v) for v in values)
# Py3k #
#return bytes(values)
# end Py3k #
+# Py2k #
+def bjoin_ints(values):
+ return bjoin(chr(v) for v in values)
+# Py3k #
+#bjoin_ints = bytes
+# end Py3k #
+
#=================================================================================
#numeric helpers
#=================================================================================
@@ -422,21 +429,25 @@ def bytes_to_int(value):
"decode string of bytes as single big-endian integer"
out = 0
for v in value:
- out = (out<<8) | ord(v)
+ out = (out<<8) | bord(v)
return out
def int_to_bytes(value, count):
"encodes integer into single big-endian byte string"
assert value < (1<<(8*count)), "value too large for %d bytes: %d" % (count, value)
- return ''.join(
- chr((value>>s) & 0xff)
+ return bjoin_ints(
+ ((value>>s) & 0xff)
for s in xrange(8*count-8,-8,-8)
)
-_join = "".join
def xor_bytes(left, right):
"perform bitwise-xor of two byte-strings"
- return _join(chr(ord(l) ^ ord(r)) for l, r in zip(left, right))
+ #NOTE: this could use bjoin_ints(), but speed is *really* important here (c.f. PBKDF2)
+ # Py2k #
+ return bjoin(chr(ord(l) ^ ord(r)) for l, r in zip(left, right))
+ # Py3k #
+ #return bytes(l ^ r for l, r in zip(left, right))
+ # end Py3k #
#=================================================================================
#alt base64 encoding
diff --git a/passlib/utils/des.py b/passlib/utils/des.py
index 279c638..88b591d 100644
--- a/passlib/utils/des.py
+++ b/passlib/utils/des.py
@@ -43,7 +43,7 @@ which has some nice notes on how this all works -
#imports
#=========================================================
#pkg
-from passlib.utils import bytes_to_int, int_to_bytes
+from passlib.utils import bytes_to_int, int_to_bytes, bytes, bord, bjoin_ints
#local
__all__ = [
"expand_des_key",
@@ -571,45 +571,54 @@ def permute(c, p):
#=========================================================
#des frontend
#=========================================================
-def expand_des_key(source):
+def expand_des_key(key):
"convert 7 byte des key to 8 byte des key (by adding parity bit every 7 bits)"
+ if not isinstance(key, bytes):
+ raise TypeError("key must be bytes, not %s" % (type(key),))
+
#NOTE: could probably do this much more cleverly and efficiently,
# but no need really given it's use.
#NOTE: the parity bits are generally ignored, including by des_encrypt_block below
- assert len(source) == 7
+ assert len(key) == 7
def iter_bits(source):
for c in source:
- v = ord(c)
+ v = bord(c)
for i in xrange(7,-1,-1):
yield (v>>i) & 1
out = 0
p = 1
- for i, b in enumerate(iter_bits(source)):
+ for i, b in enumerate(iter_bits(key)):
out = (out<<1) + b
p ^= b
if i % 7 == 6:
out = (out<<1) + p
p = 1
- return ''.join(
- chr((out>>s) & 0xFF)
+ return bjoin_ints(
+ ((out>>s) & 0xFF)
for s in xrange(8*7,-8,-8)
)
def des_encrypt_block(key, input):
"""do traditional encryption of a single DES block
- :arg key: 8 byte des key string
- :arg input: 8 byte plaintext string
- :returns: 8 byte ciphertext string
+ :arg key: 8 byte des key
+ :arg input: 8 byte plaintext
+ :returns: 8 byte ciphertext
+
+ all values must be :class:`bytes`
"""
- assert len(input) == 8
+ if not isinstance(key, bytes):
+ raise TypeError("key must be bytes, not %s" % (type(key),))
if len(key) == 7:
key = expand_des_key(key)
assert len(key) == 8
+ if not isinstance(input, bytes):
+ raise TypeError("input must be bytes, not %s" % (type(input),))
+ assert len(input) == 8
input = bytes_to_int(input)
key = bytes_to_int(key)
out = mdes_encrypt_int_block(key, input, 0, 1)