22

Any idea how I can use the paramiko.RSAKey.from_private_key() function?

I know there is a from_private_key_file(), but I'm interested in using a function to parse a private key (like below) and use that private key for SSHClient.

Private key (sample):

-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKCAIEAmfgmlY95SHXhCeBNdkhSrsG4JVbqyew845yoZRX3wcS2/doz\niVQxgx0aiOwLi+/Rnkb3PLUIwoxb/LoD/W0YMS6/NSUMt+LdH+zsjeNF2iq4rDzU\nwDSqi27q/8u/egrK7H+9HNKEVXb/87utAAm3VTM9KqKaK3VuVFrNrnsDSuECAwEA\nAQKCAIBZn3y2KiGq8BLiMNJmO4sFdnW+Jm3cw8pdo17SGItzGxJ5iX3ePkfjzhkY\nAm5mMl6OBzj6+VX0CMeywIR6C/q8HwDYSmZcuU5v76/DoW5bI6xkPrroqEz6aRE5\nyN+2hf65RD3eoPATsdrP/kxiKjZg9uG9LhgIXyVwYFs1RcqewQJBAMCVJlEYXRio\neynUtyES9HNmUGUqHKmri1FZfO56/mFdG5ZXsKE48qURCAGVxI+goGQ4vtJIXB2J\nyTEr+5qYtE0CQQDMq9/iigk+XDOa9xGCbwxbLGdPawaEivezMVdPqVzH971L6kZ8\nhEnev1DqujgGCyR+QYPW1ZCXH05FY9CqWwrlAkATzYJyJlI0XebER2ZJVVyjnSq5\nLFpkLAqYY95P23/a3SsgC4ZTHbr9tEGhgBgFONwlUhx1HRGzy95PWxl1LSylAkBk\nwP93v8gJIM5urM27zfrhLxy0ZdVRji+d0N5QYuk/r19KbcvBJEZRFxE4W++UWgve\n81V5fqytGEYptpdUJXlZAkEArxZDiT1HXXGciIgzZbh53McogPCGHiKOOPSjpM41\npneDFVvwgezCWoDauxNDzu7Nl55qPJsmvfKZ+SKvCajrhQw==\n-----END RSA PRIVATE KEY-----\n

Code I wanted to run:

import paramiko
ssh = paramiko.SSHClient()
# how do I pass in the private_key, when my private_key (shown above) is in string?
mykey = paramiko.RSAKey.from_private_key(private_key) 
ssh.connect('192.168.1.2', username = 'vinod', pkey = mykey)

Many thanks.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Mickey Cheong
  • 2,980
  • 6
  • 38
  • 50

5 Answers5

24

Lev's method worked for me:

>>> import paramiko
>>> f = open('/path/to/key.pem','r')
>>> s = f.read()
>>> import StringIO
>>> keyfile = StringIO.StringIO(s)
>>> mykey = paramiko.RSAKey.from_private_key(keyfile)
>>> ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> ssh.connect('myserver.compute-1.amazonaws.com', username='ubuntu', pkey=mykey)
>>> stdin, stdout, stderr = ssh.exec_command('uptime')
>>> stdout.readlines()
[' 19:21:10 up 24 days, 42 min,  1 user,  load average: 0.14, 0.06, 0.05\n']
Paul Zielinski
  • 460
  • 3
  • 7
10

This should do it:

import io
import paramiko

private_key_file = io.StringIO()
private_key_file.write('-----BEGIN RSA PRIVATE KEY-----\nlskjdflk\n...\n-----END RSA PRIVATE KEY-----\n')
private_key_file.seek(0)
private_key = paramiko.RSAKey.from_private_key(private_key_file)
Quinn Weber
  • 927
  • 5
  • 10
8

from_private_key() apparently takes a file object:

from_private_key(cls, file_obj, password=None)

Create a key object by reading a private key from a file (or file-like) object. If the private key is encrypted and password is not None, the given password will be used to decrypt the key (otherwise PasswordRequiredException is thrown).

Parameters:

file_obj (file) - the file to read from password (str) - an optional password to use to decrypt the key, if it's encrypted

Returns: PKey

a new key object based on the given private key

Raises:

IOError - if there was an error reading the key

PasswordRequiredException - if the private key file is encrypted, and password is None

SSHException - if the key file is invalid

So to feed it a key as a string you can use StringIO, something like:

private_key = StringIO.StringIO(key_string)
mykey = paramiko.RSAKey.from_private_key(private_key)

I have not tested this, though.

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
  • 7
    Doesn't work. `key_string` is the private key as string. I get this exception: `SSHException: not a valid RSA private key file` – zengr Aug 23 '13 at 21:19
3

Here is where 'duck typing' comes in handy - it does not have to BE a duck (=file), it just has to BEHAVE like one.

A little experimentation shows that, any object that has a valid readlines() method is fine.

I faked it with:

def myfakefile(keystring):
    myfakefile.readlines=lambda: keystring.split("\n")
    return myfakefile

mykey = paramiko.RSAKey.from_private_key(myfakefile(keystring))

This is incredibly hacky, but it works.

What this does, is, when you call myfakefile(keystring), it creates myfakefile.readlines, which returns the (split) contents of keystrings.

Then, it returns the function.

The same function is passed to from_private_key. from_private_key, thinking it is a file, calls myfakefile.readlines(). This calls the newly created (lambda) function, which returns the sort of thing you would expect from file.readlines() - or, close enough, anyway.

Note that, saving the results will not work as expected:

k1=myfakefile(keystring1)
k2=myfakefile(keystring2)

 # This will return keystring2, not keystring1!
paramkiko.RSAKey.from_private_keyfile(k1.readlines())

There are more robust methods of getting this to work as it should, but not worth the effort - just use StringIO if your needs are more complicated.

AMADANON Inc.
  • 5,753
  • 21
  • 31
-2

Very old question, but in case it helps some unfortunate soul: my sol'n to this problem was to generate a new key with default options, using

ssh-keygen -t rsa

My previous key was generated using

ssh-keygen -t rsa -b 4096 -a 100

which paramiko complained about as it did for OP.

  • Paramiko complained was because the -o flag saved the key in the OpenSSH format, and *not* the RSA format paramiko expects. If you drop the -o flag when generating the key paramiko should work with the resultant key. – KiwiMartin Oct 18 '16 at 01:46