Generazione di una chiave privata da una stringa esadecimale con openssl

2

C'è un modo rapido per prendere una serie di numeri e codificarla come una chiave privata con la riga di comando openssl ? Inventare l'interfaccia CLI

openssl genpkey -fromhex 'FFFFFFFFF' -algorithm RSA

modifica: ovviamente qualsiasi numero casuale non sempre si adatta (dipende dal codice, con EC potrebbe essere il caso che la maggior parte dei numeri sia adatta), ma questo è parte dell'accordo. Se il numero non è una chiave privata valida, desidero che openssl mi urli.

Il caso d'uso principale è, verificando i calcoli con openssl. È davvero conveniente, ad esempio, scrivere un programma che converta la chiave privata in chiave pubblica e utilizzare openssl per assicurarsi che funzioni effettivamente.

    
posta Elazar Leibovich 28.01.2013 - 05:32
fonte

2 risposte

3

Ho paura che quello che stai chiedendo non ha molto senso.

Se in effetti hai già il set di numeri che compongono la tua chiave privata, tutto ciò che devi fare è esprimerlo come una stringa. E se puoi già farlo, allora per cosa hai bisogno di openssl? E se non puoi farlo, come farai a comunicarli a openssl? In genere se hai effettivamente i dati, allora anche hanno i mezzi per produrli in un formato di file standard.

Il formato della chiave standard utilizzato in x509 è semplicemente ASN.1 dati formattati usando DER (binario) o PEM (base64 ) regole di formattazione. Ecco un'attività divertente per vedere come appare:

$ openssl genrsa > key.pem

Ora abbiamo una coppia di chiavi RSA a 512 bit. Non particolarmente utile, ma piccolo.

$ openssl rsa -text < key.pem
Private-Key: (512 bit)
modulus:
    00:cc:95:9a:a2:ac:03:6b:77:11:52:be:06:86:8e:
    ....
publicExponent: 65537 (0x10001)
privateExponent:
    00:91:d1:b0:3e:72:4c:9d:b4:68:6c:89:75:2d:43:
    ....

Quindi questa è la tua chiave privata. I primi due campi; il modulo e publicExponent sono anche la tua chiave pubblica.

Come viene memorizzato? Possiamo ASN.1 decodificarlo senza elaborazione aggiuntiva:

$ openssl asn1parse < key.pem
    0:d=0  hl=4 l= 316 cons: SEQUENCE          
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=2 l=  65 prim: INTEGER           :CC959AA2AC036B77...
   74:d=1  hl=2 l=   3 prim: INTEGER           :010001
   79:d=1  hl=2 l=  65 prim: INTEGER           :91D1B03E724C9DB4...
  146:d=1  hl=2 l=  33 prim: INTEGER           :E831F72E74263DDC...
   ...

Come puoi vedere, il file contiene semplicemente i campi di dati previsti lasciati cadere uno dopo l'altro, senza fluff. Finché hai gli identificatori ASN.1 giusti per ogni campo, hai praticamente finito.

Naturalmente, se non vuoi preoccuparti delle regole di codifica binaria, puoi leggere i campi ASN.1 come testo usando il formato "conf file" descritto in documentazione per ASN1_generate_nconf . Sembra più questo:

asn1=SEQUENCE:private_key
[private_key]
version=INTEGER:0
n=INTEGER:0xCC959AA2AC036B77...
e=INTEGER:0x010001
d=INTEGER:0x91D1B03E724C9DB4...

Puoi caricare questo formato nel comando asn1parse usando l'opzione -genconf <file> , ma non sono sicuro che il programma della riga di comando ti consenta di emettere un file PEM o DER dai contenuti. Anche se, realisticamente, un programma C che usa l'API openssl per fare questo sarebbe solo lungo circa 20 righe, quindi è qualcosa che potresti facilmente fare se necessario.

Tuttavia, tutto questo sembra abbastanza ingegnoso; perché dovresti aver bisogno di fare questo è oltre me. Ma immagino che se tu fossi abbastanza esperto in questa tecnologia abbastanza per sapere che hai bisogno di farlo, allora scrivere l'utilità appropriata per farlo sarebbe banale.

    
risposta data 28.01.2013 - 08:06
fonte
1

Non penso sia possibile: le chiavi private e pubbliche non sono numeri casuali, ma derivano da numeri primi a due fattori appositamente predisposti.

La probabilità che la tua stringa esadecimale sia una chiave privata adeguata sarebbe trascurabile.

O hai fornito una chiave privata valida generata in altro modo, ad esempio 97a40cf79c13f403f1ecb560fbfd3408ec4bc87b045f9b84eab04a930ac207dd (che ti lascerebbe il problema di come generare la chiave in primo luogo, ma in questo caso avresti solo è necessario codificarlo in ASN), oppure dovresti codificare una chiave privata fornendo un intervallo in cui cercare una coppia lavorabile di numeri primi di ~ 512 bit, da cui creare un composito di ~ 1024 bit, ad un altro algoritmo di ricerca dei primi. Questo, tuttavia, sa di "costruire il tuo sistema di crittografia", che è ampiamente considerato una mossa poco saggia.

UPDATE

OK, dì che hai tutte le informazioni che costituiscono una chiave privata - modulo, composito primo, fattori, esponenti, il lotto. OpenSSL non fornisce (AFAIK) per la creazione di un blocco PrivateKey da argomenti della riga di comando. Quindi dovresti farlo tu stesso, da RFC 3447 Appendice A.1.2:

A.1.2 RSA private key syntax

   An RSA private key should be represented with the ASN.1 type
   RSAPrivateKey:

      RSAPrivateKey ::= SEQUENCE {
          version           Version,
          modulus           INTEGER,  -- n
          publicExponent    INTEGER,  -- e
          privateExponent   INTEGER,  -- d
          prime1            INTEGER,  -- p
          prime2            INTEGER,  -- q
          exponent1         INTEGER,  -- d mod (p-1)
          exponent2         INTEGER,  -- d mod (q-1)
          coefficient       INTEGER,  -- (inverse of q) mod p
          otherPrimeInfos   OtherPrimeInfos OPTIONAL
      }

Il pacchetto inizierà quindi con un carattere "0" (0x30 hex), seguito da un'intestazione di 82 HH LL (dove 0xHHLL è la lunghezza del pacchetto - ottengo due meno della lunghezza del file della chiave binaria, anche se aspettavo quattro di meno, potreste voler verificare con una buona sequenza decodificata in base allo standard PEM 64).

Quindi ogni INTEGER verrà codificato sequenzialmente da una struttura come questa

unsigned char type;    // 0x02
unsigned char length;  // 
unsigned char ose[];   // "length" bytes of data (see RFC 3447, #4.1)

Dovresti quindi:

  • implementare I2OSP da RFC 3447 (ma se si ha la rappresentazione esadecimale, questo è semplice)
  • impacchetta i numeri come sopra
  • Codifica in Base64 ( NOTA : ci sono in realtà due codifiche base64, potresti voler controllare l'alfabeto con riferimento appropriato ),
  • "sandwich" tra -----BEGIN RSA PRIVATE KEY-----/-----END RSA PRIVATE KEY-----

e dovresti farlo.

    
risposta data 28.01.2013 - 08:11
fonte

Leggi altre domande sui tag