如何使用 Python 生成 SSH 密钥对

发布于 2024-08-25 17:33:50 字数 678 浏览 4 评论 0 原文

我正在尝试编写一个脚本来为我生成 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==

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==

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

ゝ杯具 2024-09-01 17:33:50

使用密码学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 客户端不理解此私钥格式,请替换 PKCS8TraditionalOpenSSL

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.

Note: If your SSH client does not understand this private key format, replace PKCS8 with TraditionalOpenSSL.

会傲 2024-09-01 17:33:50

以防万一未来有任何旅行者想要这样做。 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", 0o600) #use an 0o prefix for octal integers
    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 中...

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", 'wb') as content_file:
    chmod("/tmp/private.key", 0o600) #use an 0o prefix for octal integers
    content_file.write(key.exportKey('PEM'))
pubkey = key.publickey()
with open("/tmp/public.key", 'wb') as content_file:
    content_file.write(pubkey.exportKey('OpenSSH'))

The files are opened with a 'wb' as the keys must be written in binary mode.
Obviously don't store you're private key in /tmp...

2024-09-01 17:33:50

编辑 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())), )

Edit 05/09/2012:

I just realized that pycrypto already has this:

import os
from Crypto.PublicKey import RSA

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

This code works for me:

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())), )
蓝天 2024-09-01 17:33:50

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

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)

樱花坊 2024-09-01 17:33:50

ssh-keygen 的 Base64 解码版本输出到 key.pub() 的内容,密钥文件的格式为

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

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]))
涙—继续流 2024-09-01 17:33:50

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

If you want, you could just also use ssh-keygen itself.
You can extend this to also create your file, and just use open to read the content later, but i focused on creating a .pub key from an already existing key here.

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')
惯饮孤独 2024-09-01 17:33:50

只是猜测......但你尝试过这样的事情吗?:

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

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('-----')])
别闹i 2024-09-01 17:33:50

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

Can you get the AAAA...Dfg== string out of it while it's an object? If so, you could simply open a file yourself and save that instead of using the built in save_pub_key function.

如梦初醒的夏天 2024-09-01 17:33:50

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

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

Here is an example using the Twisted Conch library which leverages PyCrypto under the covers. You can find the API documentation at http://twistedmatrix.com/documents/current/api/twisted.conch.ssh.keys.html:

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
伴随着你 2024-09-01 17:33:50

您可以按照 文档

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)

You can use pycryptodome as described in documentation:

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)
2024-09-01 17:33:50

pip install ssh-key-maker

import ssh_key_maker

#对于 Windows 用户

ssh_key_maker.generate_ssh_key()

pip install ssh-key-maker

import ssh_key_maker

#for windows users

ssh_key_maker.generate_ssh_key()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文