From f49fd0e1b57071e52200806d095679753fe36e17 Mon Sep 17 00:00:00 2001 From: Legrandin Date: Wed, 7 May 2014 12:20:46 +0200 Subject: Extended fix for the RSA boundary check --- lib/Crypto/PublicKey/RSA.py | 5 +++++ lib/Crypto/PublicKey/_slowmath.py | 2 +- lib/Crypto/SelfTest/PublicKey/test_RSA.py | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py index a5afeb9..c323295 100644 --- a/lib/Crypto/PublicKey/RSA.py +++ b/lib/Crypto/PublicKey/RSA.py @@ -229,6 +229,8 @@ class _RSAobj(pubkey.pubkey): return pubkey.pubkey.verify(self, M, signature) def _encrypt(self, c, K): + if not 0 < c < self.n: + raise ValueError("Plaintext too large") return (self.key._encrypt(c),) def _decrypt(self, c): @@ -238,6 +240,9 @@ class _RSAobj(pubkey.pubkey): # going to replace the Crypto.PublicKey API soon # anyway. + if not 0 < ciphertext < self.n: + raise ValueError("Ciphertext too large") + # 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) diff --git a/lib/Crypto/PublicKey/_slowmath.py b/lib/Crypto/PublicKey/_slowmath.py index d926596..f28ea4c 100644 --- a/lib/Crypto/PublicKey/_slowmath.py +++ b/lib/Crypto/PublicKey/_slowmath.py @@ -40,7 +40,7 @@ class error(Exception): class _RSAKey(object): def _blind(self, m, r): # compute r**e * m (mod n) - return m * pow(r, self.e, self.n) + return (m * pow(r, self.e, self.n)) % self.n def _unblind(self, m, r): # compute m / r (mod n) diff --git a/lib/Crypto/SelfTest/PublicKey/test_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_RSA.py index 32bed88..16310f7 100644 --- a/lib/Crypto/SelfTest/PublicKey/test_RSA.py +++ b/lib/Crypto/SelfTest/PublicKey/test_RSA.py @@ -219,6 +219,17 @@ class RSATest(unittest.TestCase): ciphertext_result = rsaObj.encrypt(plaintext, b(""))[0] self.assertEqual(ciphertext_result, ciphertext) + def test_raw_rsa_boundary(self): + # The argument of every RSA raw operation (encrypt/decrypt) must be positive + # and no larger than the modulus + rsa_obj = self.rsa.generate(1024) + + self.assertRaises(ValueError, rsa_obj.decrypt, (rsa_obj.n,)) + self.assertRaises(ValueError, rsa_obj.encrypt, rsa_obj.n, b("")) + + self.assertRaises(ValueError, rsa_obj.decrypt, (0,)) + self.assertRaises(ValueError, rsa_obj.encrypt, 0, b("")) + def _check_private_key(self, rsaObj): # Check capabilities self.assertEqual(1, rsaObj.has_private()) -- cgit v1.2.1