summaryrefslogtreecommitdiff
path: root/rsa/key.py
diff options
context:
space:
mode:
authorSybren A. Stüvel <sybren@stuvel.eu>2012-10-11 17:09:13 +0200
committerSybren A. Stüvel <sybren@stuvel.eu>2012-10-11 17:09:13 +0200
commit9884505885e342de141d1f4a3cc0be8dcd0c54b3 (patch)
tree01afc10572b127d89f1873a02fcbb81cd3efa23b /rsa/key.py
parent2daadbbcc3857af75713bed74b327485a6636778 (diff)
downloadrsa-git-9884505885e342de141d1f4a3cc0be8dcd0c54b3.tar.gz
Added support for loading public keys from OpenSSL
Diffstat (limited to 'rsa/key.py')
-rw-r--r--rsa/key.py67
1 files changed, 49 insertions, 18 deletions
diff --git a/rsa/key.py b/rsa/key.py
index 3870541..43f4c87 100644
--- a/rsa/key.py
+++ b/rsa/key.py
@@ -26,7 +26,7 @@ of pyasn1.
'''
import logging
-from rsa._compat import b
+from rsa._compat import b, bytes_type
import rsa.prime
import rsa.pem
@@ -34,6 +34,8 @@ import rsa.common
log = logging.getLogger(__name__)
+
+
class AbstractKey(object):
'''Abstract superclass for private and public keys.'''
@@ -153,16 +155,10 @@ class PublicKey(AbstractKey):
'''
from pyasn1.codec.der import decoder
- (priv, _) = decoder.decode(keyfile)
-
- # ASN.1 contents of DER encoded public key:
- #
- # RSAPublicKey ::= SEQUENCE {
- # modulus INTEGER, -- n
- # publicExponent INTEGER, -- e
-
- as_ints = tuple(int(x) for x in priv)
- return cls(*as_ints)
+ from rsa.asn1 import AsnPubKey
+
+ (priv, _) = decoder.decode(keyfile, asn1Spec=AsnPubKey())
+ return cls(n=priv['modulus'], e=priv['publicExponent'])
def _save_pkcs1_der(self):
'''Saves the public key in PKCS#1 DER format.
@@ -170,14 +166,8 @@ class PublicKey(AbstractKey):
@returns: the DER-encoded public key.
'''
- from pyasn1.type import univ, namedtype
from pyasn1.codec.der import encoder
-
- class AsnPubKey(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('modulus', univ.Integer()),
- namedtype.NamedType('publicExponent', univ.Integer()),
- )
+ from rsa.asn1 import AsnPubKey
# Create the ASN object
asn_key = AsnPubKey()
@@ -210,6 +200,47 @@ class PublicKey(AbstractKey):
der = self._save_pkcs1_der()
return rsa.pem.save_pem(der, 'RSA PUBLIC KEY')
+ @classmethod
+ def load_pkcs1_openssl_pem(cls, keyfile):
+ '''Loads a PKCS#1.5 PEM-encoded public key file from OpenSSL.
+
+ These files can be recognised in that they start with BEGIN PUBLIC KEY
+ rather than BEGIN RSA PUBLIC KEY.
+
+ The contents of the file before the "-----BEGIN PUBLIC KEY-----" and
+ after the "-----END PUBLIC KEY-----" lines is ignored.
+
+ @param keyfile: contents of a PEM-encoded file that contains the public
+ key, from OpenSSL.
+ @return: a PublicKey object
+ '''
+
+ der = rsa.pem.load_pem(keyfile, 'PUBLIC KEY')
+ return cls.load_pkcs1_openssl_der(der)
+
+ @classmethod
+ def load_pkcs1_openssl_der(cls, keyfile):
+ '''Loads a PKCS#1 DER-encoded public key file from OpenSSL.
+
+ @param keyfile: contents of a DER-encoded file that contains the public
+ key, from OpenSSL.
+ @return: a PublicKey object
+ '''
+
+ from rsa.asn1 import OpenSSLPubKey
+ from pyasn1.codec.der import decoder
+ from pyasn1.type import univ
+
+ (keyinfo, _) = decoder.decode(keyfile, asn1Spec=OpenSSLPubKey())
+
+ if keyinfo['header']['oid'] != univ.ObjectIdentifier('1.2.840.113549.1.1.1'):
+ raise TypeError("This is not a DER-encoded OpenSSL-compatible public key")
+
+ return cls._load_pkcs1_der(keyinfo['key'][1:])
+
+
+
+
class PrivateKey(AbstractKey):
'''Represents a private RSA key.