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==
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 ...
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
.
É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())), )
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)
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]))
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 ==
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
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.
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('-----')])
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)
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.