web-dev-qa-db-fra.com

Comment générer des paires de clés SSH avec Python

J'essaie d'écrire un script pour générer des paires de clés SSH Identity pour moi.

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

Le fichier /tmp/my.key a fière allure maintenant.

En exécutant ssh-keygen -y -f /tmp/my.key > /tmp/my.key.pub, je peux extraire la clé publique.

Ma question est comment puis-je extraire la clé publique de python? Utiliser key.save_pub_key("/tmp/my.key.pub") enregistre quelque chose comme:

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

Quand je cherche quelque chose comme:

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

Juste au cas où de futurs voyageurs voudraient le faire. Le module RSA prend désormais en charge l'écriture de la clé publique au format OpenSSH (ce qui n'était peut-être pas le cas lors des publications précédentes). Donc, je pense que vous pouvez faire ce dont vous avez besoin avec:

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'))

Évidemment, ne stockez pas votre clé privée dans/tmp ...

29
fruitbeeriswrong

Utilisez cryptography! pycrypto n'est plus en développement actif et si possible vous devriez utiliser la cryptographie. Depuis juin, il est également possible de générer des clés publiques 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
)

Remarque: Vous devez avoir au moins la version 1.4.0.

29
Dave Halter

Éditer le 05/09/2012:

Je viens de me rendre compte que pycrypto a déjà ceci:

import os
from Crypto.PublicKey import RSA

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

Ce code fonctionne pour moi:

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())), )
6
Jorge E. Cardona

La clé utilisée par ssh est encodée en base64, je ne connais pas beaucoup M2Crypto, mais après un bref aperçu, il semble que vous puissiez faire ce que vous voulez de cette façon:

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)

Je n'ai pas testé la clé générée avec SSH, alors faites-le moi savoir si cela fonctionne (je devrais penser)

4
mdeous

La version décodée en base64 de la sortie ssh-keygen dans le contenu de key.pub ()

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

Que diriez-vous d'utiliser subprocess pour appeler 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')

Le petit programme ci-dessus produira un résultat comme celui-ci:

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA ... 9Jbn6D74JOKpaOU050ltyNRw == 
1
Pavel Repin

Voici un exemple utilisant la bibliothèque Twisted Conch qui exploite PyCrypto sous les couvertures. Vous pouvez trouver la documentation de l'API à l'adresse 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
gabrtv

Pouvez-vous obtenir la chaîne AAAA ... Dfg == en tant qu’objet? Si tel est le cas, vous pouvez simplement ouvrir un fichier vous-même et l'enregistrer au lieu d'utiliser la fonction intégrée Save_pub_key.

0
saramah

Juste deviner ... mais avez-vous essayé quelque chose comme ça ?:

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

Vous pouvez utiliser pycryptodome comme décrit dans 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)
0
rominf

Je ne connais pas de bibliothèque de ce type livrée en standard avec Python.

Si vous souhaitez consulter des bibliothèques tierces, vous trouverez peut-être que la bibliothèque paramiko est utile (également disponible dans PyPI ). Il implémente le protocole SSH et dispose d'une fonctionnalité permettant de gérer les clés existantes, mais pas de les générer.

La génération de clés peut être un complément utile à cette bibliothèque (vous pouvez travailler avec les développeurs pour l'incorporer à la bibliothèque Paramiko) et un démarrage plus facile que de le faire à partir de zéro.

0
bignose