2012-04-17 5 views
5

Мы генерируем ключи rsa и хотели бы хранить их как общедоступные и частные хэши base64, например, я привык видеть в своей папке ~/.ssh на моем linux box.генерация серийных rsa открытых/закрытых ключей от NED Big Ints

Однако мы имеем дело с примитивами RSA - значениями n, e и d.

Как сгенерировать хэши base64 из этих значений? И наоборот (если это не очевидно).

+0

Почему не http://docs.python.org/3.4/library/base64.html и/или (https://pypi.python.org/pypi/rsa http://stuvel.eu/ rsa)? – user2284570

+0

@ J.Random ответы? – user2284570

ответ

2

base64 - это схема кодирования двоичных данных, представленная как текст, а не хеширующий алгоритм. Если вы имеете в виду отпечаток пальца, это MD5.

Как для отпечатков пальцев, так и для данных с кодировкой base64, вы можете проконсультироваться или даже повторно использовать Twisted's Conch implementation.

1

вам необходимо использовать правильную кодировку ASN.1, а затем base64.

К сожалению, я не знаю, что такое правильная кодировка ASN.1 (я действительно не понимаю ASN.1). он встроен в openssl, но я не могу найти способ получить к нему доступ из командной строки. вы можете написать его из C, используя http://www.openssl.org/docs/crypto/RSA_print.html и http://www.openssl.org/docs/crypto/rsa.html

у вас есть питон в тегах. pyopenssl wraps openssl и может обеспечить более простой путь - https://code.launchpad.net/pyopenssl - но, глядя на источник, кажется, что они слишком высокого уровня (они, похоже, не отображают структуру RSA).

если говорить ASN.1 (или есть библиотека, которая делает так, как http://pyasn1.sourceforge.net/), то это может быть все, что вам нужно - https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem

(я понимаю, что это весьма неполны - я не ищу для щедрость, просто сбрасывая то, что я знаю, в случае, если этого достаточно, чтобы помочь - в основном «ASN.1 для DER» - это бит, который вам не хватает, это то, что определяет структуру, чтобы различные части можно было отделить при чтении)

+0

Открытый ключ id_rsa.pub имеет другой формат, однако, см. Мой ответ (он будет обновлен с подробной информацией). –

1

Я обновлю это с более подробной информацией и декодером, когда я получу бесплатное через несколько часов.

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)