Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paramiko -- using encrypted private key file on OS X

Tags:

I'm trying to use Paramiko to connect to an SSH server from Python. This is what I tried so far:

>>> import paramiko
>>> import os
>>> privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
>>> mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 198, in from_private_key_file
    key = cls(filename=filename, password=password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/rsakey.py", line 51, in __init__
    self._from_private_key_file(filename, password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/rsakey.py", line 163, in _from_private_key_file
    data = self._read_private_key_file('RSA', filename, password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 280, in _read_private_key_file
    data = self._read_private_key(tag, f, password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 323, in _read_private_key
    raise PasswordRequiredException('Private key file is encrypted')
paramiko.PasswordRequiredException: Private key file is encrypted

As you can see, it's failing because my private key is encrypted. However, the password is stored in my OS X login keychain, and when I type ssh host it won't ask for it (rather, it only asks once, then remembers it until the next reboot). Is there a way to make paramiko use the password / fetch it from the keychain, like ssh does?

like image 451
houbysoft Avatar asked Mar 22 '13 20:03

houbysoft


People also ask

Does Paramiko use OpenSSH?

Paramiko relies on cryptography for crypto functionality, which makes use of C and Rust extensions but has many precompiled options available. See our installation page for details. SSH is defined in RFC 4251, RFC 4252, RFC 4253 and RFC 4254. The primary working implementation of the protocol is the OpenSSH project.

What is Paramiko SSH?

Paramiko is a Python library that makes a connection with a remote device through SSh. Paramiko is using SSH2 as a replacement for SSL to make a secure connection between two devices. It also supports the SFTP client and server model.


2 Answers

The following approach seems to work fine (on OS X, with the usual setup of encrypted private keys that have passphrases stored in the keychain, without any user interaction):

import paramiko

ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.connect(HOST, username=USER, look_for_keys=False)
...
ssh.close()

It seems that look_for_keys=False is not absolutely necessary. However, if you use it you will get much better error messages in the case of an authentication failure ("AuthenticationException" instead of "PasswordRequiredException").


If you really want to use private keys directly, you could do the following:

import os
import paramiko
import keyring

keyfile = os.path.expanduser('~/.ssh/id_rsa')
password = keyring.get_password('SSH', keyfile)
key = paramiko.RSAKey.from_private_key_file(keyfile, password=password)

However, based on my testing, this is not needed. The above solution that uses ssh.connect in a straightforward manner should be sufficient.

like image 151
Jukka Suomela Avatar answered Oct 04 '22 11:10

Jukka Suomela


The RSAKey.from_private_key_file() is inherited from PKey(); an optional parameter of this method is a password. To quote:

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).

As you're not passing a password and your key is encrypted this exception will always be thrown. There's only one way round this problem, to actually give the method a password. You, therefore, need a way of getting the password out of the OSXKeychain.

You could use the cross-platform Keyring module to do this.

like image 27
Ben Avatar answered Oct 04 '22 12:10

Ben