summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDwayne C. Litzenberger <dlitz@dlitz.net>2011-02-21 21:11:21 -0500
committerDwayne C. Litzenberger <dlitz@dlitz.net>2011-02-21 21:11:21 -0500
commit4669b04c6f9e4cb895abd227dffc7f6718425a70 (patch)
tree3cb973f402690238c1031055ca30c1b4648a50e7
parent80252248ab1ac8599b946e026dd8895146977903 (diff)
downloadpycrypto-4669b04c6f9e4cb895abd227dffc7f6718425a70.tar.gz
Avoid timing attacks: Do blinded RSA by default
Thanks to Geremy Condra (and others) for pointing out the timing vulnerability.
-rw-r--r--lib/Crypto/PublicKey/RSA.py17
1 files changed, 15 insertions, 2 deletions
diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py
index 6e123d6..b67b6ab 100644
--- a/lib/Crypto/PublicKey/RSA.py
+++ b/lib/Crypto/PublicKey/RSA.py
@@ -29,6 +29,7 @@ __revision__ = "$Id$"
__all__ = ['generate', 'construct', 'error', 'importKey' ]
from Crypto.Util.python_compat import *
+from Crypto.Util.number import getRandomRange
from Crypto.PublicKey import _RSA, _slowmath, pubkey
from Crypto import Random
@@ -44,9 +45,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:
@@ -65,7 +69,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)