How to generate SSH key pairs with Python

2019-01-21 16:49发布

I'm attempting to write a script to generate SSH Identity key pairs for me.

from M2Crypto import RSA
key = RSA.gen_key(1024, 65337)
key.save_key("/tmp/my.key", cipher=None)

The file /tmp/my.key looks great now.

By running ssh-keygen -y -f /tmp/my.key > /tmp/my.key.pub I can extract the public key.

My question is how can I extract the public key from python? Using key.save_pub_key("/tmp/my.key.pub") saves something like:

-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADASDASDASDASDBarYRsmMazM1hd7a+u3QeMP
...
FZQ7Ic+BmmeWHvvVP4Yjyu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQ==
-----END PUBLIC KEY-----

When I'm looking for something like:

ssh-rsa AAAABCASDDBM$%3WEAv/3%$F ..... OSDFKJSL43$%^DFg==

11条回答
虎瘦雄心在
2楼-- · 2019-01-21 17:28

The key used by ssh is just base64 encoded, i don't know M2Crypto very much, but after a quick overview it seems you could do what you want this way:

import os
from base64 import b64encode
from M2Crypto import RSA            

key = RSA.gen_key(1024, 65537)
raw_key = key.pub()[1]
b64key = b64encode(raw_key)

username = os.getlogin()
hostname = os.uname()[1]
keystring = 'ssh-rsa %s %s@%s' % (b64key, username, hostname)

with open(os.getenv('HOME')+'/.ssh/id_rsa.pub') as keyfile:
    keyfile.write(keystring)

I didn't test the generated key with SSH, so please let me know if it works (it should i think)

查看更多
家丑人穷心不美
3楼-- · 2019-01-21 17:28

The base64 decoded version of ssh-keygen output to the contents of key.pub() the format of the keyfile is

b64encode('\x00\x00\x00\x07ssh-rsa%s%s' % (key.pub()[0], key.pub()[1]))
查看更多
走好不送
4楼-- · 2019-01-21 17:33

Just in case there are any future travellers looking to do this. The RSA module support writing out the public key in OpenSSH format now (possibly didn't at the time of earlier posts). So I think you can do what you need with:

from os import chmod
from Crypto.PublicKey import RSA

key = RSA.generate(2048)
with open("/tmp/private.key", 'w') as content_file:
    chmod("/tmp/private.key", 0600)
    content_file.write(key.exportKey('PEM'))
pubkey = key.publickey()
with open("/tmp/public.key", 'w') as content_file:
    content_file.write(pubkey.exportKey('OpenSSH'))

Obviously don't store you're private key in /tmp...

查看更多
Emotional °昔
5楼-- · 2019-01-21 17:34

Use cryptography! pycrypto is not in active development anymore and if possible you should be using cryptography. Since June it's possible to generate SSH public keys as well:

from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend

key = rsa.generate_private_key(
    backend=crypto_default_backend(),
    public_exponent=65537,
    key_size=2048
)
private_key = key.private_bytes(
    crypto_serialization.Encoding.PEM,
    crypto_serialization.PrivateFormat.PKCS8,
    crypto_serialization.NoEncryption())
public_key = key.public_key().public_bytes(
    crypto_serialization.Encoding.OpenSSH,
    crypto_serialization.PublicFormat.OpenSSH
)

Note: You need at least version 1.4.0.

查看更多
趁早两清
6楼-- · 2019-01-21 17:34

Just guessing... but have you tried something like this?:

print "ssh-rsa " + "".join([ l.strip() for l in open('/tmp/my.key.pub') if not l.startswith('-----')])
查看更多
登录 后发表回答