2012-04-17 5 views
5

Stiamo generando chiavi rsa e vorremmo memorizzarle come hash pubblici e privati64, come sono abituato a vedere nella mia cartella ~/.ssh sul mio scatola di linux.generazione di chiavi rsa pubbliche/private serializzate da NED Big Ints

Tuttavia, abbiamo a che fare con i primitivi RSA - i valori n, e ed d.

Come si generano gli hash base64 rispetto a tali valori? E viceversa (se non è ovvio).

+0

Perché non http://docs.python.org/3.4/library/base64.html e/o (https://pypi.python.org/pypi/rsa http://stuvel.eu/ rsa)? – user2284570

+0

@ J.Random eventuali risposte? – user2284570

risposta

2

base64 è uno schema di codifica per dati binari rappresentati come testo, non un algoritmo di hash. Se ti riferisci all'impronta digitale, è MD5.

Sia per l'impronta digitale che per i dati con codifica Base64, è possibile consultare o addirittura riutilizzare lo Twisted's Conch implementation.

1

è necessario utilizzare la codifica ASN.1 corretta e quindi base64.

sfortunatamente, non ho idea di quale sia la codifica ASN.1 corretta (non capisco veramente ASN.1). è integrato in openssl, ma non riesco a trovare un modo per accedervi dalla riga di comando. puoi scrivere da C usando http://www.openssl.org/docs/crypto/RSA_print.html e http://www.openssl.org/docs/crypto/rsa.html

hai python nei tag. pyopenssl avvolge openssl e potrebbe fornire un percorso più semplice - https://code.launchpad.net/pyopenssl - ma guardando la sorgente sembra che siano troppo di alto livello (non sembrano esporre la struttura RSA).

se si parla ASN.1 (o avere una biblioteca che fa così, come http://pyasn1.sourceforge.net/) allora questo potrebbe essere tutto ciò che serve - https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem

(Mi rendo conto che è piuttosto incompleta - io non sto cercando il bounty, basta scaricare quello che so nel caso sia sufficiente per aiutare - in pratica "ASN.1 per DER" è il bit che ti manca, è ciò che definisce la struttura in modo che le diverse parti possano essere separate quando rilette)

+0

La chiave pubblica id_rsa.pub ha comunque un formato diverso, vedi la mia risposta (sarà aggiornata con i dettagli). –

1

Aggiornerò questo con maggiori dettagli e un decodificatore quando sarò libero in poche ore.

def bitlength_and_integer_in_bytes(n): 
    bytes_length = n.bit_length()//8+1 
    return bytes_length.to_bytes(4, "big")+n.to_bytes(bytes_length, "big") 

def gen_id_rsa_pub(n,e): 
    return b"ssh-rsa "+base64.b64encode(b"\x00\x00\x00\x07ssh-rsa"+bitlength_and_integer_in_bytes(e)+bitlength_and_integer_in_bytes(n))+b" RSA key description" 
open("id_rsa.pub", "bw").write(gen_id_rsa_pub(n,e)) 
##import base64 
##from pyasn1.codec.der import decoder 
##s = "\n".join(open(".ssh/id_rsa").readlines()[1:-1]) 
##d = decoder.decode(base64.b64decode(s)) 
import base64 
from pyasn1.codec.der import encoder 
from pyasn1.type.univ import * 
#below from http://stackoverflow.com/a/9758173/443348 
def egcd(a, b): 
    if a == 0: 
     return (b, 0, 1) 
    else: 
     g, y, x = egcd(b % a, a) 
     return (g, x - (b // a) * y, y) 

def modinv(a, m): 
    g, x, y = egcd(a, m) 
    if g != 1: 
     raise Exception('modular inverse does not exist') 
    else: 
     return x % m 

#got example values from https://en.wikipedia.org/wiki/RSA_(algorithm)#A_working_example 
p = 61 
q = 53 
n = p*q #3233 
totient_n = (p-1)*(q-1) # 3120 
e = 17 # Should be coprime to 3120 
d = modinv(e, totient_n) #2753 

s = Sequence() 
def setvalues(sequence, values): 
    for index, value in enumerate(values): 
     sequence.setComponentByPosition(index, value) 

q = n/p 

setvalues(s, map(Integer, (0, n, e, d, p, q, d%(p-1), d%(q-1), modinv(q,p)))) 
id_rsa = b"-----BEGIN RSA PRIVATE KEY-----\n"+base64.b64encode(encoder.encode(s))+b"\n-----END RSA PRIVATE KEY-----\n" 
open("id_rsa", "bw").write(id_rsa)