summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLegrandin <gooksankoo@hoiptorrow.mailexpire.com>2011-09-21 20:54:17 +0200
committerLegrandin <gooksankoo@hoiptorrow.mailexpire.com>2011-09-21 20:54:17 +0200
commit51a760b18506ddfd11a692e7848178be63ee471a (patch)
tree90a68626e53b84b0c68b7e8de8518fce8a652314
parentb8dc2d95ea146d4ed77e48c33c1d731ff6ee5d50 (diff)
downloadpycrypto-51a760b18506ddfd11a692e7848178be63ee471a.tar.gz
Added support for export of public RSA keys in OpenSSH format
-rw-r--r--lib/Crypto/PublicKey/RSA.py22
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_importKey.py7
2 files changed, 24 insertions, 5 deletions
diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py
index a148d7c..908ec68 100644
--- a/lib/Crypto/PublicKey/RSA.py
+++ b/lib/Crypto/PublicKey/RSA.py
@@ -33,7 +33,7 @@ __revision__ = "$Id$"
__all__ = ['generate', 'construct', 'error', 'importKey' ]
from Crypto.Util.python_compat import *
-from Crypto.Util.number import getRandomRange, bytes_to_long
+from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes
from Crypto.PublicKey import _RSA, _slowmath, pubkey
from Crypto import Random
@@ -172,6 +172,7 @@ class _RSAobj(pubkey.pubkey):
:Parameter format: The encoding to use to wrap the key.
- *'DER'* for PKCS#1
+ - *'OpenSSH'* for OpenSSH public keys (no private key)
- *'PEM'* for RFC1421
:Type format: string
@@ -179,6 +180,17 @@ class _RSAobj(pubkey.pubkey):
:Raise ValueError:
When the format is unknown.
"""
+ if format=='OpenSSH':
+ eb = long_to_bytes(self.e)
+ nb = long_to_bytes(self.n)
+ if ord(eb[0]) & 0x80: eb='\x00'+nb
+ if ord(nb[0]) & 0x80: nb='\x00'+nb
+ keyparts = [ 'ssh-rsa', eb, nb ]
+ keystring = ''.join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
+ return 'ssh-rsa '+binascii.b2a_base64(keystring)[:-1]
+
+ # PKCS#1 is a direct DER encoding. PEM uses it as well, but
+ # wraps in an ASCII envelope.
der = DerSequence()
if self.has_private():
keyType = "RSA PRIVATE"
@@ -389,10 +401,10 @@ class RSAImplementation(object):
# This is probably an OpenSSH key
keystring = binascii.a2b_base64(externKey.split(' ')[1])
keyparts = []
- while keystring:
- len = struct.unpack(">I",keystring[:4])[0]
- keyparts.append(keystring[4:4+len])
- keystring = keystring[4+len:]
+ while len(keystring)>4:
+ l = struct.unpack(">I",keystring[:4])[0]
+ keyparts.append(keystring[4:4+l])
+ keystring = keystring[4+l:]
e = bytes_to_long(keyparts[1])
n = bytes_to_long(keyparts[2])
return self.construct([n, e])
diff --git a/lib/Crypto/SelfTest/PublicKey/test_importKey.py b/lib/Crypto/SelfTest/PublicKey/test_importKey.py
index 4edc243..018754d 100644
--- a/lib/Crypto/SelfTest/PublicKey/test_importKey.py
+++ b/lib/Crypto/SelfTest/PublicKey/test_importKey.py
@@ -150,6 +150,13 @@ Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ==
pemKey = key.exportKey("PEM")
self.assertEqual(pemKey, self.rsaPublicKeyPEM)
+ def testExportKey5(self):
+ key = self.rsa.construct([self.n, self.e])
+ openssh_1 = key.exportKey("OpenSSH").split()
+ openssh_2 = self.rsaPublicKeyOpenSSH.split()
+ self.assertEqual(openssh_1[0], openssh_2[0])
+ self.assertEqual(openssh_1[1], openssh_2[1])
+
class ImportKeyTestsSlow(ImportKeyTests):
def setUp(self):
self.rsa = RSA.RSAImplementation(use_fast_math=0)