summaryrefslogtreecommitdiff
path: root/rsa/transform.py
diff options
context:
space:
mode:
authorSybren A. St?vel <sybren@stuvel.eu>2011-07-10 01:35:46 +0200
committerSybren A. St?vel <sybren@stuvel.eu>2011-07-10 01:35:46 +0200
commit31eaa23bb8d818c0f6f9d514e41f7da85029d533 (patch)
treee2e1ea230eb30723d6b23b2bc203899a31f7001c /rsa/transform.py
parent88fbb3b163ac9d965f9fff8ada5e3fd5bfd49d03 (diff)
downloadrsa-31eaa23bb8d818c0f6f9d514e41f7da85029d533.tar.gz
Reinstated some of the backed out changeset 812d745b6bef:
- added support for block size - improved some exceptions
Diffstat (limited to 'rsa/transform.py')
-rwxr-xr-xrsa/transform.py41
1 files changed, 40 insertions, 1 deletions
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','-','_'.