Как генерировать пары ключей SSH с Python - PullRequest
30 голосов
/ 18 марта 2010

Я пытаюсь написать скрипт для генерации пар ключей идентификации 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==

Ответы [ 11 ]

34 голосов
/ 24 августа 2016

Используйте cryptography! pycrypto больше не находится в активной разработке, и если возможно, вы должны использовать криптографию С июня также можно генерировать открытые ключи 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.

32 голосов
/ 17 марта 2014

На всякий случай, если кто-нибудь из будущих путешественников захочет это сделать. Модуль 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...

6 голосов
/ 28 марта 2011

Изменить 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())), )
4 голосов
/ 18 марта 2010

Ключ, используемый 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, поэтому, пожалуйста, дайте мне знать, если он работает (если подумать)

2 голосов
/ 15 октября 2010

Версия s64-keygen декодированного base64 для вывода содержимого key.pub () в формате ключевого файла:

b64encode('\x00\x00\x00\x07ssh-rsa%s%s' % (key.pub()[0], key.pub()[1]))
1 голос
/ 27 февраля 2012

Вот пример использования библиотеки Twisted Conch, которая использует PyCrypto под крышками. Вы можете найти документацию по API на 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
1 голос
/ 18 марта 2010

Как насчет использования 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==
0 голосов
/ 06 декабря 2018

Вы можете использовать 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)
0 голосов
/ 18 марта 2010

Я не знаю такой библиотеки, которая входит в стандартную комплектацию Python.

Если вы хотите обратиться к сторонним библиотекам, вам может пригодиться библиотека paramiko (также доступна из PyPI ). Он реализует протокол SSH и обладает функциональностью для обработки существующих ключей, но не для их генерации.

Генерация ключей может быть полезным дополнением к этой библиотеке (вы можете поработать с разработчиками , чтобы включить ее в библиотеку Paramiko), и более легким началом, чем делать это с нуля.

0 голосов
/ 18 марта 2010

Просто угадай ... а ты пробовал что-то подобное?

1002 *
...