summaryrefslogtreecommitdiff
path: root/lib/Crypto/PublicKey
diff options
context:
space:
mode:
authorLegrandin <gooksankoo@hoiptorrow.mailexpire.com>2011-01-16 21:44:10 +0100
committerLegrandin <gooksankoo@hoiptorrow.mailexpire.com>2011-01-16 21:44:10 +0100
commita2fdd4bada1ef39f2bcf554e30c33d1e4b027132 (patch)
treeeaf3ed05338331de1d26735361f0fce69581c914 /lib/Crypto/PublicKey
parent60d83b2deaebb65562e87a8cf81dd5ff0a7f8693 (diff)
downloadpycrypto-a2fdd4bada1ef39f2bcf554e30c33d1e4b027132.tar.gz
FIX BUG 702835. When importing an DER RSA private key, u (that is, p^{-1} mod q) must be computed manually. RSA.importKey() also raises a more descriptive exception in case of an unknown key format.
Diffstat (limited to 'lib/Crypto/PublicKey')
-rw-r--r--lib/Crypto/PublicKey/RSA.py25
1 files changed, 20 insertions, 5 deletions
diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py
index 6e123d6..bcb7f58 100644
--- a/lib/Crypto/PublicKey/RSA.py
+++ b/lib/Crypto/PublicKey/RSA.py
@@ -36,6 +36,8 @@ from Crypto import Random
from Crypto.Util.asn1 import DerObject, DerSequence
import binascii
+from Crypto.Util.number import inverse
+
try:
from Crypto.PublicKey import _fastmath
except ImportError:
@@ -143,7 +145,7 @@ class _RSAobj(pubkey.pubkey):
keyType = "RSA PRIVATE"
der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
self.d % (self.p-1), self.d % (self.q-1),
- self.u ]
+ inverse(self.q, self.p) ]
else:
keyType = "PUBLIC"
der.append('\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00')
@@ -162,7 +164,7 @@ class _RSAobj(pubkey.pubkey):
pem += ''.join(chunks)
pem += "-----END %s KEY-----" % keyType
return pem
- return ValueError("")
+ return ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
class RSAImplementation(object):
def __init__(self, **kwargs):
@@ -204,7 +206,7 @@ class RSAImplementation(object):
def generate(self, bits, randfunc=None, progress_func=None):
if bits < 1024 or (bits & 0xff) != 0:
# pubkey.getStrongPrime doesn't like anything that's not a multiple of 128 and > 512
- raise ValueError("RSA modulus length must be a multiple of 256 and > 1024")
+ raise ValueError("RSA modulus length must be a multiple of 256 and >= 1024")
rf = self._get_randfunc(randfunc)
obj = _RSA.generate_py(bits, rf, progress_func) # TODO: Don't use legacy _RSA module
key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u)
@@ -219,11 +221,22 @@ class RSAImplementation(object):
der.decode(externKey, True)
if len(der)==9 and der.hasOnlyInts() and der[0]==0:
# ASN.1 RSAPrivateKey element
- del der[6:8] # Remove d mod (p-1) and d mod (q-1)
+ del der[6:] # Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
+ der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
del der[0] # Remove version
return self.construct(der[:])
if len(der)==2:
- # ASN.1 SubjectPublicKeyInfo element
+ # The DER object is a SEQUENCE with two elements:
+ # a SubjectPublicKeyInfo SEQUENCE and an opaque BIT STRING.
+ #
+ # The first element is always the same:
+ # 0x30 0x0D SEQUENCE, 12 bytes of payload
+ # 0x06 0x09 OBJECT IDENTIFIER, 9 bytes of payload
+ # 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
+ # rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
+ # 0x05 0x00 NULL
+ #
+ # The second encapsulates the actual ASN.1 RSAPublicKey element.
if der[0]=='\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00':
bitmap = DerObject()
bitmap.decode(der[1], True)
@@ -239,6 +252,8 @@ class RSAImplementation(object):
externKey: the RSA key to import, encoded as a string.
The key can be in DER (PKCS#1) or in unencrypted
PEM format (RFC1421).
+
+ Raises a ValueError/IndexError if the given key cannot be parsed.
"""
if externKey.startswith('-----'):
# This is probably a PEM encoded key