diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-06-17 00:17:40 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-06-17 00:17:40 -0400 |
| commit | 3f7c43556e647df2b2993fc4cf47a87933e276cc (patch) | |
| tree | 03c9005da2e56c7fe02b1cde674ff10f95541304 /passlib/utils | |
| parent | 96e8745f3673c99a31e03b30a75825a934b22507 (diff) | |
| download | passlib-3f7c43556e647df2b2993fc4cf47a87933e276cc.tar.gz | |
utils.des now py3 compat; fixed some other utils as well
Diffstat (limited to 'passlib/utils')
| -rw-r--r-- | passlib/utils/__init__.py | 23 | ||||
| -rw-r--r-- | passlib/utils/des.py | 31 |
2 files changed, 37 insertions, 17 deletions
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) |
