Paramiko: "not a valid RSA private key file"
Question:
I am trying connect to server using following spinet
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ip = ['x.x.x.x']
key_file = "/Users/user/.ssh/id_rsa"
key = paramiko.RSAKey.from_private_key_file(key_file)
ssh.load_system_host_keys()
ssh.connect(ips, port=22, username='XYZ', pkey=key, timeout=11)
But I am getting an error:
not a valid RSA private key file
Answers:
The paramiko.RSAKey.from_private_key_file
method requires the private key file to be in “PEM” format. Examine the file you’re trying to read and see if it begins with a line that says:
-----BEGIN RSA PRIVATE KEY-----
If it doesn’t have that line then it’s not PEM.
If it’s not PEM then you’ll have to find some way to create a PEM version of the private key. (EDIT: the original poster used PuTTY’s puttygen
utility to export the private key into a PEM-format file.)
Make sure that the new file has the same ownership and limited access permissions that the original id_rsa
file has, so that nobody can steal the key by reading the file. Then, obviously, modify your paramiko
call to read the key from the new PEM-format file.
I faced a similar situation and ssh-keygen comes to my help. You should make a copy of id_rsa and convert it to RSA type with ssh-keygen.
To Convert “BEGIN OPENSSH PRIVATE KEY” to “BEGIN RSA PRIVATE KEY”
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa
Recent versions of OpenSSH (7.8 and newer) generate keys in new OpenSSH format by default, which starts with:
-----BEGIN OPENSSH PRIVATE KEY-----
That format is fully supported by the Paramiko since version 2.7.1 (2019-12-09) only.
If you are stuck with an older version of Paramiko, you can use ssh-keygen
to convert the key to the classic OpenSSH format:
ssh-keygen -p -f file -m pem -P passphrase -N passphrase
(if the key is not encrypted with a passphrase, use ""
instead of passphrase
)
For Windows users: Note that ssh-keygen.exe
is now built-in in Windows 10. And can be downloaded from Microsoft Win32-OpenSSH project for older versions of Windows.
On Windows, you can also use PuTTYgen (from PuTTY package):
- Start PuTTYgen
- Load the key
- Go to Conversions > Export OpenSSH key.
For RSA keys, it will use the classic format.
If you are creating a new key with ssh-keygen
, just add -m PEM
to generate the new key in the classic format:
ssh-keygen -m PEM
Note that you can get the error, also when you are trying to use a completely different key format, like ssh.com or PuTTY .ppk. Then you will have to convert the key in any case.
- For ssh.com format, see Paramiko: "not a valid DSA private key file".
- For PuTTY .ppk format, use PuTTYgen as shown above.
I have encountered the same error while I was connected with ssh to an Ubuntu VM.
In my terminal SSH_AUTH_SOCK
environment variable is not defined, and paramiko throws the not a valid RSA private key file
error.
However, if I am connected in a graphical session to the same machine, the graphical terminal has got SSH_AUTH_SOCK
defined, and Paramiko is happy.
As a workaround, I have copied the content of SSH_AUTH_SOCK
in my SSH terminal and it works better.
As I checked, there was no issue with the path as well permissions(only read permission on the RSA file will work), so the problem was with the Paramiko version.
I updated it using the below command and it resolved the issue for me.
pip3 install paramiko update
The following solution worked for me:
- install the
putty
package:
brew install putty
- convert the .ppk into .pem :
puttygen <filename>.ppk -O private-openssh -o <filename>.pem
- give a try one more time through python paramiko:
import paramiko
username, hostname, port = ('username', 'domain.com', 22,)
transport = paramiko.Transport(hostname, port)
private_key = paramiko.RSAKey.from_private_key(open(pem_file_path))
params = {"username": username, "pkey": private_key}
# if there is a password, add it to the previous dict
transport.connect(**params)
conn = paramiko.SFTPClient.from_transport(transport)
Some good references:
I am trying connect to server using following spinet
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ip = ['x.x.x.x']
key_file = "/Users/user/.ssh/id_rsa"
key = paramiko.RSAKey.from_private_key_file(key_file)
ssh.load_system_host_keys()
ssh.connect(ips, port=22, username='XYZ', pkey=key, timeout=11)
But I am getting an error:
not a valid RSA private key file
The paramiko.RSAKey.from_private_key_file
method requires the private key file to be in “PEM” format. Examine the file you’re trying to read and see if it begins with a line that says:
-----BEGIN RSA PRIVATE KEY-----
If it doesn’t have that line then it’s not PEM.
If it’s not PEM then you’ll have to find some way to create a PEM version of the private key. (EDIT: the original poster used PuTTY’s puttygen
utility to export the private key into a PEM-format file.)
Make sure that the new file has the same ownership and limited access permissions that the original id_rsa
file has, so that nobody can steal the key by reading the file. Then, obviously, modify your paramiko
call to read the key from the new PEM-format file.
I faced a similar situation and ssh-keygen comes to my help. You should make a copy of id_rsa and convert it to RSA type with ssh-keygen.
To Convert “BEGIN OPENSSH PRIVATE KEY” to “BEGIN RSA PRIVATE KEY”
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa
Recent versions of OpenSSH (7.8 and newer) generate keys in new OpenSSH format by default, which starts with:
-----BEGIN OPENSSH PRIVATE KEY-----
That format is fully supported by the Paramiko since version 2.7.1 (2019-12-09) only.
If you are stuck with an older version of Paramiko, you can use ssh-keygen
to convert the key to the classic OpenSSH format:
ssh-keygen -p -f file -m pem -P passphrase -N passphrase
(if the key is not encrypted with a passphrase, use ""
instead of passphrase
)
For Windows users: Note that ssh-keygen.exe
is now built-in in Windows 10. And can be downloaded from Microsoft Win32-OpenSSH project for older versions of Windows.
On Windows, you can also use PuTTYgen (from PuTTY package):
- Start PuTTYgen
- Load the key
- Go to Conversions > Export OpenSSH key.
For RSA keys, it will use the classic format.
If you are creating a new key with ssh-keygen
, just add -m PEM
to generate the new key in the classic format:
ssh-keygen -m PEM
Note that you can get the error, also when you are trying to use a completely different key format, like ssh.com or PuTTY .ppk. Then you will have to convert the key in any case.
- For ssh.com format, see Paramiko: "not a valid DSA private key file".
- For PuTTY .ppk format, use PuTTYgen as shown above.
I have encountered the same error while I was connected with ssh to an Ubuntu VM.
In my terminal SSH_AUTH_SOCK
environment variable is not defined, and paramiko throws the not a valid RSA private key file
error.
However, if I am connected in a graphical session to the same machine, the graphical terminal has got SSH_AUTH_SOCK
defined, and Paramiko is happy.
As a workaround, I have copied the content of SSH_AUTH_SOCK
in my SSH terminal and it works better.
As I checked, there was no issue with the path as well permissions(only read permission on the RSA file will work), so the problem was with the Paramiko version.
I updated it using the below command and it resolved the issue for me.
pip3 install paramiko update
The following solution worked for me:
- install the
putty
package:
brew install putty
- convert the .ppk into .pem :
puttygen <filename>.ppk -O private-openssh -o <filename>.pem
- give a try one more time through python paramiko:
import paramiko
username, hostname, port = ('username', 'domain.com', 22,)
transport = paramiko.Transport(hostname, port)
private_key = paramiko.RSAKey.from_private_key(open(pem_file_path))
params = {"username": username, "pkey": private_key}
# if there is a password, add it to the previous dict
transport.connect(**params)
conn = paramiko.SFTPClient.from_transport(transport)
Some good references: