<p>You have the wrong elliptic curve parameters in your PEM file. Bitcoin uses secp256k1, but you have (copied) the curve parameters for NIST P-256 (aka secp256r1).</p>
<p><code>algorithmIdentifierParameters</code> should be <code>b'\x06\x05\x2b\x81\x04\x00\x0a'</code> for secp256k1.</p>

CC BY-SA 4.0
2021-11-22T18:17:39.397Z
Exactly! Thanks! I just found it while reading this useful table giving the byte notation for OID : https://thalesdocs.com/gphsm/luna/7/docs/network/Content/sdk/using/ecc_curve_cross-reference.htm
StashOfCode
CC BY-SA 4.0
2021-11-22T18:24:49.437Z
If you know a better resource for converting OID from strings to bytes, it may be useful.
StashOfCode
CC BY-SA 4.0
2021-11-28T11:31:50.643Z
See [MSDN](https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN) for this conversion...
StashOfCode
CC BY-SA 4.0
2021-11-22T17:51:56.417Z
2021-11-22T17:51:56.417Z
Ava Chow
<p>I'm trying to check the public key which lies in the ScriptPubKey of output #0 of transaction #1 bloc #9 with openssl. I'm using Python to create a DER file, and openssl to check it.</p>
<p>ScriptPubKey value is:</p>
<pre><code>0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3
</code></pre>
<p>My Python code to create the DER file is:</p>
<pre><code>scriptPubKey = block9.transactions[0].outputs[0].scriptPubKey[1:-1]
x = scriptPubKey[1:1+32]
y = scriptPubKey[1+32:]
publicKey = bytearray ([0x03, len (scriptPubKey) + 1, 0x00]) + scriptPubKey
algorithmIdentifierId = b'\x06\x07\x2a\x86\x48\xce\x3d\x02\x01'
algorithmIdentifierParameters = b'\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07'
algorithmIdentifier = algorithmIdentifierId + algorithmIdentifierParameters
publicKey = bytearray ([0x30, len (algorithmIdentifier)]) + algorithmIdentifier + publicKey
publicKey = bytearray ([0x30, len (publicKey)]) + publicKey
file = open (f'public.der', 'wb')
file.write (publicKey)
file.close ()
</code></pre>
<p>After running this code, I get a <code>public.der</code> which I check using openssl. First; I check the ASN.1 syntax, which is correct:</p>
<pre><code>$ openssl asn1parse -inform der -in public.der 
    0:d=0  hl=2 l=  89 cons: SEQUENCE          
    2:d=1  hl=2 l=  19 cons: SEQUENCE          
    4:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   13:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   23:d=1  hl=2 l=  66 prim: BIT STRING
</code></pre>
<p>Then I check the key itself, and this doesn't work:</p>
<pre><code>$ openssl ec -pubin -inform der -in public.der -text -noout
read EC key
unable to load Key
140542543959360:error:1012606B:elliptic curve routines:EC_POINT_set_affine_coordinates:point is not on curve:../crypto/ec/ec_lib.c:812:
140542543959360:error:10098010:elliptic curve routines:o2i_ECPublicKey:EC lib:../crypto/ec/ec_asn1.c:1158:
140542543959360:error:100D708E:elliptic curve routines:eckey_pub_decode:decode error:../crypto/ec/ec_ameth.c:157:
140542543959360:error:0B09407D:x509 certificate routines:x509_pubkey_decode:public key decode error:../crypto/x509/x_pubkey.c:125:
</code></pre>
<p>This code relies on this <a href="https://stackoverflow.com/questions/56772982/build-pem-file-by-having-ec-public-key-coordinates">post</a>. It works well if I use the x and y coordinates which the author of the post gives as an example:</p>
<pre><code>x = b'\x81\x01\xEC\xE4\x74\x64\xA6\xEA\xD7\x0C\xF6\x9A\x6E\x2B\xD3\xD8\x86\x91\xA3\x26\x2D\x22\xCB\xA4\xF7\x63\x5E\xAF\xF2\x66\x80\xA8'
y = b'\xD8\xA1\x2B\xA6\x1D\x59\x92\x35\xF6\x7D\x9C\xB4\xD5\x8F\x17\x83\xD3\xCA\x43\xE7\x8F\x0A\x5A\xBA\xA6\x24\x07\x99\x36\xC0\xC3\xA9'
scriptPubKey = b'\x04' + x + y
publicKey = bytearray ([0x03, len (scriptPubKey) + 1, 0x00]) + scriptPubKey
algorithmIdentifierId = b'\x06\x07\x2a\x86\x48\xce\x3d\x02\x01'
algorithmIdentifierParameters = b'\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07'
algorithmIdentifier = algorithmIdentifierId + algorithmIdentifierParameters
publicKey = bytearray ([0x30, len (algorithmIdentifier)]) + algorithmIdentifier + publicKey
publicKey = bytearray ([0x30, len (publicKey)]) + publicKey
file = open (f'public.der', 'wb')
file.write (publicKey)
file.close ()
</code></pre>
<p>No problemo for openssl here:</p>
<pre><code>$ openssl ec -pubin -inform der -in public.der -text -noout
read EC key
Public-Key: (256 bit)
pub:
    04:81:01:ec:e4:74:64:a6:ea:d7:0c:f6:9a:6e:2b:
    d3:d8:86:91:a3:26:2d:22:cb:a4:f7:63:5e:af:f2:
    66:80:a8:d8:a1:2b:a6:1d:59:92:35:f6:7d:9c:b4:
    d5:8f:17:83:d3:ca:43:e7:8f:0a:5a:ba:a6:24:07:
    99:36:c0:c3:a9
ASN1 OID: prime256v1
NIST CURVE: P-256
</code></pre>
<p>May somebody tell me what I missed? I tried to inverse the byte order of x and y, and/or to exchange x and y, but I could not make it work with the x and y values from ScriptPubKey...</p>
<p>According to pages 73 to 74 of <a href="https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/" rel="nofollow noreferrer">this book</a>, x and y are supposed to be given in this order, and in big endian...</p>

<blockchain><public-key><openssl>
Block 9 Transaction 1 Output 0 ScriptPubKey openssl validation fails
StashOfCode
# Block 9 Transaction 1 Output 0 ScriptPubKey openssl validation fails

(Asked by: username_0 on 2021-11-22)

I'm trying to check the public key which lies in the ScriptPubKey of output #0 of transaction #1 bloc #9 with openssl. I'm using Python to create a DER file, and openssl to check it.

ScriptPubKey value is:

```
0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3

```

My Python code to create the DER file is:

```
scriptPubKey = block9.transactions[0].outputs[0].scriptPubKey[1:-1]
x = scriptPubKey[1:1+32]
y = scriptPubKey[1+32:]
publicKey = bytearray ([0x03, len (scriptPubKey) + 1, 0x00]) + scriptPubKey
algorithmIdentifierId = b'\x06\x07\x2a\x86\x48\xce\x3d\x02\x01'
algorithmIdentifierParameters = b'\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07'
algorithmIdentifier = algorithmIdentifierId + algorithmIdentifierParameters
publicKey = bytearray ([0x30, len (algorithmIdentifier)]) + algorithmIdentifier + publicKey
publicKey = bytearray ([0x30, len (publicKey)]) + publicKey
file = open (f'public.der', 'wb')
file.write (publicKey)
file.close ()

```

After running this code, I get a `public.der` which I check using openssl. First; I check the ASN.1 syntax, which is correct:

```
$ openssl asn1parse -inform der -in public.der 
    0:d=0  hl=2 l=  89 cons: SEQUENCE          
    2:d=1  hl=2 l=  19 cons: SEQUENCE          
    4:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
   13:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
   23:d=1  hl=2 l=  66 prim: BIT STRING

```

Then I check the key itself, and this doesn't work:

```
$ openssl ec -pubin -inform der -in public.der -text -noout
read EC key
unable to load Key
140542543959360:error:1012606B:elliptic curve routines:EC_POINT_set_affine_coordinates:point is not on curve:../crypto/ec/ec_lib.c:812:
140542543959360:error:10098010:elliptic curve routines:o2i_ECPublicKey:EC lib:../crypto/ec/ec_asn1.c:1158:
140542543959360:error:100D708E:elliptic curve routines:eckey_pub_decode:decode error:../crypto/ec/ec_ameth.c:157:
140542543959360:error:0B09407D:x509 certificate routines:x509_pubkey_decode:public key decode error:../crypto/x509/x_pubkey.c:125:

```

This code relies on this [post](https://stackoverflow.com/questions/56772982/build-pem-file-by-having-ec-public-key-coordinates). It works well if I use the x and y coordinates which the author of the post gives as an example:

```
x = b'\x81\x01\xEC\xE4\x74\x64\xA6\xEA\xD7\x0C\xF6\x9A\x6E\x2B\xD3\xD8\x86\x91\xA3\x26\x2D\x22\xCB\xA4\xF7\x63\x5E\xAF\xF2\x66\x80\xA8'
y = b'\xD8\xA1\x2B\xA6\x1D\x59\x92\x35\xF6\x7D\x9C\xB4\xD5\x8F\x17\x83\xD3\xCA\x43\xE7\x8F\x0A\x5A\xBA\xA6\x24\x07\x99\x36\xC0\xC3\xA9'
scriptPubKey = b'\x04' + x + y
publicKey = bytearray ([0x03, len (scriptPubKey) + 1, 0x00]) + scriptPubKey
algorithmIdentifierId = b'\x06\x07\x2a\x86\x48\xce\x3d\x02\x01'
algorithmIdentifierParameters = b'\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07'
algorithmIdentifier = algorithmIdentifierId + algorithmIdentifierParameters
publicKey = bytearray ([0x30, len (algorithmIdentifier)]) + algorithmIdentifier + publicKey
publicKey = bytearray ([0x30, len (publicKey)]) + publicKey
file = open (f'public.der', 'wb')
file.write (publicKey)
file.close ()

```

No problemo for openssl here:

```
$ openssl ec -pubin -inform der -in public.der -text -noout
read EC key
Public-Key: (256 bit)
pub:
    04:81:01:ec:e4:74:64:a6:ea:d7:0c:f6:9a:6e:2b:
    d3:d8:86:91:a3:26:2d:22:cb:a4:f7:63:5e:af:f2:
    66:80:a8:d8:a1:2b:a6:1d:59:92:35:f6:7d:9c:b4:
    d5:8f:17:83:d3:ca:43:e7:8f:0a:5a:ba:a6:24:07:
    99:36:c0:c3:a9
ASN1 OID: prime256v1
NIST CURVE: P-256

```

May somebody tell me what I missed? I tried to inverse the byte order of x and y, and/or to exchange x and y, but I could not make it work with the x and y values from ScriptPubKey...

According to pages 73 to 74 of [this book](https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/), x and y are supposed to be given in this order, and in big endian...

**Tags:** blockchain, public-key, openssl


---

## 1 answers

### Answer by username_1 on 2021-11-22. Score: 3 | Accepted answer

You have the wrong elliptic curve parameters in your PEM file. Bitcoin uses secp256k1, but you have (copied) the curve parameters for NIST P-256 (aka secp256r1).

`algorithmIdentifierParameters` should be `b'\x06\x05\x2b\x81\x04\x00\x0a'` for secp256k1.

> **Comments:**
> **username_0**: Exactly! Thanks! I just found it while reading this useful table giving the byte notation for OID : https://thalesdocs.com/gphsm/luna/7/docs/network/Content/sdk/using/ecc_curve_cross-reference.htm  
> **username_0**: If you know a better resource for converting OID from strings to bytes, it may be useful.  
> **username_0**: See [MSDN](https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN) for this conversion...  

---

