Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Python生成SSH密钥对_Python_Ssh_M2crypto_Ssh Keys - Fatal编程技术网

如何使用Python生成SSH密钥对

如何使用Python生成SSH密钥对,python,ssh,m2crypto,ssh-keys,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\u pub\u key(“/tmp/my.k

我正在尝试编写一个脚本来为我生成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\u pub\u key(“/tmp/my.key.pub”)
保存如下内容:

-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADASDASDASDASDBarYRsmMazM1hd7a+u3QeMP
...
FZQ7Ic+BmmeWHvvVP4Yjyu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQ==
-----END PUBLIC KEY-----
ssh-rsa AAAABCASDDBM$%3WEAv/3%$F ..... OSDFKJSL43$%^DFg==
当我在寻找像这样的东西时:

-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADASDASDASDASDBarYRsmMazM1hd7a+u3QeMP
...
FZQ7Ic+BmmeWHvvVP4Yjyu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQ==
-----END PUBLIC KEY-----
ssh-rsa AAAABCASDDBM$%3WEAv/3%$F ..... OSDFKJSL43$%^DFg==

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

只是猜测一下。。。但是你试过这样的东西吗

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

我不知道有哪种库是Python的标准库

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


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

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测试生成的密钥,因此请让我知道它是否有效(我认为应该是这样)

base64解码版本的SSH keygen输出到key.pub()的内容。密钥文件的格式是

b64encode('\x00\x00\x00\x07ssh-rsa%s%s' % (key.pub()[0], key.pub()[1]))
2012年9月5日编辑:

我刚刚意识到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())), )

下面是一个使用Twisted Conch库的示例,该库在封面下利用PyCrypto。您可以在以下位置找到API文档:


以防万一,将来会有旅客希望这样做。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…

使用
密码术
pycrypto
不再处于开发阶段,如果可能,您应该使用加密技术。自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


注意:如果您的SSH客户端不理解此私钥格式,
PKCS8
TraditionalOpenSSL

,您可以使用
pycryptodome
,如中所述:


如果需要,也可以使用
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')

这离我要找的东西太近了。不幸的是,我不确定它是否有效。B64编码的字符几乎与ssh keygen输出的字符匹配,但在第一个AAAA和密钥的其余部分之间还有24个字符。也就是说,b64密钥看起来像“ssh rsa AAAAabcdef…==”而ssh keygen密钥看起来像“ssh rsa AAAAabcdef…==”还有其他提示吗?仔细看,前4个字节表示字符串ssh rsa的长度,后面是key.pub()中的字节[0]所以这很容易构造。我刚刚在pycrypto的分支中添加了这段代码,你介意解释一下在生成密钥后对密钥做了什么吗?特别是关于模数,这里有一个填充,我现在不能很好地解释它,这是3年前的事了,这段代码实际上很难看,你应该试着阅读pycrypto实现,而不是这个,代码在这里:检查pycryto,因为已经有exportKey方法的格式“OpenSSH”。pycrypto
pycryptodome
是一个替代品。我想你的意思是
65537
而不是
65337
。前者更为常见,但共识是65537(即2^16+1)是安全的。65337不符合NIST标准。在
key.exportKey('PEM')
中,参数表示输出格式。有三个选项:“DER”-二进制编码,“PEM”-纹理编码,“OpenSSH”-纹理编码符合OpenSSH规范。@signal根据,OpenSSH for export“仅适用于公钥(而非私钥)”。我相信您引用的短语与exportKey使用“OpenSSH”格式选项有关,而不是exportKey方法本身。例如,文档中说,您可以使用“OpenSSH”格式arg作为公钥(如我所做),使用“PEM”作为私钥(如我所做);请参阅Python3中的其他答案,八进制文字必须有一个“0o”前缀,因此:
chmod(“/tmp/private.key”,0600)
变成
chmod(“/tmp/private.key”,0o600)
注意事项:
加密>=1.4.0
的版本要求,缺少导入语句:
来自cryptography.hazmat.backends导入默认\u后端作为加密\u默认\u后端
谢谢!相应地进行了调整。如何将此格式转换为其他格式,即`ssh rsa AAAABCASDDBM$%3WEAv/3%$F。。。。。OSDFKJSL43$%^DFg=='这是最好的,目前在主要项目中使用,至少在2018年,这应该是公认的答案。这个问题中的大多数其他内容都已明显老化。