it-swarm.com.de

So erstellen Sie SSH-Schlüsselpaare mit Python

Ich versuche, ein Skript zu schreiben, um SSH-Identitätsschlüsselpaare für mich zu generieren.

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

Die Datei /tmp/my.key sieht jetzt gut aus.

Durch Ausführen von ssh-keygen -y -f /tmp/my.key > /tmp/my.key.pub kann ich den öffentlichen Schlüssel extrahieren.

Meine Frage ist, wie ich den öffentlichen Schlüssel aus Python extrahieren kann. Die Verwendung von key.save_pub_key("/tmp/my.key.pub") speichert etwa Folgendes:

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

Wenn ich nach etwas suche:

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

Nur für den Fall, dass zukünftige Reisende dies tun möchten. Das RSA-Modul unterstützt jetzt das Ausschreiben des öffentlichen Schlüssels im OpenSSH-Format (möglicherweise nicht zum Zeitpunkt früherer Posts). Ich denke, Sie können machen, was Sie brauchen mit:

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

Speichern Sie Ihren privaten Schlüssel natürlich nicht in/tmp ...

29

Verwenden Sie cryptography! pycrypto befindet sich nicht mehr in der aktiven Entwicklung, und wenn möglich sollten Sie Kryptographie verwenden. Seit Juni können auch öffentliche SSH-Schlüssel generiert werden:

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
)

Hinweis: Sie benötigen mindestens die Version 1.4.0.

29
Dave Halter

Edit 05/09/2012:

Ich habe gerade realisiert, dass Pycrypto bereits folgendes hat:

import os
from Crypto.PublicKey import RSA

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

Dieser Code funktioniert für mich:

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

Der von ssh verwendete Schlüssel ist nur base64-codiert. Ich kenne M2Crypto nicht sehr viel, aber nach einer kurzen Übersicht scheint es, als könnten Sie das tun, was Sie wollen:

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 %[email protected]%s' % (b64key, username, hostname)

with open(os.getenv('HOME')+'/.ssh/id_rsa.pub') as keyfile:
    keyfile.write(keystring)

Ich habe den generierten Schlüssel nicht mit SSH getestet, also lass es mich wissen, wenn es funktioniert (sollte ich denken)

4
mdeous

Die base64-decodierte Version von ssh-keygen gibt an den Inhalt von key.pub () das Format der Schlüsseldatei aus

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

Wie wäre es mit subprocess, um ssh-keygen aufzurufen?

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

Das obige kleine Programm erzeugt eine Ausgabe wie diese:

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

Hier ist ein Beispiel, das die Twisted Conch-Bibliothek verwendet, die PyCrypto unter der Abdeckung nutzt. Die API-Dokumentation finden Sie unter 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

Kannst du die AAAA ... Dfg == string daraus ziehen, während es ein Objekt ist? In diesem Fall können Sie einfach eine Datei selbst öffnen und speichern, anstatt die eingebaute Funktion save_pub_key zu verwenden.

0
saramah

Nur raten ... aber haben Sie so etwas ausprobiert ?:

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

Sie können pycryptodome wie in documentation beschrieben verwenden.

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

Ich kenne keine solche Bibliothek, die in Python standardmäßig enthalten ist.

Wenn Sie nach Bibliotheken von Drittanbietern suchen möchten, können Sie die Bibliothek paramiko nützlich finden (auch verfügbar unter PyPI ). Es implementiert das SSH-Protokoll und verfügt über Funktionen zum Umgang mit vorhandenen Schlüsseln, jedoch ohne deren Generierung.

Die Generierung von Schlüsseln kann eine nützliche Ergänzung zu dieser Bibliothek sein (Sie könnten mit den Entwicklern zusammenarbeiten um sie in die Paramiko-Bibliothek zu integrieren), und ein einfacher Start, als wenn Sie es von Grund auf machen.

0
bignose