Generando clave privada desde una cadena hexadecimal con openssl

2

¿Hay una forma rápida de tomar un conjunto de números y codificarlo como una clave privada con la línea de comando openssl ? Inventar la interfaz CLI

openssl genpkey -fromhex 'FFFFFFFFF' -algorithm RSA

editar: por supuesto, no caben números aleatorios (depende del cifrado, con EC podría ser el caso de que caben la mayoría de los números), pero eso es parte del trato. Si el número no es una clave privada válida, quiero que me grite openssl.

El caso de uso principal es verificar cálculos con openssl. Es realmente conveniente, por ejemplo, escribir un programa que convierta la clave privada en una clave pública, y use openssl para asegurarse de que realmente funciona.

    
pregunta Elazar Leibovich 28.01.2013 - 05:32
fuente

2 respuestas

3

Me temo que lo que estás preguntando no tiene mucho sentido.

Si de hecho ya tiene el conjunto de números que componen su clave privada, todo lo que necesita hacer es expresar eso como una cadena. Y si ya puede hacer eso, ¿para qué necesita openssl? Y si no puedes hacer eso, entonces, ¿cómo los vas a comunicar a openssl? Por lo general, si realmente tiene los datos, también tiene los medios para generarlos en un formato de archivo estándar.

El formato de clave estándar utilizado en x509 es simplemente ASN.1 datos formateados usando DER (binario) o PEM (base64 ) reglas de formateo. Aquí hay una actividad divertida para ver cómo se ve:

$ openssl genrsa > key.pem

Ahora tenemos un par de claves RSA de 512 bits. No es particularmente útil, pero pequeño.

$ 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:
    ....

Así que esa es tu clave privada. Los dos primeros campos; el módulo y publicExponent también son su clave pública.

¿Cómo se almacena esto? Podemos ASN.1 descodificarlo sin procesamiento adicional:

$ 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...
   ...

Como puede ver, el archivo simplemente contiene los campos de datos esperados que se colocaron uno tras otro, sin pelusa. Siempre y cuando tengas los identificadores ASN.1 correctos para cada campo, estarás listo.

Por supuesto, si no quiere molestarse con las reglas de codificación binarias, puede leer los campos ASN.1 como texto usando el formato "conf archivo" descrito en documentation para ASN1_generate_nconf . Se parece más a esto:

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

Puede cargar este formato en el comando asn1parse utilizando la opción -genconf <file> , pero no estoy seguro de que el programa de línea de comandos le permita generar un archivo PEM o DER desde el contenido. Aunque, de manera realista, un programa en C que utiliza la API de openssl para hacer eso solo tendría unas 20 líneas, por lo que es algo que podría hacer fácilmente si fuera necesario.

Sin embargo, todo esto suena bastante artificial; ¿Por qué posiblemente necesitarías hacer esto está más allá de mí? Pero me imagino que si tuvieras la suficiente experiencia en esta tecnología para saber que tenías la necesidad de hacerlo, entonces escribir la utilidad adecuada para hacerlo sería trivial.

    
respondido por el tylerl 28.01.2013 - 08:06
fuente
1

No creo que sea posible: las claves públicas y privadas no son números aleatorios, sino que se derivan de números primos grandes de dos factores especialmente diseñados.

La probabilidad de que su cadena hexadecimal sea una clave privada adecuada sería despreciable.

O bien, usted suministró una clave privada válida generada de alguna otra manera, por ejemplo, 97a40cf79c13f403f1ecb560fbfd3408ec4bc87b045f9b84eab04a930ac207dd (lo que le dejaría con el problema de cómo generar la clave en primer lugar, pero luego solo debe codificarlo con ASN), o tendría que codificar una clave privada proporcionando un rango donde buscar un par viable de ~ 512 bits primos, a partir de los cuales construir un compuesto de ~ 1024 bits, a otro algoritmo de búsqueda principal. Eso, sin embargo, huele a "construir tu propio sistema de criptografía", que es ampliamente considerado como un movimiento imprudente.

ACTUALIZACIÓN

Bien, digamos que tiene toda la información que constituye una clave privada: módulo, primos compuestos, factores, exponentes, el lote. OpenSSL no proporciona (AFAIK) para construir un bloque PrivateKey a partir de argumentos de la línea de comandos. Por lo tanto, tendría que hacerlo usted mismo, de RFC 3447 Apéndice 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
      }

Su paquete comenzaría entonces con un carácter "0" (0x30 hex), seguido de un encabezado de 82 HH LL (donde 0xHHLL es la longitud del paquete; obtengo dos menos que la longitud del archivo de clave binaria, incluso si esperaba menos de cuatro ; es posible que desee verificar con una buena secuencia descodificada de PEM base64 conocida.

Luego, cada INTEGER se codificará secuencialmente por una estructura como esta

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

Entonces necesitarías:

  • implemente el I2OSP de RFC 3447 (pero si tiene la representación hexadecimal, eso es sencillo)
  • empaquetar los números como se indica arriba
  • Codifíquelos en Base64 ( NOTA : en realidad hay dos codificaciones en base64; es posible que desee verificar el alfabeto con las herramientas referencia apropiada ),
  • "sandwich" ellos entre -----BEGIN RSA PRIVATE KEY-----/-----END RSA PRIVATE KEY-----

y deberías haber terminado.

    
respondido por el LSerni 28.01.2013 - 08:11
fuente

Lea otras preguntas en las etiquetas