summaryrefslogtreecommitdiff
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
parent88fbb3b163ac9d965f9fff8ada5e3fd5bfd49d03 (diff)
downloadrsa-31eaa23bb8d818c0f6f9d514e41f7da85029d533.tar.gz
Reinstated some of the backed out changeset 812d745b6bef:
- added support for block size - improved some exceptions
-rwxr-xr-xrsa/core.py7
-rwxr-xr-xrsa/transform.py41
2 files changed, 45 insertions, 3 deletions
diff --git a/rsa/core.py b/rsa/core.py
index 8f989df..2df4be5 100755
--- a/rsa/core.py
+++ b/rsa/core.py
@@ -17,8 +17,11 @@ def encrypt_int(message, ekey, n):
if not type(message) is types.LongType:
raise TypeError("You must pass a long or int")
- if message < 0 or message > n:
- raise OverflowError("The message is too long")
+ if message < 0:
+ raise ValueError('Only non-negative numbers are supported')
+
+ if message > n:
+ raise OverflowError("The message %i is too long for n=%i" % (message, n))
#Note: Bit exponents start at zero (bit counts start at 1) this is correct
safebit = rsa.common.bit_size(n) - 2 # compute safe bit (MSB - 1)
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','-','_'.