summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Sundman <anders@4zm.org>2011-05-19 19:55:12 +0200
committerAnders Sundman <anders@4zm.org>2011-05-19 19:55:12 +0200
commite226cd7f963d2c21c839071d10ed3102b758fdf6 (patch)
treee3b0c6ade1c88dacb0406dfc23870667868a3c28
parent606b17789c1869597466c714134f138c51b938f5 (diff)
parent4669b04c6f9e4cb895abd227dffc7f6718425a70 (diff)
downloadpycrypto-e226cd7f963d2c21c839071d10ed3102b758fdf6.tar.gz
Merge from dlitz/master
-rw-r--r--README7
-rw-r--r--lib/Crypto/PublicKey/RSA.py19
-rw-r--r--python-3-changes.txt218
-rw-r--r--setup.py22
-rw-r--r--src/_fastmath.c18
5 files changed, 161 insertions, 123 deletions
diff --git a/README b/README
index 7196b63..212d4e6 100644
--- a/README
+++ b/README
@@ -86,6 +86,13 @@ possible, track down the bug and include a patch that fixes it,
provided that you are able to meet the eligibility requirements at
http://www.pycrypto.org/submission-requirements/.
+It is possible to test a single sub-package or a single module only, for instance
+when you investigate why certain tests fail and don't want to run the whole
+suite each time. Use "python setup.py test --module=name", where 'name'
+is either a sub-package (Cipher, PublicKey, etc) or a module (Cipher.DES,
+PublicKey.RSA, etc).
+To further cut test coverage, pass also the option "--skip-slow-tests".
+
To install the package under the site-packages directory of
your Python installation, run "python setup.py install".
diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py
index d95f2cf..0e0f2a1 100644
--- a/lib/Crypto/PublicKey/RSA.py
+++ b/lib/Crypto/PublicKey/RSA.py
@@ -33,6 +33,9 @@ if sys.version_info[0] == 2 and sys.version_info[1] == 1:
from Crypto.Util.py21compat import *
from Crypto.Util.py3compat import *
+
+from Crypto.Util.number import getRandomRange
+
from Crypto.PublicKey import _RSA, _slowmath, pubkey
from Crypto import Random
@@ -47,9 +50,12 @@ except ImportError:
class _RSAobj(pubkey.pubkey):
keydata = ['n', 'e', 'd', 'p', 'q', 'u']
- def __init__(self, implementation, key):
+ def __init__(self, implementation, key, randfunc=None):
self.implementation = implementation
self.key = key
+ if randfunc is None:
+ randfunc = Random.new().read
+ self._randfunc = randfunc
def __getattr__(self, attrname):
if attrname in self.keydata:
@@ -68,7 +74,16 @@ class _RSAobj(pubkey.pubkey):
# instead, but this is more compatible and we're
# going to replace the Crypto.PublicKey API soon
# anyway.
- return self.key._decrypt(ciphertext)
+
+ # Blinded RSA decryption (to prevent timing attacks):
+ # Step 1: Generate random secret blinding factor r, such that 0 < r < n-1
+ r = getRandomRange(1, self.key.n-1, randfunc=self._randfunc)
+ # Step 2: Compute c' = c * r**e mod n
+ cp = self.key._blind(ciphertext, r)
+ # Step 3: Compute m' = c'**d mod n (ordinary RSA decryption)
+ mp = self.key._decrypt(cp)
+ # Step 4: Compute m = m**(r-1) mod n
+ return self.key._unblind(mp, r)
def _blind(self, m, r):
return self.key._blind(m, r)
diff --git a/python-3-changes.txt b/python-3-changes.txt
index ca6f5a6..b135bfe 100644
--- a/python-3-changes.txt
+++ b/python-3-changes.txt
@@ -1,109 +1,109 @@
-Py code:
-
-setup.py invokes 2to3 automatically. This handles int/long and print issues,
- among others.
-setup.py will touch nt.py on win32 after build and build again. This is
- necessary so 2to3 can do its magic on that file.
-
-There are still a lot of places in the code that need manual attention even
- with 2to3. They mostly have to do with string (2.x) vs. byte/unicode (3.x)
- representation
-
-Use "if sys.version_info[0] == 2:" where needed. Ideally, most of the
- conditional code can be in py3compat.
-
-Replace str(x) with bstr(x) if bytes were intended. Becomes str(x) in 2.x and
- bytes(x) in 3.x through py3compat module.
-Replace chr(x) with bchr(x) if bytes were intended. Becomes chr(x) in 2.x and
- bytes([x]) in 3.x through py3compat module.
-Replace ord(x) with bord(x) if bytes were intended. Becomes ord(x) in 2.x and
- x in 3.x through py3compat module.
-
-Comparing a string index to a string literal needs to be changed in 3.x, as
- b'string'[0] returns an integer, not b's'.
-The comparison can be fixed by indexing the right side, too:
- "if s[0]==b('\x30')[0]:" or "if self.typeTag!=self.typeTags['SEQUENCE'][0]:"
-
-String literals need to be bytes if bytes were intended.
-Replace "x" with b("x") if bytes were intended. Becomes "x" in 2.x, and
- s.encode("x","latin-1") in 3.x through py3compat module.
-For example, '"".join' is replaced by 'b("").join', and 's = ""' becomes
- 's = b("")'.
-Search for \x to find literals that may have been intended as byte strings
-!! However, where a human-readable ASCII text string output was intended,
- such as in AllOrNothing.undigest(), leave as a string literal !!
-
-Only load py21compat.py
- "if sys.version_info[0] == 2 and sys.version_info[1] == 1:" .
- The assignment to True, False generates syntax errors in 3.x, and >= 2.2 don't
- need the compatibility code.
-
-Where print is used with >> to redirect, use a separate function instead.
- See setup.py for an example
-
-The string module has been changed in 3.x. It lost join and split, maketrans
- now expects bytes, and so on.
-Replace string.join(a,b) with b.join(a).
-Replace string.split(a) with a.split().
-Replace body of white-space-stripping functions with 'return "".join(s.split())'
-
-Integer division via the "/" operator can return a float in 3.x. This causes
- issues in Util.number.getStrongPrime. As 2.1 does not support the "//"
- operator, divmod(a,b)[0] is used instead, to conform with an existing practice
- throughout the rest of the pycrypto code base.
-
-Do not use assert_/failUnless or failIf. These are deprecated and are scheduled
- to be removed in Python 3.3 and 3.4.
-Use instead assertEqual(expr,True) for assert_ and assertEqual(expr,False) for
- failIf
-
-Added unit tests for Crypto.Random.random. Fixed random.shuffle().
-random.sample() changed to no longer fail on Python 2.1.
-
-Added unit test for Crypto.Protocol.AllOrNothing.
-AllOrNothing changed to no longer fail occasionally.
-
-C code:
-
-Extended "pycrypto_compat.h". It handles #define's for Python 3.x forward
- compatibility
-
-#include "pycrypto_compat.h"
-// All other local includes after this, so they can benefit from the
-// definitions in pycrypto_compat.h
-
-The compat header #defines IS_PY3K if compiling on 3.x
-The compat header #defines PyBytes_*, PyUnicode_*, PyBytesObject to resolve to
- their PyString* counterparts if compiling on 2.x.
-PyLong_* can be dangerous depending on code construct (think an if that runs
- PyInt_* with else PyLong_*),
-therefore it is #defined in each individual module if needed and safe to do so.
-
-PyString_* has been replaced with PyBytes_* or PyUnicode_* depending on intent
-PyStringObject has been replaced with PyBytesObject or PyUnicodeObject
- depending on intent.
-PyInt_* has been replaced with PyLong_*, where safe to do (in all cases so far)
-
-The C code uses "#ifdef IS_PY3K" liberally.
-Code duplication has been avoided.
-
-Module initialization and module structure differ significantly in 3.x.
- Conditionals take care of it.
-
-myModuleType.ob_type assignment conditionally becomes PyTypeReady for 3.x.
-
-getattr cannot be used to check against custom attributes in 3.x. For 3.x,
- conditional code uses getattro and PyUnicode_CompareWithASCIIString instead
- of strcmp
-
-hexdigest() needed to be changed to return a Unicode object with 3.x
-
-
-TODO for extra credit:
-- Check for type of string in functions and throw an error when it's not
- correct. While at it, ensure that functions observe the guidelines below
- re type.
- This is friendlier than just relying on Python's errors.
-- Make sure DerSequence slicing is tested, since I took the explicit slice
- functions away in 3.x
-
+Py code:
+
+setup.py invokes 2to3 automatically. This handles int/long and print issues,
+ among others.
+setup.py will touch nt.py on win32 after build and build again. This is
+ necessary so 2to3 can do its magic on that file.
+
+There are still a lot of places in the code that need manual attention even
+ with 2to3. They mostly have to do with string (2.x) vs. byte/unicode (3.x)
+ representation
+
+Use "if sys.version_info[0] == 2:" where needed. Ideally, most of the
+ conditional code can be in py3compat.
+
+Replace str(x) with bstr(x) if bytes were intended. Becomes str(x) in 2.x and
+ bytes(x) in 3.x through py3compat module.
+Replace chr(x) with bchr(x) if bytes were intended. Becomes chr(x) in 2.x and
+ bytes([x]) in 3.x through py3compat module.
+Replace ord(x) with bord(x) if bytes were intended. Becomes ord(x) in 2.x and
+ x in 3.x through py3compat module.
+
+Comparing a string index to a string literal needs to be changed in 3.x, as
+ b'string'[0] returns an integer, not b's'.
+The comparison can be fixed by indexing the right side, too:
+ "if s[0]==b('\x30')[0]:" or "if self.typeTag!=self.typeTags['SEQUENCE'][0]:"
+
+String literals need to be bytes if bytes were intended.
+Replace "x" with b("x") if bytes were intended. Becomes "x" in 2.x, and
+ s.encode("x","latin-1") in 3.x through py3compat module.
+For example, '"".join' is replaced by 'b("").join', and 's = ""' becomes
+ 's = b("")'.
+Search for \x to find literals that may have been intended as byte strings
+!! However, where a human-readable ASCII text string output was intended,
+ such as in AllOrNothing.undigest(), leave as a string literal !!
+
+Only load py21compat.py
+ "if sys.version_info[0] == 2 and sys.version_info[1] == 1:" .
+ The assignment to True, False generates syntax errors in 3.x, and >= 2.2 don't
+ need the compatibility code.
+
+Where print is used with >> to redirect, use a separate function instead.
+ See setup.py for an example
+
+The string module has been changed in 3.x. It lost join and split, maketrans
+ now expects bytes, and so on.
+Replace string.join(a,b) with b.join(a).
+Replace string.split(a) with a.split().
+Replace body of white-space-stripping functions with 'return "".join(s.split())'
+
+Integer division via the "/" operator can return a float in 3.x. This causes
+ issues in Util.number.getStrongPrime. As 2.1 does not support the "//"
+ operator, divmod(a,b)[0] is used instead, to conform with an existing practice
+ throughout the rest of the pycrypto code base.
+
+Do not use assert_/failUnless or failIf. These are deprecated and are scheduled
+ to be removed in Python 3.3 and 3.4.
+Use instead assertEqual(expr,True) for assert_ and assertEqual(expr,False) for
+ failIf
+
+Added unit tests for Crypto.Random.random. Fixed random.shuffle().
+random.sample() changed to no longer fail on Python 2.1.
+
+Added unit test for Crypto.Protocol.AllOrNothing.
+AllOrNothing changed to no longer fail occasionally.
+
+C code:
+
+Extended "pycrypto_compat.h". It handles #define's for Python 3.x forward
+ compatibility
+
+#include "pycrypto_compat.h"
+// All other local includes after this, so they can benefit from the
+// definitions in pycrypto_compat.h
+
+The compat header #defines IS_PY3K if compiling on 3.x
+The compat header #defines PyBytes_*, PyUnicode_*, PyBytesObject to resolve to
+ their PyString* counterparts if compiling on 2.x.
+PyLong_* can be dangerous depending on code construct (think an if that runs
+ PyInt_* with else PyLong_*),
+therefore it is #defined in each individual module if needed and safe to do so.
+
+PyString_* has been replaced with PyBytes_* or PyUnicode_* depending on intent
+PyStringObject has been replaced with PyBytesObject or PyUnicodeObject
+ depending on intent.
+PyInt_* has been replaced with PyLong_*, where safe to do (in all cases so far)
+
+The C code uses "#ifdef IS_PY3K" liberally.
+Code duplication has been avoided.
+
+Module initialization and module structure differ significantly in 3.x.
+ Conditionals take care of it.
+
+myModuleType.ob_type assignment conditionally becomes PyTypeReady for 3.x.
+
+getattr cannot be used to check against custom attributes in 3.x. For 3.x,
+ conditional code uses getattro and PyUnicode_CompareWithASCIIString instead
+ of strcmp
+
+hexdigest() needed to be changed to return a Unicode object with 3.x
+
+
+TODO for extra credit:
+- Check for type of string in functions and throw an error when it's not
+ correct. While at it, ensure that functions observe the guidelines below
+ re type.
+ This is friendlier than just relying on Python's errors.
+- Make sure DerSequence slicing is tested, since I took the explicit slice
+ functions away in 3.x
+
diff --git a/setup.py b/setup.py
index d53fdc6..63f5d57 100644
--- a/setup.py
+++ b/setup.py
@@ -267,14 +267,17 @@ class TestCommand(Command):
description = "Run self-test"
+ # Long option name, short option name, description
user_options = [
('skip-slow-tests', None,
- 'Skip slow tests')
+ 'Skip slow tests'),
+ ('module=', 'm', 'Test a single module (e.g. Cipher, PublicKey)')
]
def initialize_options(self):
self.build_dir = None
self.skip_slow_tests = None
+ self.module = None
def finalize_options(self):
self.set_undefined_options('install', ('build_lib', 'build_dir'))
@@ -287,8 +290,21 @@ class TestCommand(Command):
try:
sys.path.insert(0, self.build_dir)
from Crypto import SelfTest
- SelfTest.run(verbosity=self.verbose, stream=sys.stdout,
- config=self.config)
+ moduleObj = None
+ if self.module:
+ if self.module.count('.')==0:
+ # Test a whole a sub-package
+ full_module = "Crypto.SelfTest." + self.module
+ module_name = self.module
+ else:
+ # Test only a module
+ # Assume only one dot is present
+ comps = self.module.split('.')
+ module_name = "test_" + comps[1]
+ full_module = "Crypto.SelfTest." + comps[0] + "." + module_name
+ # Import sub-package or module
+ moduleObj = __import__( full_module, globals(), locals(), module_name )
+ SelfTest.run(module=moduleObj, verbosity=self.verbose, stream=sys.stdout, config=self.config)
finally:
# Restore sys.path
sys.path[:] = old_path
diff --git a/src/_fastmath.c b/src/_fastmath.c
index fe3fde3..3b81a6b 100644
--- a/src/_fastmath.c
+++ b/src/_fastmath.c
@@ -172,7 +172,7 @@ dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s)
return 1;
}
mpz_init (temp);
- mpz_powm (r, key->g, k, key->p);
+ mpz_powm_sec (r, key->g, k, key->p);
mpz_mod (r, r, key->q);
mpz_invert (s, k, key->q);
mpz_mul (temp, key->x, r);
@@ -201,8 +201,8 @@ dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s)
mpz_mod (u1, u1, key->q);
mpz_mul (u2, r, w);
mpz_mod (u2, u2, key->q);
- mpz_powm (v1, key->g, u1, key->p);
- mpz_powm (v2, key->y, u2, key->p);
+ mpz_powm_sec (v1, key->g, u1, key->p);
+ mpz_powm_sec (v2, key->y, u2, key->p);
mpz_mul (w, v1, v2);
mpz_mod (w, w, key->p);
mpz_mod (w, w, key->q);
@@ -226,7 +226,7 @@ rsaEncrypt (rsaKey * key, mpz_t v)
{
return 1;
}
- mpz_powm (v, v, key->e, key->n);
+ mpz_powm_sec (v, v, key->e, key->n);
return 0;
}
@@ -254,11 +254,11 @@ rsaDecrypt (rsaKey * key, mpz_t v)
/* m1 = c ^ (d mod (p-1)) mod p */
mpz_sub_ui(h, key->p, 1);
mpz_fdiv_r(h, key->d, h);
- mpz_powm(m1, v, h, key->p);
+ mpz_powm_sec(m1, v, h, key->p);
/* m2 = c ^ (d mod (q-1)) mod q */
mpz_sub_ui(h, key->q, 1);
mpz_fdiv_r(h, key->d, h);
- mpz_powm(m2, v, h, key->q);
+ mpz_powm_sec(m2, v, h, key->q);
/* h = u * ( m2 - m1 ) mod q */
mpz_sub(h, m2, m1);
if (mpz_sgn(h)==-1)
@@ -277,7 +277,7 @@ rsaDecrypt (rsaKey * key, mpz_t v)
}
/* slow */
- mpz_powm (v, v, key->d, key->n);
+ mpz_powm_sec (v, v, key->d, key->n);
return 0;
}
@@ -292,7 +292,7 @@ rsaBlind (rsaKey * key, mpz_t v, mpz_t b)
{
return 2;
}
- mpz_powm (b, b, key->e, key->n);
+ mpz_powm_sec (b, b, key->e, key->n);
mpz_mul (v, v, b);
mpz_mod (v, v, key->n);
return 0;
@@ -1249,7 +1249,7 @@ rabinMillerTest (mpz_t n, int rounds, PyObject *randfunc)
}
} while (base_was_tested);
mpz_init_set (tested[i], a);
- mpz_powm (z, a, m, n);
+ mpz_powm_sec (z, a, m, n);
if ((mpz_cmp_ui (z, 1) == 0) || (mpz_cmp (z, n_1) == 0))
continue;
composite = 1;