From 31eaa23bb8d818c0f6f9d514e41f7da85029d533 Mon Sep 17 00:00:00 2001 From: "Sybren A. St?vel" Date: Sun, 10 Jul 2011 01:35:46 +0200 Subject: Reinstated some of the backed out changeset 812d745b6bef: - added support for block size - improved some exceptions --- rsa/transform.py | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'rsa/transform.py') diff --git a/rsa/transform.py b/rsa/transform.py index 35b7461..076c385 100755 --- a/rsa/transform.py +++ b/rsa/transform.py @@ -9,8 +9,22 @@ import types def bit_size(number): """Returns the number of bits required to hold a specific long number""" + if number < 0: + raise ValueError('Only nonnegative numbers possible: %s' % number) + + if number == 0: + return 1 + return int(math.ceil(math.log(number, 2))) +def byte_size(number): + """Returns the number of bytes required to hold a specific long number. + + The number of bytes is rounded up. + """ + + return int(math.ceil(bit_size(number) / 8.0)) + def bytes2int(bytes): """Converts a list of bytes or an 8-bit string to an integer. @@ -72,7 +86,7 @@ def int2bytes(number, block_size=None): # Do some bounds checking if block_size is not None: - needed_bytes = int(math.ceil(bit_size(number) / 8.0)) + needed_bytes = byte_size(number) if needed_bytes > block_size: raise OverflowError('Needed %i bytes for number, but block size ' 'is %i' % (needed_bytes, block_size)) @@ -92,6 +106,31 @@ def int2bytes(number, block_size=None): return padding + ''.join(bytes) +def block_op(block_provider, block_size, operation): + r'''Generator, applies the operation on each block and yields the result + + Each block is converted to a number, the given operation is applied and then + the resulting number is converted back to a block of data. The resulting + block is yielded. + + @param block_provider: an iterable that iterates over the data blocks. + @param block_size: the used block size + @param operation: a function that accepts an integer and returns an integer + + >>> blocks = ['\x00\x01\x02', '\x03\x04\x05'] + >>> list(block_op(blocks, 3, lambda x: (x + 6))) + ['\x00\x01\x08', '\x03\x04\x0b'] + + ''' + + for block in block_provider: + number = bytes2int(block) + print 'In : %i (%i bytes)' % (number, byte_size(number)) + after_op = operation(number) + print 'Out: %i (%i bytes)' % (after_op, byte_size(after_op)) + yield int2bytes(after_op, block_size) + + def to64(number): """Converts a number in the range of 0 to 63 into base 64 digit character in the range of '0'-'9', 'A'-'Z', 'a'-'z','-','_'. -- cgit v1.2.1