5

I created a random integer array of 32 bytes to use as my private key for secp256k1 curve.

const uint8_t secret[] = {0xb2,0x9a,0xc6,0xbd,0xc7,0x3d,0xc4,0xe1,
                          0x85,0xa7,0x3c,0x96,0xf8,0x1c,0x58,0x43,
                          0xe2,0xbf,0x2d,0x68,0xe5,0x6f,0xf6,0xae,
                          0x4f,0xe7,0x51,0xcd,0x9d,0x47,0x00,0xfa}

I want to turn this hex array into a ASN.1 DER encoded key so I can further use it with my hardware which expects the keys to be ASN.1 DER encoded.

Can you point me in the right direction on how to achieve this ?

Edit , I found an encoded key-pair, maybe I can pick up from this. Does the array below contain both public and private key parts ?

 keyPairData[] = { 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13,
    0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
    0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
    0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02,
    0x01, 0x01, 0x04, 0x20, 0x78, 0xE5, 0x20, 0x6A,
    0x08, 0xED, 0xD2, 0x52, 0x36, 0x33, 0x8A, 0x24,
    0x84, 0xE4, 0x2F, 0x1F, 0x7D, 0x1F, 0x6D, 0x94,
    0x37, 0xA9, 0x95, 0x86, 0xDA, 0xFC, 0xD2, 0x23,
    0x6F, 0xA2, 0x87, 0x35, 0xA1, 0x44, 0x03, 0x42,
    0x00, 0x04, 0xED, 0xA7, 0xE9, 0x0B, 0xF9, 0x20,
    0xCF, 0xFB, 0x9D, 0xF6, 0xDB, 0xCE, 0xF7, 0x20,
    0xE1, 0x23, 0x8B, 0x3C, 0xEE, 0x84, 0x86, 0xD2,
    0x50, 0xE4, 0xDF, 0x30, 0x11, 0x50, 0x1A, 0x15,
    0x08, 0xA6, 0x2E, 0xD7, 0x49, 0x52, 0x78, 0x63,
    0x6E, 0x61, 0xE8, 0x5F, 0xED, 0xB0, 0x6D, 0x87,
    0x92, 0x0A, 0x04, 0x19, 0x14, 0xFE, 0x76, 0x63,
    0x55, 0xDF, 0xBD, 0x68, 0x61, 0x59, 0x31, 0x8E,
    0x68, 0x7C };
Dogus Ural
  • 153
  • 1
  • 6

1 Answers1

8

ASN.1 is a way of defining structures for data, and DER is a binary encoding of those structures. But they aren't describing any structures by themselves. Saying that something needs to be ASN.1 / DER encoded is like saying that the key needs to be represented in XML without specifying the tags or tree structure.


What you are required to generate is a PKCS#8 (inner) encoded private key. The SEC1 document link that I provided before defines the inner SEQUENCE in there. The PKCS#8 inner structure is used to identify the type of key. Most of what is in SEC1 was copied to X9.62. And yes, it clearly contains the optional public key. If you look for ways to encode your private key to PKCS#8 you'll find a lot more information. It's for instance the default encoding for OpenSSL, but most other libraries will use the same.

I can generate the same in Java (ECPrivateKey.getEncoded() for curve "secp256k1") but without the optional - and in my opinion spurious - public point included. You can see the structure you've provided in the Lapo online ASN.1 decoder. Yes, it clearly includes the public key as optional BIT STRING at the end (appending it yourself means adjusting the length encodings of the SEQUENCE's though).

If your structure lacks a public key, I would first just try and import it; it's pretty easy to compute the public key from the private key and parameters: just point multiplication with the base point G. Likely the device is capable of doing that.


You will generally want to create a "named" curve where the domain parameters are given by an OID (as in the example you've been given). It is more likely that explicit domain parameters are rejected by devices that only operate on a limited set of curves.

I've however encountered HSM's that require you to provide the unnamed parameters. In that case you may need to construct your private key using the explicit parameters and then encode...

Maarten Bodewes
  • 96,351
  • 14
  • 169
  • 323