Saltar al contenido

Cómo convertir un ECDSA key al formato PEM

Presta atención porque en esta noticia vas a encontrar la contestación que buscas.Esta división ha sido probado por nuestros expertos para garantizar la calidad y veracidad de nuestro contenido.

Solución:

Estás reclamando tu crudo key está en formato DER de OpenSSL, que no lo es. También estás clamando un privado key es un publico key, que no lo es, y afirmar que está cifrado con contraseña, lo cual es incorrecto de cualquier manera: público keys nunca están encriptados y son privados keys en los formatos DER específicos del algoritmo “tradicional” también conocido como “heredado” de OpenSSL (para ECC, definido por SECG SEC1) no se pueden cifrar. (OTOH privado keys en formato PKCS8 se puede cifrar con contraseña en DER o PEM, aunque PEM es más conveniente. Y el formato FWIW PKCS12 siempre está cifrado con contraseña y siempre DER.)

Un ECC (ECDSA, ECDH, ECMQV, etc.) key es siempre relativo a alguna ‘curva’ (más exactamente, subgrupo de orden principal sobre una curva con un generador identificado, también conocido como punto base). Para bitcoin esto es secp256k1, pero su pregunta no dice que se limite a bitcoin y esta respuesta requeriría modificaciones para otras aplicaciones que usen otras curvas.

Si tu tambien tienes el publico key (como un punto sin comprimir), simplemente puede usar la solución de https://bitcoin.stackexchange.com/questions/66594/signing-transaction-with-ssl-private-key-to-pem. Concatenar las cadenas hexadecimales:

  a pre_string : 30740201010420
  the privkey  : (32 bytes as 64 hexits) 
  a mid_string : a00706052b8104000aa144034200 (identifies secp256k1) 
  the pubkey   : (65 bytes as 130 hexits)

y luego convierta el hexadecimal a binario y lea como DER, o convierta el hexadecimal (probablemente a través de binario) a base64 y envuelva con -----BEGIN/END EC PRIVATE KEY----- líneas para hacerlo PEM.

Si no tienes el publico key, puede modificarlo ligeramente. Concatenar las cadenas hexadecimales

302e0201010420 privkey_32bytes_64hexits a00706052b8104000a 

y convertir a binario, luego leer en openssl ec -inform d . Nota OpenSSL derivará el público key de lo privado key dada la curva, pero no almacenarla en la salida PEM, por lo que la lectura con software que no sea OpenSSL no está garantizada. Puede que necesites usar openssl ec -text [-noout] (en la entrada PEM o DER según convenga) para que el público key valor, luego regrese y cree la codificación más completa que incluya al público key como anteriormente.


ADICIONAL: ya que parece que no comprende las palabras de la respuesta, expondré esto con tanto detalle como pueda.

El valor a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 es lo privado crudo key representado en hexadecimal. Un valor privado secp256k1 es de 32 bytes en binario; cuando el binario se representa en hexadecimal, cada byte toma dos dígitos hexadecimales, por lo que 32 bytes toman 64 dígitos hexadecimales. Todo este valor es el privado sin procesar key. No hay ninguna parte que consta de 25 dígitos O 25 bytes que tenga algún significado útil. No tome ninguna parte de este valor de 25 puntos.

Para construir la representación OpenSSL / SECG de un privado key sin publico key, pon el maleficio string representando lo privado key – todo, sin modificaciones – entre las otras dos cadenas hexadecimales que mostré como segunda opción:

 302e0201010420 a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 a00706052b8104000a 

Luego convierta este hexadecimal combinado string a binario, y lea el resultado en openssl ec -inform d:

$ echo 302e0201010420 a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 a00706052b8104000a | xxd -r -p >48101258.1
$ openssl ec -inform d <48101258.1
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MC4CAQEEIKFAvVB6VzYOL6UDKYwDWFTw3LJIvtq756FNs5IKqs9XoAcGBSuBBAAK
-----END EC PRIVATE KEY-----

El resultado es el formato PEM, pero el formato PEM no incluye al público key, que indicas que quieres. Para ver los campos, incluido el público derivado key, agregar -text; para ver solo los campos y no la salida PEM, agregue -noout:

$ openssl ec -inform d <48101258.1 -text -noout
read EC key
Private-Key: (256 bit)
priv:
    a1:40:bd:50:7a:57:36:0e:2f:a5:03:29:8c:03:58:
    54:f0:dc:b2:48:be:da:bb:e7:a1:4d:b3:92:0a:aa:
    cf:57
pub:
    04:20:ea:6d:8c:e7:bc:bb:48:33:69:b2:91:1c:75:
    e5:60:2a:34:28:be:44:96:e9:7f:14:ad:52:fd:4a:
    6a:a0:e3:60:83:9c:6e:db:32:2a:22:55:7c:70:1e:
    d0:fa:1e:06:cf:57:4f:be:17:bd:6a:85:51:69:c5:
    65:96:72:cf:a9
ASN1 OID: secp256k1

Ahora, si quieres un formato PEM key incluido el publico key, llevar ambos las cadenas hexadecimales para el privado key (los 64 dígitos) Y el valor hexadecimal recién mostrado para el público keyy conéctelos a mi primero opción. También tenga en cuenta un público ECC key es un punto de curva que puede tener dos formas, comprimido o sin comprimir; el formulario generado aquí está descomprimido. Si lo necesita, lo agregaré más tarde. Un punto secp256k1 en forma sin comprimir tiene 65 bytes, representados en hexadecimal como 130 dígitos hexadecimales. (Cuales openssl ec formatos como 4 líneas cada una de 15 bytes con 5 bytes restantes).

$ echo 30740201010420 a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 a00706052b8104000aa144034200 
> 04:20:ea:6d:8c:e7:bc:bb:48:33:69:b2:91:1c:75: e5:60:2a:34:28:be:44:96:e9:7f:14:ad:52:fd:4a: 
> 6a:a0:e3:60:83:9c:6e:db:32:2a:22:55:7c:70:1e: d0:fa:1e:06:cf:57:4f:be:17:bd:6a:85:51:69:c5: 
> 65:96:72:cf:a9 | xxd -r -p >48101258.2
$ # note xxd -r -p ignores the colons; other hex programs may need them removed instead
$ openssl ec -inform d <48101258.2
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIKFAvVB6VzYOL6UDKYwDWFTw3LJIvtq756FNs5IKqs9XoAcGBSuBBAAK
oUQDQgAEIOptjOe8u0gzabKRHHXlYCo0KL5Elul/FK1S/UpqoONgg5xu2zIqIlV8
cB7Q+h4Gz1dPvhe9aoVRacVllnLPqQ==
-----END EC PRIVATE KEY-----

AÑADIDO 2019-02 para DavidS: como se muestra correctamente en la respuesta de k06a

  • la primera parte de mi midstring (o el sufijo completo para mi opción de solo privado) a00706052b8104000a es una etiqueta de contexto y una longitud a007 para una etiqueta OID y longitud 0605 conteniendo 2b8104000a que es 1.3.132.0.10 que es secp256k1 y

  • el resto de mi cuerda media a144034200 es una etiqueta de contexto y una longitud que contiene la longitud de la etiqueta y el encabezado de bits no utilizados para un BITSTRING, que es la clave pública sin procesar como un punto sin comprimir.

Hacer secp256r1 también conocido como P-256 o prime256v1 en su lugar, debe cambiar el AlgId.OID a 1.2.840.10045.3.1.7 que está codificado como a00a 0608 2a8648ce3d030107. Los valores de clave privada y clave pública para p256r1 son del mismo tamaño que para p256k1, pero el AlgId es más largo, por lo que también necesita cambiar la longitud de la SECUENCIA externa dando

30770201010420 privatekey32bytes # note 77 
a00a06082a8648ce3d030107 a144034200 publicpoint65bytes 

Formato de clave privada de curva elíptica:

ECPrivateKey ::= SEQUENCE 
 version        INTEGER  ecPrivkeyVer1(1)  (ecPrivkeyVer1),
 privateKey     OCTET STRING,
 parameters [0] ECParameters  NamedCurve  OPTIONAL,
 publicKey  [1] BIT STRING OPTIONAL

Entonces publicKey es OPTIONAL y teóricamente se puede perder.

Aquí hay un ejemplo de mi DER secp256k1 privado key:

30740201 01042092 E768CB72 0DC16924 27D156DB 39630748 0D1507B9 A4958450
2574B9A0 922F4BA0 0706052B 8104000A A1440342 00041954 9737B704 D1789A57
82E3430E 8259F904 71326081 054854D2 A5D096F9 686D05B0 30D98BA3 C60C056E
204CEF61 C0AC5B53 A9A6B9A0 5AFF9DA2 6CA4B65B 2E84

Intentando descomponer:

$ openssl asn1parse -inform DER -in <(echo "30740201 01042092 E768CB72 0DC16924 27D156DB 39630748 0D1507B9 A4958450 2574B9A0 922F4BA0 0706052B 8104000A A1440342 00041954 9737B704 D1789A57 82E3430E 8259F904 71326081 054854D2 A5D096F9 686D05B0 30D98BA3 C60C056E 204CEF61 C0AC5B53 A9A6B9A0 5AFF9DA2 6CA4B65B 2E84" | xxd -r -p)

Resultado del análisis ASN.1:

 0:d=0  hl=2 l= 116 cons: SEQUENCE          
 2:d=1  hl=2 l=   1 prim: INTEGER           :01
 5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:92E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4B
39:d=1  hl=2 l=   7 cons: cont [ 0 ]        
41:d=2  hl=2 l=   5 prim: OBJECT            :secp256k1
48:d=1  hl=2 l=  68 cons: cont [ 1 ]        
50:d=2  hl=2 l=  66 prim: BIT STRING  

Detallado (consulte https://bitcoin.stackexchange.com/a/66622/22979):

30 - ASN.1
74 - Length of all following bytes (116 bytes)

  02 - Type (integer)
  01 - Length of integer (1 byte)
  01 - Value of integer (1)

  04 - Type (octet string)
  20 - Length of string (32 bytes)
  92E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4B - Private Key

  A0 - Tag 0
  07 - Length of tag (7 bytes)
  06 - Type (Object ID)
  05 - Length of the Object ID (5 bytes)
  2b 81 04 00 0a - The object ID of the curve secp256k1

  A1 - Tag 1
  44 - Length of tag (68 bytes)
  03 - Type – Bit string
  42 - Length of the bit string (66 bytes)
  00 - ???
  04 - Uncompressed Public Key
  19549737B704D1789A5782E3430E8259F90471326081054854D2A5D096F9686D - Public Key X coord
  05B030D98BA3C60C056E204CEF61C0AC5B53A9A6B9A05AFF9DA26CA4B65B2E84 - Public Key Y coord

Eliminé el objeto de clave pública y la longitud ASN.1 fija de 116 bytes (0x74) a 46 bytes (0x2e):

$ openssl asn1parse -inform DER -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)

Resultado obtenido:

 0:d=0  hl=2 l=  46 cons: SEQUENCE          
 2:d=1  hl=2 l=   1 prim: INTEGER           :01
 5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:92E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4B
39:d=1  hl=2 l=   7 cons: cont [ 0 ]        
41:d=2  hl=2 l=   5 prim: OBJECT            :secp256k1

Intentando obtener una clave pública:

$ openssl ec -inform DER -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)

Resultado:

read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MC4CAQEEIJLnaMtyDcFpJCfRVts5YwdIDRUHuaSVhFAldLmgki9LoAcGBSuBBAAK
-----END EC PRIVATE KEY-----

Un intento más:

$ openssl ec -inform DER -text -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)

Resultado:

read EC key
Segmentation fault: 11

Usé el sistema OSX openssl - parece que lo es LibreSSL 2.2.7.

Adicional: Se informó un error a LibreSSL: https://github.com/libressl-portable/portable/issues/395
ACTUALIZAR: En la última versión de macOS 10.15.1, openssl preinstalado (LibreSSL 2.8.3) corrigió este error.

Luego instalé el último openssl: brew install openssl

/usr/local/Cellar/openssl/1.0.2n/bin/openssl ec -inform DER -text -noout -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)

Y consiguió:

read EC key
Private-Key: (256 bit)
priv:
    00:92:e7:68:cb:72:0d:c1:69:24:27:d1:56:db:39:
    63:07:48:0d:15:07:b9:a4:95:84:50:25:74:b9:a0:
    92:2f:4b
pub: 
    04:19:54:97:37:b7:04:d1:78:9a:57:82:e3:43:0e:
    82:59:f9:04:71:32:60:81:05:48:54:d2:a5:d0:96:
    f9:68:6d:05:b0:30:d9:8b:a3:c6:0c:05:6e:20:4c:
    ef:61:c0:ac:5b:53:a9:a6:b9:a0:5a:ff:9d:a2:6c:
    a4:b6:5b:2e:84
ASN1 OID: secp256k1

Solución final:

$ /usr/local/Cellar/openssl/1.0.2n/bin/openssl ec -inform DER -text -noout -in <(cat <(echo -n "302e0201010420") <(echo -n "***") <(echo -n "a00706052b8104000a") | xxd -r -p) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d 'n' && echo

Reemplazar *** con un hexadecimal privado key.

Puedes corroborar nuestra función escribiendo un comentario y dejando una puntuación te damos las gracias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *