summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSybren A. St?vel <sybren@stuvel.eu>2011-07-21 22:16:56 +0200
committerSybren A. St?vel <sybren@stuvel.eu>2011-07-21 22:16:56 +0200
commit540464cb492b582b7a080497d03891c326f24b89 (patch)
tree1dc2ce204cf312b603d4df0424ebce92ad3e503a
parent68584a0901f33624e1b34a24cee25f9b7514f673 (diff)
downloadrsa-540464cb492b582b7a080497d03891c326f24b89.tar.gz
Moved key load/save to PrivateKey class
-rw-r--r--rsa/key.py216
-rw-r--r--tests/test_load_save_keys.py8
2 files changed, 114 insertions, 110 deletions
diff --git a/rsa/key.py b/rsa/key.py
index c0dd5d5..4e4ff5d 100644
--- a/rsa/key.py
+++ b/rsa/key.py
@@ -131,6 +131,114 @@ class PrivateKey(object):
def __ne__(self, other):
return not (self == other)
+ @classmethod
+ def load_pkcs1_der(cls, keyfile):
+ r'''Loads a key in PKCS#1 DER format.
+
+ @param keyfile: contents of a DER-encoded file that contains the private
+ key.
+ @return: a PrivateKey object
+
+ First let's construct a DER encoded key:
+
+ >>> import base64
+ >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt'
+ >>> der = base64.decodestring(b64der)
+
+ This loads the file:
+
+ >>> PrivateKey.load_pkcs1_der(der)
+ PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
+
+ '''
+
+ from pyasn1.codec.der import decoder
+ (priv, _) = decoder.decode(keyfile)
+
+ # ASN.1 contents of DER encoded private key:
+ #
+ # RSAPrivateKey ::= SEQUENCE {
+ # version Version,
+ # modulus INTEGER, -- n
+ # publicExponent INTEGER, -- e
+ # privateExponent INTEGER, -- d
+ # prime1 INTEGER, -- p
+ # prime2 INTEGER, -- q
+ # exponent1 INTEGER, -- d mod (p-1)
+ # exponent2 INTEGER, -- d mod (q-1)
+ # coefficient INTEGER, -- (inverse of q) mod p
+ # otherPrimeInfos OtherPrimeInfos OPTIONAL
+ # }
+
+ if priv[0] != 0:
+ raise ValueError('Unable to read this file, version %s != 0' % priv[0])
+
+ return cls(*priv[1:9])
+
+ def save_pkcs1_der(self):
+ '''Saves the private key in PKCS#1 DER format.
+
+ @param priv_key: the private key to save
+ @returns: the DER-encoded private key.
+ '''
+
+ from pyasn1.type import univ, namedtype, tag
+ from pyasn1.codec.der import encoder
+
+ class AsnPrivKey(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('version', univ.Integer()),
+ namedtype.NamedType('modulus', univ.Integer()),
+ namedtype.NamedType('publicExponent', univ.Integer()),
+ namedtype.NamedType('privateExponent', univ.Integer()),
+ namedtype.NamedType('prime1', univ.Integer()),
+ namedtype.NamedType('prime2', univ.Integer()),
+ namedtype.NamedType('exponent1', univ.Integer()),
+ namedtype.NamedType('exponent2', univ.Integer()),
+ namedtype.NamedType('coefficient', univ.Integer()),
+ )
+
+ # Create the ASN object
+ asn_key = AsnPrivKey()
+ asn_key.setComponentByName('version', 0)
+ asn_key.setComponentByName('modulus', self.n)
+ asn_key.setComponentByName('publicExponent', self.e)
+ asn_key.setComponentByName('privateExponent', self.d)
+ asn_key.setComponentByName('prime1', self.p)
+ asn_key.setComponentByName('prime2', self.q)
+ asn_key.setComponentByName('exponent1', self.exp1)
+ asn_key.setComponentByName('exponent2', self.exp2)
+ asn_key.setComponentByName('coefficient', self.coef)
+
+ return encoder.encode(asn_key)
+
+ @classmethod
+ def load_pkcs1_pem(cls, keyfile):
+ '''Loads a PKCS#1 PEM-encoded private key file.
+
+ The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and
+ after the "-----END RSA PRIVATE KEY-----" lines is ignored.
+
+ @param keyfile: contents of a PEM-encoded file that contains the private
+ key.
+ @return: a PrivateKey object
+ '''
+
+ der = rsa.pem.load_pem(keyfile, 'RSA PRIVATE KEY')
+ return cls.load_pkcs1_der(der)
+
+ def save_pkcs1_pem(self):
+ '''Saves a PKCS#1 PEM-encoded private key file.
+
+ @param keyfile: a PrivateKey object
+ @return: contents of a PEM-encoded file that contains the private key.
+ '''
+
+ der = self.save_pkcs1_der()
+ return rsa.pem.save_pem(der, 'RSA PRIVATE KEY')
+
+
+
def extended_gcd(a, b):
"""Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
"""
@@ -245,112 +353,8 @@ def newkeys(nbits):
PrivateKey(n, e, d, p, q)
)
-def load_private_key_der(keyfile):
- r'''Loads a key in DER format.
-
- @param keyfile: contents of a DER-encoded file that contains the private
- key.
- @return: a PrivateKey object
-
- First let's construct a DER encoded key:
-
- >>> import base64
- >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt'
- >>> der = base64.decodestring(b64der)
-
- This loads the file:
-
- >>> load_private_key_der(der)
- PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
-
- '''
-
- from pyasn1.codec.der import decoder
- (priv, _) = decoder.decode(keyfile)
-
- # ASN.1 contents of DER encoded private key:
- #
- # RSAPrivateKey ::= SEQUENCE {
- # version Version,
- # modulus INTEGER, -- n
- # publicExponent INTEGER, -- e
- # privateExponent INTEGER, -- d
- # prime1 INTEGER, -- p
- # prime2 INTEGER, -- q
- # exponent1 INTEGER, -- d mod (p-1)
- # exponent2 INTEGER, -- d mod (q-1)
- # coefficient INTEGER, -- (inverse of q) mod p
- # otherPrimeInfos OtherPrimeInfos OPTIONAL
- # }
-
- if priv[0] != 0:
- raise ValueError('Unable to read this file, version %s != 0' % priv[0])
-
- return PrivateKey(*priv[1:9])
-
-def save_private_key_der(priv_key):
- '''Saves the private key in DER format.
-
- @param priv_key: the private key to save
- @returns: the DER-encoded private key.
- '''
-
- from pyasn1.type import univ, namedtype, tag
- from pyasn1.codec.der import encoder
-
- class AsnPrivKey(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('version', univ.Integer()),
- namedtype.NamedType('modulus', univ.Integer()),
- namedtype.NamedType('publicExponent', univ.Integer()),
- namedtype.NamedType('privateExponent', univ.Integer()),
- namedtype.NamedType('prime1', univ.Integer()),
- namedtype.NamedType('prime2', univ.Integer()),
- namedtype.NamedType('exponent1', univ.Integer()),
- namedtype.NamedType('exponent2', univ.Integer()),
- namedtype.NamedType('coefficient', univ.Integer()),
- )
-
- # Create the ASN object
- asn_key = AsnPrivKey()
- asn_key.setComponentByName('version', 0)
- asn_key.setComponentByName('modulus', priv_key.n)
- asn_key.setComponentByName('publicExponent', priv_key.e)
- asn_key.setComponentByName('privateExponent', priv_key.d)
- asn_key.setComponentByName('prime1', priv_key.p)
- asn_key.setComponentByName('prime2', priv_key.q)
- asn_key.setComponentByName('exponent1', priv_key.exp1)
- asn_key.setComponentByName('exponent2', priv_key.exp2)
- asn_key.setComponentByName('coefficient', priv_key.coef)
-
- return encoder.encode(asn_key)
-
-def load_private_key_pem(keyfile):
- '''Loads a PEM-encoded private key file.
-
- The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and
- after the "-----END RSA PRIVATE KEY-----" lines is ignored.
-
- @param keyfile: contents of a PEM-encoded file that contains the private
- key.
- @return: a PrivateKey object
- '''
-
- der = rsa.pem.load_pem(keyfile, 'RSA PRIVATE KEY')
- return load_private_key_der(der)
-
-def save_private_key_pem(priv_key):
- '''Saves a PEM-encoded private key file.
-
- @param keyfile: a PrivateKey object
- @return: contents of a PEM-encoded file that contains the private key.
- '''
-
- der = save_private_key_der(priv_key)
- return rsa.pem.save_pem(der, 'RSA PRIVATE KEY')
-
-
-__all__ = ['PublicKey', 'PrivateKey', 'newkeys', 'load']
+__all__ = ['PublicKey', 'PrivateKey', 'newkeys', 'load_private_key_der',
+ 'load_private_key_pem', 'save_private_key_der', 'save_private_key_pem']
if __name__ == '__main__':
import doctest
diff --git a/tests/test_load_save_keys.py b/tests/test_load_save_keys.py
index c13d059..5026afd 100644
--- a/tests/test_load_save_keys.py
+++ b/tests/test_load_save_keys.py
@@ -33,7 +33,7 @@ class DerTest(unittest.TestCase):
def test_load_private_key(self):
'''Test loading private DER keys.'''
- key = rsa.key.load_private_key_der(PRIVATE_DER)
+ key = rsa.key.PrivateKey.load_pkcs1_der(PRIVATE_DER)
expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
self.assertEqual(expected, key)
@@ -42,7 +42,7 @@ class DerTest(unittest.TestCase):
'''Test saving private DER keys.'''
key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
- der = rsa.key.save_private_key_der(key)
+ der = key.save_pkcs1_der()
self.assertEqual(PRIVATE_DER, der)
@@ -53,7 +53,7 @@ class PemTest(unittest.TestCase):
def test_load_private_key(self):
'''Test loading private PEM files.'''
- key = rsa.key.load_private_key_pem(PRIVATE_PEM)
+ key = rsa.key.PrivateKey.load_pkcs1_pem(PRIVATE_PEM)
expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
self.assertEqual(expected, key)
@@ -62,7 +62,7 @@ class PemTest(unittest.TestCase):
'''Test saving private PEM files.'''
key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
- pem = rsa.key.save_private_key_pem(key)
+ pem = key.save_pkcs1_pem()
self.assertEqual(CLEAN_PRIVATE_PEM, pem)