如何使用Python生成SSH密钥对

时间:2010-03-17 22:35:40

标签: python ssh m2crypto ssh-keys

我正在尝试编写一个脚本来为我生成SSH身份密钥对。

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

文件/tmp/my.key现在看起来很棒。

通过运行ssh-keygen -y -f /tmp/my.key > /tmp/my.key.pub,我可以提取公钥。

我的问题是如何从python中提取公钥?使用key.save_pub_key("/tmp/my.key.pub")可以保存以下内容:

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

当我在寻找类似的东西时:

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

12 个答案:

答案 0 :(得分:34)

使用cryptographypycrypto不再处于活动开发状态,如果可能,您应该使用加密技术。自6月以来,它也可以生成SSH公钥:

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
)

注意:您至少需要版本1.4.0

答案 1 :(得分:31)

以防有未来的旅行者希望这样做。 RSA模块现在支持以OpenSSH格式写出公钥(可能在之前的帖子中没有)。所以我认为你可以做你需要的:

from os import chmod
from Crypto.PublicKey import RSA

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

使用'wb'打开文件,因为必须以二进制模式写入密钥。 显然不要将你的私钥存储在/ tmp ...

答案 2 :(得分:6)

编辑05/09/2012:

我刚才意识到pycrypto已经有了这个:

import os
from Crypto.PublicKey import RSA

key = RSA.generate(2048, os.urandom)
print key.exportKey('OpenSSH')

此代码适用于我:

import os
from Crypto.PublicKey import RSA

key = RSA.generate(2048, os.urandom)

# Create public key.                                                                                                                                               
ssh_rsa = '00000007' + base64.b16encode('ssh-rsa')

# Exponent.                                                                                                                                                        
exponent = '%x' % (key.e, )
if len(exponent) % 2:
    exponent = '0' + exponent

ssh_rsa += '%08x' % (len(exponent) / 2, )
ssh_rsa += exponent

modulus = '%x' % (key.n, )
if len(modulus) % 2:
    modulus = '0' + modulus

if modulus[0] in '89abcdef':
    modulus = '00' + modulus

ssh_rsa += '%08x' % (len(modulus) / 2, )
ssh_rsa += modulus

public_key = 'ssh-rsa %s' % (
    base64.b64encode(base64.b16decode(ssh_rsa.upper())), )

答案 3 :(得分:4)

ssh使用的密钥只是base64编码,我不太了解M2Crypto,但经过快速概述后,您似乎可以按照这种方式做到:

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)

我没有使用SSH测试生成的密钥,所以请告诉我它是否有效(我应该认为)

答案 4 :(得分:2)

base64解码后的ssh-keygen输出到key.pub()的内容,密钥文件的格式是

b64encode('\x00\x00\x00\x07ssh-rsa%s%s' % (key.pub()[0], key.pub()[1]))

答案 5 :(得分:1)

如何使用subprocess来调用ssh-keygen

from subprocess import Popen, PIPE
import shlex

def get_pub_key(path):
    args = shlex.split('ssh-keygen -y -f')
    args.append(path)
    p = Popen(args, stdout=PIPE)
    stdout = p.communicate()[0]
    if p.returncode != 0:
        raise Exception("Error handling would be nice, eh?")
    return stdout.strip()

print get_pub_key('/tmp/my.key')

上面的小程序会产生这样的输出:

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA ... 9Jbn6D74JOKpaOU050ltyNRw==

答案 6 :(得分:1)

以下是使用Twisted Conch库的示例,该库利用了PyCrypto。您可以在http://twistedmatrix.com/documents/current/api/twisted.conch.ssh.keys.html找到API文档:

from twisted.conch.ssh import keys

# one-time use key
k="""-----BEGIN RSA PRIVATE KEY-----
PRIVATE KEY STUFF
-----END RSA PRIVATE KEY-----"""

# create pycrypto RSA object
rsa = keys.RSA.importKey(k)

# create `twisted.conch.ssh.keys.Key` instance which has some nice helpers
key = keys.Key(rsa)

# pull the public part of the key and export an openssh version
ssh_public = key.public().toString("openssh")
print ssh_public

答案 7 :(得分:0)

你可以获得AAAA ...当它是一个对象时,Dfg ==字符串吗?如果是这样,您可以自己打开一个文件并保存,而不是使用内置的save_pub_key函数。

答案 8 :(得分:0)

猜猜......但你有没有试过这样的事情?:

print "ssh-rsa " + "".join([ l.strip() for l in open('/tmp/my.key.pub') if not l.startswith('-----')])

答案 9 :(得分:0)

我不知道这是一个标配Python的库。

如果您想查看第三方库,您可能会发现paramiko库很有用(也是available from PyPI)。它实现了SSH协议,并具有处理现有密钥的功能,但不生成它们。

生成密钥可能是该库的一个有用的补充(您可以work with the developers将其合并到Paramiko库中),并且比从头开始更容易开始。

答案 10 :(得分:0)

您可以按照documentation中的说明使用pycryptodome

from Crypto.PublicKey import RSA

key = RSA.generate(2048)
private_key = key.export_key()
file_out = open("private.pem", "wb")
file_out.write(private_key)

public_key = key.publickey().export_key()
file_out = open("receiver.pem", "wb")
file_out.write(public_key)

答案 11 :(得分:0)

如果需要,您也可以使用ssh-keygen本身。 您可以扩展它以创建文件,以后再使用open来阅读内容,但是我的重点是从此处已经存在的密钥创建.pub密钥。

from subprocess import Popen, PIPE
import os

home = f'{os.path.expanduser("~")}'
cert_pos = f'{home}/.ssh/my_key'
your_key_pw = ''

cmd = ['ssh-keygen', '-y', '-f', cert_pos]
if your_key_pw:
    cmd.append('-P')
    cmd.append(your_key_pw)

p = Popen(cmd, stdout=PIPE)
p.wait()
res, err = p.communicate()

cert_content = res.decode('utf-8')