<p><strong>#0 what is the format?</strong> As you partly guessed, that is the &quot;PEM&quot; armoring of the DER encoding of the <strong><code>SubjectPublicKeyInfo</code> ASN.1 type from X.509</strong>, republished for Internet use as <a href="https://www.rfc-editor.org/rfc/rfc5280#section-4.1" rel="nofollow noreferrer">RFC5280 section 4.1 particularly 4.1.2.7</a>. To support multiple algorithms including new ones in the future, this structure is a <code>SEQUENCE</code> of an <code>AlgorithmIdentifier</code> which identifies the algorithm (using an <code>OBJECT IDENTIFIER</code> for the algorithm and various types for parameters depending on the algorithm), followed by a <code>BIT STRING</code> that contains the key value encoded in a format that varies depending on the algorithm. The AlgId and key format specific to ECDSA (and ECDH) are in <a href="https://www.rfc-editor.org/rfc/rfc3279#section-2.3.5" rel="nofollow noreferrer">RFC3279 section 2.3.5</a> although you can ignore the complicated parts about <code>ECParameters</code> because in practice everyone uses the simpler <code>namedCurve OBJECT IDENTIFIER</code> option, and the key format is just the SEC1/X9.62 point.</p>
<p>Here <code>301006072a8648ce3d020106052b8104000a</code> is the AlgId and decodes as</p>
<pre><code>    0:d=0  hl=2 l=  16 cons: SEQUENCE
    2:d=1  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   11:d=1  hl=2 l=   5 prim: OBJECT            :secp256k1
</code></pre>
<p>(As you've already figured out, &quot;PEM&quot; is just base64 of the DER, with line breaks at intervals, plus a <code>----BEGIN whatever-----</code> line at the top and an <code>-----END whatever-----</code> line at the bottom.)</p>
<p><strong>#1 encode without python?</strong> Aside from implementing (part of) DER yourself, which isn't that hard if you want, I see the <a href="https://github.com/Warner/python-ecdsa" rel="nofollow noreferrer">page you link to</a> talks a lot about OpenSSL compatibility: for programs in C or languages that can (easily) call C, which is many, OpenSSL can generate, read, write, and use for various operations ECC keys in this format (and the un-armored DER form). Java 7+ cryptography can do it, but the standard providers only in DER; for PEM you have to en/de-armor yourself or use <a href="http://www.BouncyCastle.org" rel="nofollow noreferrer">http://www.BouncyCastle.org</a> instead. I expect dot-NET can do it, but I don't use that and can't say definitely. I know I've seen perl modules for DER, but somehow I can never find things in CPAN even though that's its purpose. If you want a more specific answer, revise your question (or if it's sufficiently different, ask a new one).</p>
<p><strong>#2 private key?</strong> That page says it uses <code>-----BEGIN EC PRIVATE KEY-----</code> which could be either of two <strong>'legacy' formats in OpenSSL:</strong> unencrypted or encrypted. Since the examples don't show any password, I'll assume the former. If you look at a key file and see lines about <code>Proc-type</code> and <code>DEK-info</code> inserted <em>after</em> the <code>-----BEGIN</code> line but <em>before</em> the base64 data, it's legacy-encrypted and that's more complicated.</p>
<p>Without that, it's the private key structure defined by the SEC1 document at <a href="http://www.secg.org/" rel="nofollow noreferrer">http://www.secg.org/</a> in C.4, which contains an <code>OCTET STRING</code> for the private key (actually an integer, but not encoded as such), parameters defined in C.2 which if you examine carefully are essentially equivalent to those in RFC 3279, and once again a <code>BIT STRING</code> containing the public key (a point).</p>
<p>OpenSSL also supports the &quot;new&quot; (as of about 2000!) PKCS#8 format for private keys. Much like X.509 SPKI for public key, this is a generic wrapper that is basically an <code>AlgorithmIdentifier</code> for the algorithm plus an <code>OCTET STRING</code> containing the key value depending on the algorithm, except that PKCS#8 also has an option for encrypting at the PKCS#8 level (as opposed to the &quot;PEM&quot; level). I don't know if the python module handles these formats or not, and if not, whether you would want to use them and thereby be incompatible with the python module. If you <em>don't</em> want to use PKCS#8 and <em>do</em> want to use OpenSSL, be careful to use the specific EC routines not the generic ones.</p>

CC BY-SA 3.0
2015-12-07T08:57:00.427Z
Thanks! I figured it out eventually: `der_string = "\x30{totallen}\x02\x01\x01\x04\x20{privkey}\xa0\x07\x06\x05\x2b\x81\x04\x00\x0a\xa1\x44\x03\x42\x00\x04{x}{y}"` is for privkeys, and `der_string = "\x30{totallen}\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04\x00\x0a\x03\x42\x00\x04{pubkey}"` for pubkeys
Wizard Of Ozzie
CC BY-SA 3.0
2017-09-27T17:45:27.227Z
Thanks, this shed a lot of light on things! Just one question: Is the Bitcoin public key needed at all in the message signing process, when using DER encoded PEM-files to sign the message?
Kebman
CC BY-SA 3.0
2017-09-29T04:18:49.460Z
@Kebman: ECDSA signing needs only privatekey not public. But Bitcoin doesn't sign messages, it signs transactions which (always or nearly) involve addresses which are hashed from the publickeys. EC privatekey files created by OpenSSL always _include_ publickey, even though not required by SEC1 (and PKCS8), and in any case the publickey can always be recomputed from the privatekey.
dave_thompson_085
CC BY-SA 3.0
2015-12-06T10:50:19.727Z
2015-12-06T11:01:30.440Z
2021-10-07T07:05:27.390Z
dave_thompson_085
<p>I have been looking at <a href="https://coinapult.com/developer/api/ecc" rel="nofollow">Coinapult's API documentation</a> which details the use of PEM format in <em><a href="https://github.com/Warner/python-ecdsa" rel="nofollow">python-ecdsa</a></em>. Specifically, private keys and public keys need to be formatted using PEM.</p>

<p>Let's take Coinapult's specified public key:</p>

<pre><code>-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWp9wd4EuLhIZNaoUgZxQztSjrbqgTT0w
LBq8RwigNE6nOOXFEoGCjGfekugjrHWHUi8ms7bcfrowpaJKqMfZXg==
-----END PUBLIC KEY-----
</code></pre>

<p>Using python-ecdsa:</p>

<pre><code>vk = ecdsa.VerifyingKey.from_pem(ECC_COINAPULT_PUB)
s = vk.to_string()
s.encode('hex')   
&gt;&gt;&gt; "5a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e"
</code></pre>

<p>Or if it were a Bitcoin public key, that'd be <code>045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e</code></p>

<p>OK, that makes sense, but when we take the base64 encoded data between the leading and trailing <code>-----BEGIN-----</code>:</p>

<pre><code>base64_data = "".join(ECC_COINAPULT_PUB[27:-26 ].split('\n'))
s = base64.b64decode(base64_data)
result = s.encode("hex")
&gt;&gt;&gt; "3056301006072a8648ce3d020106052b8104000a034200045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e"  # WTF is this??
</code></pre>

<p>Note that the PEM format decodes to some sort of DER string, <code>3056301006072a8648ce3d020106052b8104000a034200045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e</code>, but what on earth is this DER string? I see <code>5a9f7077....a8c7d95e</code> is in that string, so what are the leading bytes meaning?</p>

<p><strong>Questions</strong>:
 1. How do I encode a pubkey to PEM format <em>without using python-ecdsa</em>?
 2. Is it the same procedure in #1 for <strong>private keys</strong> as it is public keys?</p>

<ecdsa>
PEM format for ECDSA
Wizard Of Ozzie
# PEM format for ECDSA

(Asked by: username_0 on 2015-12-06)

I have been looking at [Coinapult's API documentation](https://coinapult.com/developer/api/ecc) which details the use of PEM format in *[python-ecdsa](https://github.com/Warner/python-ecdsa)*. Specifically, private keys and public keys need to be formatted using PEM.

Let's take Coinapult's specified public key:

```
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWp9wd4EuLhIZNaoUgZxQztSjrbqgTT0w
LBq8RwigNE6nOOXFEoGCjGfekugjrHWHUi8ms7bcfrowpaJKqMfZXg==
-----END PUBLIC KEY-----

```

Using python-ecdsa:

```
vk = ecdsa.VerifyingKey.from_pem(ECC_COINAPULT_PUB)
s = vk.to_string()
s.encode('hex')   
>>> "5a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e"

```

Or if it were a Bitcoin public key, that'd be `045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e`

OK, that makes sense, but when we take the base64 encoded data between the leading and trailing `-----BEGIN-----`:

```
base64_data = "".join(ECC_COINAPULT_PUB[27:-26 ].split('\n'))
s = base64.b64decode(base64_data)
result = s.encode("hex")
>>> "3056301006072a8648ce3d020106052b8104000a034200045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e"  # WTF is this??

```

Note that the PEM format decodes to some sort of DER string, `3056301006072a8648ce3d020106052b8104000a034200045a9f7077812e2e121935aa14819c50ced4a3adbaa04d3d302c1abc4708a0344ea738e5c51281828c67de92e823ac7587522f26b3b6dc7eba30a5a24aa8c7d95e`, but what on earth is this DER string? I see `5a9f7077....a8c7d95e` is in that string, so what are the leading bytes meaning?

**Questions**:
1. How do I encode a pubkey to PEM format *without using python-ecdsa*?
2. Is it the same procedure in #1 for **private keys** as it is public keys?

**Tags:** ecdsa


---

## 1 answers

### Answer by username_1 on 2015-12-06. Score: 6 | Accepted answer

**#0 what is the format?** As you partly guessed, that is the "PEM" armoring of the DER encoding of the **`SubjectPublicKeyInfo` ASN.1 type from X.509**, republished for Internet use as [RFC5280 section 4.1 particularly 4.1.2.7](https://www.rfc-editor.org/rfc/rfc5280#section-4.1). To support multiple algorithms including new ones in the future, this structure is a `SEQUENCE` of an `AlgorithmIdentifier` which identifies the algorithm (using an `OBJECT IDENTIFIER` for the algorithm and various types for parameters depending on the algorithm), followed by a `BIT STRING` that contains the key value encoded in a format that varies depending on the algorithm. The AlgId and key format specific to ECDSA (and ECDH) are in [RFC3279 section 2.3.5](https://www.rfc-editor.org/rfc/rfc3279#section-2.3.5) although you can ignore the complicated parts about `ECParameters` because in practice everyone uses the simpler `namedCurve OBJECT IDENTIFIER` option, and the key format is just the SEC1/X9.62 point.

Here `301006072a8648ce3d020106052b8104000a` is the AlgId and decodes as

```
    0:d=0  hl=2 l=  16 cons: SEQUENCE
    2:d=1  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   11:d=1  hl=2 l=   5 prim: OBJECT            :secp256k1

```

(As you've already figured out, "PEM" is just base64 of the DER, with line breaks at intervals, plus a `----BEGIN whatever-----` line at the top and an `-----END whatever-----` line at the bottom.)

**#1 encode without python?** Aside from implementing (part of) DER yourself, which isn't that hard if you want, I see the [page you link to](https://github.com/Warner/python-ecdsa) talks a lot about OpenSSL compatibility: for programs in C or languages that can (easily) call C, which is many, OpenSSL can generate, read, write, and use for various operations ECC keys in this format (and the un-armored DER form). Java 7+ cryptography can do it, but the standard providers only in DER; for PEM you have to en/de-armor yourself or use <http://www.BouncyCastle.org> instead. I expect dot-NET can do it, but I don't use that and can't say definitely. I know I've seen perl modules for DER, but somehow I can never find things in CPAN even though that's its purpose. If you want a more specific answer, revise your question (or if it's sufficiently different, ask a new one).

**#2 private key?** That page says it uses `-----BEGIN EC PRIVATE KEY-----` which could be either of two **'legacy' formats in OpenSSL:** unencrypted or encrypted. Since the examples don't show any password, I'll assume the former. If you look at a key file and see lines about `Proc-type` and `DEK-info` inserted *after* the `-----BEGIN` line but *before* the base64 data, it's legacy-encrypted and that's more complicated.

Without that, it's the private key structure defined by the SEC1 document at <http://www.secg.org/> in C.4, which contains an `OCTET STRING` for the private key (actually an integer, but not encoded as such), parameters defined in C.2 which if you examine carefully are essentially equivalent to those in RFC 3279, and once again a `BIT STRING` containing the public key (a point).

OpenSSL also supports the "new" (as of about 2000!) PKCS#8 format for private keys. Much like X.509 SPKI for public key, this is a generic wrapper that is basically an `AlgorithmIdentifier` for the algorithm plus an `OCTET STRING` containing the key value depending on the algorithm, except that PKCS#8 also has an option for encrypting at the PKCS#8 level (as opposed to the "PEM" level). I don't know if the python module handles these formats or not, and if not, whether you would want to use them and thereby be incompatible with the python module. If you *don't* want to use PKCS#8 and *do* want to use OpenSSL, be careful to use the specific EC routines not the generic ones.

> **Comments:**
> **username_0**: Thanks! I figured it out eventually: `der_string = "\x30{totallen}\x02\x01\x01\x04\x20{privkey}\xa0\x07\x06\x05\x2b\x81\x04\x00\x0a\xa1\x44\x03\x42\x00\x04{x}{y}"` is for privkeys, and `der_string = "\x30{totallen}\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04\x00\x0a\x03\x42\x00\x04{pubkey}"` for pubkeys  
> **username_2**: Thanks, this shed a lot of light on things! Just one question: Is the Bitcoin public key needed at all in the message signing process, when using DER encoded PEM-files to sign the message?  
> **username_1**: @username_2: ECDSA signing needs only privatekey not public. But Bitcoin doesn't sign messages, it signs transactions which (always or nearly) involve addresses which are hashed from the publickeys. EC privatekey files created by OpenSSL always _include_ publickey, even though not required by SEC1 (and PKCS8), and in any case the publickey can always be recomputed from the privatekey.  

---

