2010-03-17 23 views
25

Sto tentando di scrivere uno script per generare coppie di chiavi SSH Identity per me.Come generare coppie di chiavi SSH con Python

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

Il file /tmp/my.key sembra ottimo ora.

Eseguendo ssh-keygen -y -f /tmp/my.key > /tmp/my.key.pub Posso estrarre la chiave pubblica.

La mia domanda è come posso estrarre la chiave pubblica da Python? Utilizzando key.save_pub_key("/tmp/my.key.pub") salva qualcosa di simile:

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

quando sto cercando qualcosa di simile:

ssh-rsa AAAABCASDDBM$%3WEAv/3%$F ..... OSDFKJSL43$%^DFg== 
+0

Controllare pycryto, poiché ha già il formato 'OpenSSH' per il metodo exportKey. –

+0

pycrypto [non è mantenuto e ha vulnerabilità note] (https://github.com/dlitz/pycrypto/issues/173). 'pycryptodome' è una sostituzione drop-in. – galgalesh

+0

Penso che intendessi '65537' piuttosto che' 65337'. Il primo è molto più comune. [I rischi associati all'uso di altri numeri sono contestati] (http://security.stackexchange.com/questions/2335/should-rsa-public-exponent-be-only-in-3-5-17-257-or- 65537-dovuto-a-sicurezza-c), ma il consenso è che 65537 (cioè, 2^16 + 1) è sicuro. 65337 non è compatibile con NIST. – Zenexer

risposta

0

si può ottenere l'AAAA ... Dfg == stringa fuori di esso, mentre si tratta di un oggetto? Se è così, puoi semplicemente aprire un file tu stesso e salvarlo invece di usare la funzione built_pub_key integrata.

0

solo indovinare ... Ma avete provato qualcosa di simile ?:

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

non so di un tale libreria in Python.

È possibile trovare utile la libreria paramiko (anche available from PyPI). Implementa il protocollo SSH e ha funzionalità per gestire le chiavi esistenti, ma non le genera.

La generazione di chiavi potrebbe essere un'utile aggiunta a quella libreria (è possibile aggiungere work with the developers alla libreria) e iniziare in modo più semplice rispetto a farlo da zero.

1

Come utilizzare subprocess per richiamare 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') 

Il piccolo programma sopra produrrà un output simile a questo:

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA ... 9Jbn6D74JOKpaOU050ltyNRw== 
+2

L'invocazione di comandi esterni dovrebbe sempre essere l'ultima risorsa. – dom0

+3

Dipende, @csde_rats. Ho i miei dubbi sui bit "sempre" e "l'ultimo restort". Invocare processi da altri processi non è poi così male. Interi sistemi operativi erano costruiti secondo quel principio :) –

4

La chiave usata da ssh è solo codificato Base64, non so M2Crypto molto, ma dopo una rapida panoramica esso sembra che si possa fare ciò che si vuole in questo modo:

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) 

non ho la prova la chiave generata con SSH, quindi per favore fatemi sapere se funziona (dovrebbe credo)

+1

questo è oh così vicino a quello che sto cercando. Sfortunatamente, non sono sicuro che funzioni. I caratteri codificati in b64 corrispondono quasi a quelli di ssh-keygen, ma ci sono altri 24 caratteri tra il primo AAAA e il resto della chiave. cioè, la chiave b64 sembra "ssh-rsa AAAAabcdef ... ==" e la chiave ssh-keygen ha l'aspetto di "ssh-rsa AAAA <24 letters> abcdef ... ==" Altri suggerimenti? – Lee

+0

Si prega di affermare che la risposta funziona o non funziona. – ThorSummoner

2

La base64 decodificati versione di uscita ssh-keygen per il contenuto di key.pub() il formato del file di chiavi è

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

Guardandolo più i primi 4 byte rappresentano la lunghezza della stringa ssh-rsa, seguita dai byte trovati in key.pub() [0], quindi è facile da costruire. – manis

4

Edit 05/09/2012:

Ho appena realizzato che pycrypto ha già questo:

import os 
from Crypto.PublicKey import RSA 

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

questo codice funziona per 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())),) 
+0

Ho appena aggiunto questo codice a un fork di pycrypto all'indirizzo https://github.com/jorgeecardona/pycrypto –

+0

Ti dispiacerebbe spiegare un po 'di più su cosa viene fatto alla chiave dopo generazione? Soprattutto rispetto al 'modulo '? – Will

+0

C'è un padding, non posso spiegarlo abbastanza bene in questo momento, questo era 3 anni fa, questo codice in realtà è brutto, e dovresti provare a leggere l'implementazione di pycrypto invece questo, il codice è qui: https: //github.com/dlitz/pycrypto/blob/master/lib/Crypto/PublicKey/RSA.py#L678 –

1

Ecco un esempio che utilizza la libreria Twisted Conch che sfrutta PyCrypto sotto le copertine.È possibile trovare la documentazione delle API a 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 
27

Solo nel caso ci siano futuri viaggiatori che cercano di fare questo. Il modulo RSA supporta ora la scrittura della chiave pubblica nel formato OpenSSH (probabilmente non al momento dei post precedenti). Quindi penso che si può fare quello che ti serve con:

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

Ovviamente non conservare a sei chiave privata in/tmp ...

+4

In 'key.exportKey ('PEM')', l'argomento indica l'output ** formato **. Ci sono tre opzioni: 'DER' - codifica binaria, 'PEM' - codifica texture, 'OpenSSH' - codifica texture secondo spec. OpenSSH. – signal

+0

@signal Secondo [la documentazione] (https://pythonhosted.org/pycrypto/Crypto.PublicKey.RSA._RSAobj-class.html#exportKey), OpenSSH per l'esportazione è "adatto solo per le chiavi pubbliche (non per le chiavi private) ". – elBradford

+0

Credo che la frase citata si riferisca all'utilizzo dell'opzione di formato 'OpenSSH' con exportKey piuttosto che il metodo exportKey stesso, ad esempio i documenti dicono che è possibile utilizzare l'argomento di formato 'OpenSSH' per la chiave pubblica, come ho fatto io e 'PEM' per la chiave privata come ho fatto. – fruitbeeriswrong

15

Usa cryptography! pycrypto non è più in sviluppo attivo e se possibile dovresti usare la crittografia. Dal giugno è possibile generare chiavi pubbliche SSH così:

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 
) 

Nota: è necessario almeno la versione 1.4.0.

+3

Punti di nota: requisito di versione di 'cryptography> = 1.4.0' e manca un'istruzione import:' da cryptography.hazmat.backends importa default_backend come crypto_default_backend' – Samveen

+0

Grazie! Regolato di conseguenza. –

+0

Come si converte questo in un altro formato, ad esempio 'ssh-rsa AAAABCASDDBM $% 3WEAv/3% $ F .....OSDFKJSL43 $%^DFg == ' – user592419

Problemi correlati