summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLegrandin <gooksankoo@hoiptorrow.mailexpire.com>2012-04-26 00:11:58 +0200
committerLegrandin <gooksankoo@hoiptorrow.mailexpire.com>2012-04-26 00:11:58 +0200
commit52ad7cfa630776f21f3a2600d1b1132ef224ac72 (patch)
tree0d14da47a47230c3c35188a906fab016aa880234
parented2911838732eb40bd729b32e134b8947ebb005d (diff)
parent61420abf2e7f80b9ad340a176e57d9a666fa7ea5 (diff)
downloadpycrypto-52ad7cfa630776f21f3a2600d1b1132ef224ac72.tar.gz
Merge branch 'master' of git://github.com/dlitz/pycrypto
-rw-r--r--lib/Crypto/Random/OSRNG/posix.py27
-rw-r--r--lib/Crypto/SelfTest/Util/test_number.py12
-rw-r--r--src/_fastmath.c35
3 files changed, 62 insertions, 12 deletions
diff --git a/lib/Crypto/Random/OSRNG/posix.py b/lib/Crypto/Random/OSRNG/posix.py
index f88cd77..ca6ac05 100644
--- a/lib/Crypto/Random/OSRNG/posix.py
+++ b/lib/Crypto/Random/OSRNG/posix.py
@@ -25,10 +25,12 @@
__revision__ = "$Id$"
__all__ = ['DevURandomRNG']
+import errno
import os
import stat
from rng_base import BaseRNG
+from Crypto.Util.py3compat import b
class DevURandomRNG(BaseRNG):
@@ -46,7 +48,6 @@ class DevURandomRNG(BaseRNG):
raise TypeError("%r is not a character special device" % (self.name,))
self.__file = f
- self._read = f.read
BaseRNG.__init__(self)
@@ -54,7 +55,29 @@ class DevURandomRNG(BaseRNG):
self.__file.close()
def _read(self, N):
- return self.__file.read(N)
+ # Starting with Python 3 open with buffering=0 returns a FileIO object.
+ # FileIO.read behaves like read(2) and not like fread(3) and thus we
+ # have to handle the case that read returns less data as requested here
+ # more carefully.
+ data = b("")
+ while len(data) < N:
+ try:
+ d = self.__file.read(N - len(data))
+ except IOError, e:
+ # read(2) has been interrupted by a signal; redo the read
+ if e.errno == errno.EINTR:
+ continue
+ raise
+
+ if d is None:
+ # __file is in non-blocking mode and no data is available
+ return data
+ if len(d) == 0:
+ # __file is in blocking mode and arrived at EOF
+ return data
+
+ data += d
+ return data
def new(*args, **kwargs):
return DevURandomRNG(*args, **kwargs)
diff --git a/lib/Crypto/SelfTest/Util/test_number.py b/lib/Crypto/SelfTest/Util/test_number.py
index 7a74e3a..0502e9e 100644
--- a/lib/Crypto/SelfTest/Util/test_number.py
+++ b/lib/Crypto/SelfTest/Util/test_number.py
@@ -252,10 +252,14 @@ class MiscTests(unittest.TestCase):
def test_isPrime(self):
"""Util.number.isPrime"""
+ self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime
+ self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime
+ self.assertEqual(number.isPrime(1), False) # Regression test: isPrime(1) caused some versions of PyCrypto to crash.
self.assertEqual(number.isPrime(2), True)
self.assertEqual(number.isPrime(3), True)
self.assertEqual(number.isPrime(4), False)
self.assertEqual(number.isPrime(2L**1279-1), True)
+ self.assertEqual(number.isPrime(-(2L**1279-1)), False) # Regression test: negative numbers should not be prime
# test some known gmp pseudo-primes taken from
# http://www.trnicely.net/misc/mpzspsp.html
for composite in (43 * 127 * 211, 61 * 151 * 211, 15259 * 30517,
@@ -272,6 +276,14 @@ class MiscTests(unittest.TestCase):
self.assertEqual(number.size(0xa2ba40),8*3)
self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5L), 1024)
+ def test_negative_number_roundtrip_mpzToLongObj_longObjToMPZ(self):
+ """Test that mpzToLongObj and longObjToMPZ (internal functions) roundtrip negative numbers correctly."""
+ n = -100000000000000000000000000000000000L
+ e = 2L
+ k = number._fastmath.rsa_construct(n, e)
+ self.assertEqual(n, k.n)
+ self.assertEqual(e, k.e)
+
def get_tests(config={}):
from Crypto.SelfTest.st_common import list_test_cases
return list_test_cases(MiscTests)
diff --git a/src/_fastmath.c b/src/_fastmath.c
index 4b5dede..b8b24b6 100644
--- a/src/_fastmath.c
+++ b/src/_fastmath.c
@@ -66,19 +66,26 @@ static void
longObjToMPZ (mpz_t m, PyLongObject * p)
{
int size, i;
+ long negative;
mpz_t temp, temp2;
mpz_init (temp);
mpz_init (temp2);
#ifdef IS_PY3K
- if (p->ob_base.ob_size > 0)
+ if (p->ob_base.ob_size > 0) {
size = p->ob_base.ob_size;
- else
+ negative = 1;
+ } else {
size = -p->ob_base.ob_size;
+ negative = -1;
+ }
#else
- if (p->ob_size > 0)
+ if (p->ob_size > 0) {
size = p->ob_size;
- else
+ negative = 1;
+ } else {
size = -p->ob_size;
+ negative = -1;
+ }
#endif
mpz_set_ui (m, 0);
for (i = 0; i < size; i++)
@@ -91,6 +98,7 @@ longObjToMPZ (mpz_t m, PyLongObject * p)
#endif
mpz_add (m, m, temp2);
}
+ mpz_mul_si(m, m, negative);
mpz_clear (temp);
mpz_clear (temp2);
}
@@ -104,12 +112,15 @@ mpzToLongObj (mpz_t m)
#else
int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT;
#endif
+ int sgn;
int i;
mpz_t temp;
PyLongObject *l = _PyLong_New (size);
if (!l)
return NULL;
- mpz_init_set (temp, m);
+ sgn = mpz_sgn(m);
+ mpz_init(temp);
+ mpz_mul_si(temp, m, sgn);
for (i = 0; i < size; i++)
{
#ifdef IS_PY3K
@@ -124,9 +135,9 @@ mpzToLongObj (mpz_t m)
while ((i > 0) && (l->ob_digit[i - 1] == 0))
i--;
#ifdef IS_PY3K
- l->ob_base.ob_size = i;
+ l->ob_base.ob_size = i * sgn;
#else
- l->ob_size = i;
+ l->ob_size = i * sgn;
#endif
mpz_clear (temp);
return (PyObject *) l;
@@ -1062,7 +1073,7 @@ isPrime (PyObject * self, PyObject * args, PyObject * kwargs)
longObjToMPZ (n, (PyLongObject *) l);
Py_BEGIN_ALLOW_THREADS;
- /* first check if n is known to be prime and do some trail division */
+ /* first check if n is known to be prime and do some trial division */
for (i = 0; i < SIEVE_BASE_SIZE; ++i)
{
if (mpz_cmp_ui (n, sieve_base[i]) == 0)
@@ -1342,8 +1353,12 @@ rabinMillerTest (mpz_t n, int rounds, PyObject *randfunc)
}
Py_BEGIN_ALLOW_THREADS;
- if ((mpz_tstbit (n, 0) == 0) || (mpz_cmp_ui (n, 3) < 0))
- return (mpz_cmp_ui (n, 2) == 0);
+ /* check special cases (n==2, n even, n < 2) */
+ if ((mpz_tstbit (n, 0) == 0) || (mpz_cmp_ui (n, 3) < 0)) {
+ return_val = (mpz_cmp_ui (n, 2) == 0);
+ Py_BLOCK_THREADS;
+ return return_val;
+ }
mpz_init (tmp);
mpz_init (n_1);