summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYesudeep Mangalapilly <yesudeep@gmail.com>2011-08-11 12:03:37 +0530
committerYesudeep Mangalapilly <yesudeep@gmail.com>2011-08-11 12:03:37 +0530
commita5673890cec3d7518726b15d4cecc17c0b55aa4a (patch)
tree49e3c5294d511520ca12ef8a5b9df29dd6d2a8ca
parent7d73cf4398345824eaadf47e31f9c500c612a8b7 (diff)
downloadrsa-a5673890cec3d7518726b15d4cecc17c0b55aa4a.tar.gz
Adds speed tests for int2bytes and old_int2bytes.
* In the following tests, the first speed test for each version of Python checked is the new implementation and the second is the old implementation. $ ./speed.sh int2bytes speed test python2.5 1000 loops, best of 3: 315 usec per loop 100 loops, best of 3: 4.87 msec per loop python2.6 10000 loops, best of 3: 170 usec per loop 100 loops, best of 3: 3.34 msec per loop python2.7 10000 loops, best of 3: 169 usec per loop 100 loops, best of 3: 2.8 msec per loop python3.2 10000 loops, best of 3: 169 usec per loop 100 loops, best of 3: 3.16 msec per loop
-rw-r--r--rsa/transform.py71
-rwxr-xr-xspeed.sh15
-rw-r--r--tests/test_transform.py10
3 files changed, 89 insertions, 7 deletions
diff --git a/rsa/transform.py b/rsa/transform.py
index 6503cf1..8d3a461 100644
--- a/rsa/transform.py
+++ b/rsa/transform.py
@@ -21,9 +21,11 @@ From bytes to a number, number to bytes, etc.
from __future__ import absolute_import
+import types
import binascii
from struct import pack
-from rsa._compat import is_integer, b
+from rsa import common
+from rsa._compat import is_integer, b, byte
ZERO_BYTE = b('\x00')
@@ -43,7 +45,7 @@ def bytes2int(raw_bytes):
return int(binascii.hexlify(raw_bytes), 16)
-def int2bytes(number, block_size=None):
+def old_int2bytes(number, block_size=0):
r'''Converts a number to a string of bytes.
@param number: the number to convert
@@ -55,6 +57,65 @@ def int2bytes(number, block_size=None):
bytes than fit into the block.
+ >>> old_int2bytes(123456789)
+ b'\x07[\xcd\x15'
+ >>> bytes2int(int2bytes(123456789))
+ 123456789
+
+ >>> old_int2bytes(123456789, 6)
+ b'\x00\x00\x07[\xcd\x15'
+ >>> bytes2int(int2bytes(123456789, 128))
+ 123456789
+
+ >>> old_int2bytes(123456789, 3)
+ Traceback (most recent call last):
+ ...
+ OverflowError: Needed 4 bytes for number, but block size is 3
+
+ '''
+
+ # Type checking
+ if not is_integer(number):
+ raise TypeError("You must pass an integer for 'number', not %s" %
+ number.__class__)
+
+ if number < 0:
+ raise ValueError('Negative numbers cannot be used: %i' % number)
+
+ # Do some bounds checking
+ needed_bytes = common.byte_size(number)
+ if block_size > 0:
+ if needed_bytes > block_size:
+ raise OverflowError('Needed %i bytes for number, but block size '
+ 'is %i' % (needed_bytes, block_size))
+
+ # Convert the number to bytes.
+ raw_bytes = []
+ while number > 0:
+ raw_bytes.insert(0, byte(number & 0xFF))
+ number >>= 8
+
+ # Pad with zeroes to fill the block
+ if block_size > 0:
+ padding = (block_size - needed_bytes) * ZERO_BYTE
+ else:
+ padding = b('')
+
+ return padding + b('').join(raw_bytes)
+
+
+def int2bytes(number, block_size=None):
+ """Converts a number to a string of bytes.
+
+ @param number: the number to convert
+ @param block_size: the number of bytes to output. If the number encoded to
+ bytes is less than this, the block will be zero-padded. When not given,
+ the returned block is not padded.
+
+ @throws OverflowError when block_size is given and the number takes up more
+ bytes than fit into the block.
+
+
>>> int2bytes(123456789)
'\x07[\xcd\x15'
>>> bytes2int(int2bytes(123456789))
@@ -69,9 +130,7 @@ def int2bytes(number, block_size=None):
Traceback (most recent call last):
...
OverflowError: Need 4 bytes for number, but block size is 3
-
- '''
-
+ """
# Type checking
if not is_integer(number):
raise TypeError("You must pass an integer for 'number', not %s" %
@@ -95,7 +154,7 @@ def int2bytes(number, block_size=None):
if x != ZERO_BYTE[0]:
break
- if block_size > 0:
+ if block_size is not None and block_size > 0:
# Bounds checking. We're not doing this up-front because the
# most common use case is not specifying a chunk size. In the worst
# case, the number will already have been converted to bytes above.
diff --git a/speed.sh b/speed.sh
new file mode 100755
index 0000000..17f1ea4
--- /dev/null
+++ b/speed.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+echo "int2bytes speed test"
+echo "python2.5"
+python2.5 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
+python2.5 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
+echo "python2.6"
+python2.6 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
+python2.6 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
+echo "python2.7"
+python2.7 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
+python2.7 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
+echo "python3.2"
+python3 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
+python3 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
diff --git a/tests/test_transform.py b/tests/test_transform.py
index ecc1a30..9bd3c6d 100644
--- a/tests/test_transform.py
+++ b/tests/test_transform.py
@@ -3,7 +3,7 @@
import unittest2
from rsa._compat import b
-from rsa.transform import int2bytes
+from rsa.transform import int2bytes, old_int2bytes
class Test_integer_to_bytes(unittest2.TestCase):
@@ -12,13 +12,21 @@ class Test_integer_to_bytes(unittest2.TestCase):
b('\x00\x00\x07[\xcd\x15'))
self.assertEqual(int2bytes(123456789, 7),
b('\x00\x00\x00\x07[\xcd\x15'))
+ self.assertEqual(old_int2bytes(123456789, 6),
+ b('\x00\x00\x07[\xcd\x15'))
+ self.assertEqual(old_int2bytes(123456789, 7),
+ b('\x00\x00\x00\x07[\xcd\x15'))
def test_raises_OverflowError_when_chunk_size_is_insufficient(self):
self.assertRaises(OverflowError, int2bytes, 123456789, 3)
self.assertRaises(OverflowError, int2bytes, 299999999999, 4)
+ self.assertRaises(OverflowError, old_int2bytes, 123456789, 3)
+ self.assertRaises(OverflowError, old_int2bytes, 299999999999, 4)
def test_raises_ValueError_when_negative_integer(self):
self.assertRaises(ValueError, int2bytes, -1)
+ self.assertRaises(ValueError, old_int2bytes, -1)
def test_raises_TypeError_when_not_integer(self):
self.assertRaises(TypeError, int2bytes, None)
+ self.assertRaises(TypeError, old_int2bytes, None)