<p>What you are looking at is just an implementation detail that you really don't need to worry about. It's just converting from an internal format (which may use different coordinate systems and bit lengths, especially for tests) to the standard output format. Within the library itself, the data in the signature may be easier and more efficient to handle when in other formats or coordinates systems. So the structures that represent that data store the data differently. However when outputting results, it must all be in a standard format, so that's what these conversions do: change from internal representation to a standard output format.</p>
<p>This is done for any of the signature serialization outputs that libsecp256k1 does. The compact format is just the two 256 bit values for R and s concatenated with each other. The first 32 bytes is R, the second is s. For standard compact signatures, that's it. For compact recoverable signatures (which is what you are looking at), there is an additional byte for the recovery id that is prepended to the compact signature.</p>

CC BY-SA 4.0
2018-12-25T08:25:03.130Z
In fact, I want to get a compact format of signature using the OpenSSL library. it has [ECDSA_do_sign](https://github.com/openssl/openssl/blob/4ace4ccda2934d2628c3d63d41e79abe041621a7/include/openssl/ec.h#L1185) function which returns a [structure](https://github.com/openssl/openssl/blob/4ace4ccda2934d2628c3d63d41e79abe041621a7/crypto/ec/ec_lcl.h#L625) consisting of two pointers to BIGNUM. Could you please tell me how to convert this internal representation from the OpenSSL into a standard one? I cannot find in the interface a function similar to the function from bitcoin-core.
Oroffe
CC BY-SA 4.0
2018-12-25T16:22:51.343Z
Of course you won't be able to find how to do that in Bitcoin Core because Bitcoin Core does not use OpenSSL for signature operations anymore. The ways that libsecp and openssl represent things internally are different from each other.  You can use [`ECDSA_SIG_get0`](https://www.openssl.org/docs/man1.1.1/man3/d2i_ECDSA_SIG.html) to get the `BIGNUM`s for r and s, then use [`BN_bn2binpad`](https://www.openssl.org/docs/manmaster/man3/BN_bn2bin.html) to get the `BIGNUM`s serialized as 32 byte big-endian integers. Then just concatenate the two byte strings to get the compact signature.
Ava Chow
CC BY-SA 4.0
2020-08-06T08:57:35.590Z
How to verify the compact signature? as `bitcoinjs-message` nodejs library throw error `Error: Invalid signature length`.
Shubham Chadokar
CC BY-SA 4.0
2022-06-16T21:45:24.893Z
@AndrewChow, i believe the recovery ID byte is prepended to the signature (r,s). It is the first byte, not the last.
Sachin Meier
CC BY-SA 4.0
2022-06-17T15:10:25.427Z
@SachinMeier Oh, indeed it is the first byte. I have updated the answer.
Ava Chow
CC BY-SA 4.0
2018-12-24T20:07:23.097Z
2022-06-17T15:10:11.457Z
2022-06-17T15:10:11.457Z
Ava Chow
<p>I would like to understand how to get Bitcoin ECDSA signature in a compact format, when it's exactly 65 bytes. </p>

<p>In the bitcoin-core repository, <a href="https://github.com/bitcoin-core/secp256k1/blob/1e6f1f5ad5e7f1e3ef79313ec02023902bf8175c/src/modules/recovery/main_impl.h#L12" rel="nofollow noreferrer">secp256k1_ecdsa_recoverable_signature_load</a> is responsible for this. As far as I understand, in it <strong><em>r</em></strong> and <strong><em>s</em></strong> are separately reduced to a 32 byte representation using <a href="https://github.com/bitcoin-core/secp256k1/blob/1e6f1f5ad5e7f1e3ef79313ec02023902bf8175c/src/scalar_low_impl.h#L47" rel="nofollow noreferrer">secp256k1_scalar_set_b32</a>, but I don't understand how it function works. What is a EXHAUSTIVE_TEST_ORDER? Why does the resulting representation of 32b scalar remain valid after it? I would be very grateful if someone could explain it to me.</p>

<bitcoin-core><signature><ecdsa><source-code>
Bitcoin ECDSA signature in the compact format
Oroffe
# Bitcoin ECDSA signature in the compact format

(Asked by: username_0 on 2018-12-24)

I would like to understand how to get Bitcoin ECDSA signature in a compact format, when it's exactly 65 bytes.

In the bitcoin-core repository, [secp256k1\_ecdsa\_recoverable\_signature\_load](https://github.com/bitcoin-core/secp256k1/blob/1e6f1f5ad5e7f1e3ef79313ec02023902bf8175c/src/modules/recovery/main_impl.h#L12) is responsible for this. As far as I understand, in it ***r*** and ***s*** are separately reduced to a 32 byte representation using [secp256k1\_scalar\_set\_b32](https://github.com/bitcoin-core/secp256k1/blob/1e6f1f5ad5e7f1e3ef79313ec02023902bf8175c/src/scalar_low_impl.h#L47), but I don't understand how it function works. What is a EXHAUSTIVE\_TEST\_ORDER? Why does the resulting representation of 32b scalar remain valid after it? I would be very grateful if someone could explain it to me.

**Tags:** bitcoin-core, signature, ecdsa, source-code


---

## 1 answers

### Answer by username_1 on 2018-12-24. Score: 2 | Accepted answer

What you are looking at is just an implementation detail that you really don't need to worry about. It's just converting from an internal format (which may use different coordinate systems and bit lengths, especially for tests) to the standard output format. Within the library itself, the data in the signature may be easier and more efficient to handle when in other formats or coordinates systems. So the structures that represent that data store the data differently. However when outputting results, it must all be in a standard format, so that's what these conversions do: change from internal representation to a standard output format.

This is done for any of the signature serialization outputs that libsecp256k1 does. The compact format is just the two 256 bit values for R and s concatenated with each other. The first 32 bytes is R, the second is s. For standard compact signatures, that's it. For compact recoverable signatures (which is what you are looking at), there is an additional byte for the recovery id that is prepended to the compact signature.

> **Comments:**
> **username_0**: In fact, I want to get a compact format of signature using the OpenSSL library. it has [ECDSA_do_sign](https://github.com/openssl/openssl/blob/4ace4ccda2934d2628c3d63d41e79abe041621a7/include/openssl/ec.h#L1185) function which returns a [structure](https://github.com/openssl/openssl/blob/4ace4ccda2934d2628c3d63d41e79abe041621a7/crypto/ec/ec_lcl.h#L625) consisting of two pointers to BIGNUM. Could you please tell me how to convert this internal representation from the OpenSSL into a standard one? I cannot find in the interface a function similar to the function from bitcoin-core.  
> **username_1**: Of course you won't be able to find how to do that in Bitcoin Core because Bitcoin Core does not use OpenSSL for signature operations anymore. The ways that libsecp and openssl represent things internally are different from each other.  You can use [`ECDSA_SIG_get0`](https://www.openssl.org/docs/man1.1.1/man3/d2i_ECDSA_SIG.html) to get the `BIGNUM`s for r and s, then use [`BN_bn2binpad`](https://www.openssl.org/docs/manmaster/man3/BN_bn2bin.html) to get the `BIGNUM`s serialized as 32 byte big-endian integers. Then just concatenate the two byte strings to get the compact signature.  
> **username_2**: How to verify the compact signature? as `bitcoinjs-message` nodejs library throw error `Error: Invalid signature length`.  
> **username_3**: @AndrewChow, i believe the recovery ID byte is prepended to the signature (r,s). It is the first byte, not the last.  
> **username_1**: @username_3 Oh, indeed it is the first byte. I have updated the answer.  

---

