<p>If you're looking for a quick utility to <a href="https://bitauth.github.io/bitcoin-ts/interfaces/secp256k1.html#compresspublickey" rel="nofollow noreferrer">compress</a>/<a href="https://bitauth.github.io/bitcoin-ts/interfaces/secp256k1.html#uncompresspublickey" rel="nofollow noreferrer">uncompress</a> Secp256k1 public keys, try <a href="https://github.com/bitauth/bitcoin-ts" rel="nofollow noreferrer">bitcoin-ts</a>:</p>



<pre><code>const {instantiateSecp256k1, hexToBin, binToHex} = require("bitcoin-ts")
const secp256k1 = await instantiateSecp256k1();

const compressed = hexToBin('02ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe');

const uncompressed = secp256k1.uncompressPublicKey(compressed);
console.log(binToHex(uncompressed));
// =&gt; 04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28

const recompressed = secp256k1.compressPublicKey(uncompressed);
console.log(binToHex(recompressed));
// =&gt; 02ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe
</code></pre>



<p><a href="https://repl.it/@bitjson/Decompress-Secp256k1-Public-Keys-with-bitcoin-ts" rel="nofollow noreferrer">Run in the browser →</a></p>

CC BY-SA 4.0
2020-03-24T00:01:08.563Z
2020-04-09T22:18:57.427Z
2020-04-09T22:18:57.427Z
Jason Dreyzehner
<p>Points are decompressed by solving for <code>y</code> in the equation used for secp256k1's elliptic curve where <code>x</code> is the last 32 bytes of your public key. The equation is <code>y^2 = x^3 + 7</code>. You will get 2 possible <code>y</code> values, one even and one odd. The correct one is indicated by the prefix byte of your public key which indicates whether <code>y</code> is even or odd.</p>

<p>Note that all operations must be modulo <code>p</code> which is defined by secp256k1's spec as being <code>0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F</code>.</p>

<p>This python script will decompress the two public keys that you have posted:</p>

<pre><code>#! /usr/bin/env python3

import binascii

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F

def decompress_pubkey(pk):
    x = int.from_bytes(pk[1:33], byteorder='big')
    y_sq = (pow(x, 3, p) + 7) % p
    y = pow(y_sq, (p + 1) // 4, p)
    if y % 2 != pk[0] % 2:
        y = p - y
    y = y.to_bytes(32, byteorder='big')
    return b'\x04' + pk[1:33] + y

print(binascii.hexlify(decompress_pubkey(binascii.unhexlify('0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898'))).decode())
print(binascii.hexlify(decompress_pubkey(binascii.unhexlify('02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27'))).decode())

</code></pre>

<p>The uncompressed public keys are:</p>

<pre><code>0429b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898d6881e81d2e0163348ff07b3a9a3968401572aa79c79e7edb522f41addc8e6ce
04f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f274d335b71c85e064f80191e1f7e2437afa676a3e2a5a5fafcf0d27940cd33e4b4
</code></pre>

<hr>

<p>Pubkey decompression is completely different and unrelated to address generation. Addresses are generated by taking a public key as is (either compressed or uncompressed) hashing it, and then encoding it. The compression matters because the resulting serialized public will produce one hash (and thus one address) when it is compressed, and a different hash (and thus different address) when uncompressed.</p>

<p>Addresses are encoded by hashing the serialized public key with SHA256 and then with RIPEMD160. The resulting hash is encoded using <a href="https://en.bitcoin.it/wiki/Base58Check_encoding" rel="noreferrer">Base58 Check encoding</a>.</p>

<p>In the transaction you provided, the three public keys:</p>

<pre><code>04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28
0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898
02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27
</code></pre>

<p>have the following hashes respectively:</p>

<pre><code>946cb2e08075bcbaf157e47bcb67eb2b2339d242
55af2ea3c45819c6c5ae710d29fcaaced5b00cc7
8b38a8d40e08362046dee55c1c94e7991d7dec75
</code></pre>

<p>Encoding those as version 0 addresses with Base 58 Check encoding results in the addresses you are expecting:</p>

<pre><code>1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P
18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot
1Dh8oSChJWZQx5sr7ePsBNtw7uKMsNnYNC
</code></pre>

<p>The code I used for this is:</p>

<pre><code>#! /usr/bin/env python3

import binascii
import hashlib

b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def sha256(s):
    return hashlib.new('sha256', s).digest()

def ripemd160(s):
    return hashlib.new('ripemd160', s).digest()

def hash256(s):
    return sha256(sha256(s))

def hash160(s):
    return ripemd160(sha256(s))

def encode(b):
    # Convert big-endian bytes to integer
    n = int('0x0' + binascii.hexlify(b).decode('utf8'), 16)

    # Divide that integer into bas58
    res = []
    while n &gt; 0:
        n, r = divmod (n, 58)
        res.append(b58_digits[r])
    res = ''.join(res[::-1])

    # Encode leading zeros as base58 zeros
    import sys
    czero = b'\x00'
    if sys.version &gt; '3':
        # In Python3 indexing a bytes returns numbers, not characters.
        czero = 0
    pad = 0
    for c in b:
        if c == czero: pad += 1
        else: break
    return b58_digits[0] * pad + res

def to_address(b, version):
    data = version + b
    checksum = hash256(data)[0:4]
    data += checksum
    return encode(data)

pk1 = binascii.unhexlify("0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898")
pk2 = binascii.unhexlify("02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27")
pk3 = binascii.unhexlify("04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28")

h1 = hash160(pk1)
h2 = hash160(pk2)
h3 = hash160(pk3)

print(to_address(h3, b'\x00'))
print(to_address(h1, b'\x00'))
print(to_address(h2, b'\x00'))
</code></pre>

<p>(Base58 encoding function from <a href="https://github.com/bitcoin-core/HWI/blob/master/hwilib/base58.py" rel="noreferrer">https://github.com/bitcoin-core/HWI/blob/master/hwilib/base58.py</a>)</p>

<p>As you can see, this does not do any point compression or decompression. Rather it takes the public key as it is and encodes it.</p>

CC BY-SA 4.0
2019-04-23T18:04:02.430Z
@user2284570 however care must be taken not to interchangeably use the compressed and uncompressed public keys. Addresses generated from uncompressed and compressed public keys are different.
Ugam Kamat
CC BY-SA 4.0
2019-04-23T18:24:42.193Z
@Andrew Chow This is not exactly right, you're implementing "03 means nonsquare Y, 02 means square Y". It should odd/even.
Pieter Wuille
CC BY-SA 4.0
2019-04-23T18:27:41.253Z
@AndrewChow There is a slight error in the code. You need to check the sign of the y-coordinate generated from the modular sqrt and then check if its sign is equal to the one attached to the compressed public key. That is because you do not know whether the y you have generated is odd or even. You are doing it the other way around.
Ugam Kamat
CC BY-SA 4.0
2019-04-23T18:37:38.900Z
It should be more like: `y = y if y%2 == pk[0]%2 else p-y`
Ugam Kamat
CC BY-SA 4.0
2019-04-23T18:39:37.073Z
Whoops. I think it's correct now.
Ava Chow
CC BY-SA 4.0
2019-04-23T18:40:44.293Z
Yes. It was easy to overlook. You got both those uncompressed public keys correct by accident.
Ugam Kamat
CC BY-SA 4.0
2019-04-23T18:42:34.963Z
@UgamKamat but then, how does Bitcoin core do to get addresses from compressed PubKey in bare Multisig transactions ?
user2284570
CC BY-SA 4.0
2019-04-23T18:48:40.237Z
@user2284570 Bitcoin Core by default uses compressed public keys. So the bare multi-sig addresses would be generated by base58encode of hash160(M<publickey1>...<PubkeyN>N). Note that if the public keys are uncompressed, the multi-sig address generated will be completely different than what is generated with compressed public keys.
Ugam Kamat
CC BY-SA 4.0
2019-04-23T19:05:14.390Z
@AndrewChow sorry : I used the wrong Public key in my question. May you update your answer ? Not only that it doesn’t work with the new Public keys since `0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898
` is `18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot` which isn’t the result given by `0429B3E0919ADC41A316AAD4F41444D9BF3A9B639550F2AA735676FFFF25BA3898D6881E81D2E0163348FF07B3A9A3968401572AA79C79E7EDB522F41ADDC8E6CE` which gives `18EA4v85M4qiUHrs3Vs9awRm86HsStCGzi`. **So ʏᴏᴜʀ ᴀɴꜱᴡᴇʀ ɪꜱ ᴡʀᴏɴɢ !**
user2284570
CC BY-SA 4.0
2019-04-23T19:10:44.603Z
@UgamKamat I mean the 3 addresses you get with in vout 4 with `getrawtransaction 5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f 1 "00000000000000001e76250b3725547b5887329cfe3a8bb930a70e66747384d3"` By testing this answer, on the compressed public keys of that transaction you can see that **it’s wrong**. Do you have any ideas why ?
user2284570
CC BY-SA 4.0
2019-04-23T19:36:20.263Z
@user2284570 As i mentioned in my first comment, addresses generated from compressed public key and uncompressed public key are different.
Ugam Kamat
CC BY-SA 4.0
2019-04-23T20:01:07.090Z
The answer is not wrong. You are misunderstanding how addresses are derived from public keys. The uncompressed and compressed versions of the same public key will produce two different addresses. Public keys are not compressed or uncompressed before address conversion, they are serialized as is (either compressed or not) and hashed and encoded.
Ava Chow
CC BY-SA 4.0
2019-04-23T20:53:52.183Z
@UgamKamat no, for the case I’m referring to [only the first public key in uncompressed](https://www.blockchain.com/fr/btc/tx/5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f?show_adv=true). There’s really uncompressed public keys on the ledger. Please see my last edit.
user2284570
CC BY-SA 4.0
2019-04-23T21:04:26.023Z
@user2284570 I have already shown you how Bitcoin Core is getting addresses for the last two public keys which are compressed. It's the same process for the uncompressed address as well. I've updated my answer to generate its address as well.
Ava Chow
CC BY-SA 4.0
2019-04-23T21:08:05.580Z
@user2284570 Can you explain what you think Bitcoin Core is doing? That way we can explain what it is that you have mistaken.
Ava Chow
CC BY-SA 4.0
2019-04-23T21:22:37.980Z
@AndrewChow ok. I simply thought uncompressing public key was required for address generation.
user2284570
CC BY-SA 4.0
2019-04-24T06:14:52.223Z
For anyone interested in the math: the magical line `y = pow(y_sq, (p + 1) // 4, p)` is due to `p` in the curve bitcoin uses being like `p % 4 == 3` otherwise you have to use an algorithm such as [Tonelli–Shanks](https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) to find `y`.
Coding Enthusiast
CC BY-SA 4.0
2024-01-26T09:56:51.387Z
I don't think the second mod operation is needed for y_sq since pow(x, 3, p) + 7 will be always less than p.
Azzuro
CC BY-SA 4.0
2019-04-23T18:00:13.077Z
2019-04-23T21:06:47.657Z
2019-04-23T21:06:47.657Z
Ava Chow
<p>Simple question but I couldn’t find the answer anywhere.</p>

<p>What’s the 65 bytes version of those public keys ?</p>

<pre><code>0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898
02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27
</code></pre>

<p>which for reference yields according to Bitcoin core <code>getrawtransaction 5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f 1 "00000000000000001e76250b3725547b5887329cfe3a8bb930a70e66747384d3"</code> :</p>

<pre><code>18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot
1Dh8oSChJWZQx5sr7ePsBNtw7uKMsNnYNC
</code></pre>

<p>with transaction output being :</p>

<pre><code>1 04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28 0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898 02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27 3 OP_CHECKMULTISIG
</code></pre>

<p>So that while the first Public key is uncompressed, <a href="https://www.blockchain.com/fr/btc/tx/5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f?show_adv=true" rel="nofollow noreferrer">they are no version uncompressed version of the 2 others keys on the Blockchain</a> which means Bitcoin core is recovering the 2 addresses above from the compressed public keys (the first one being not included because the Public key is uncompressed).</p>

<public-key>
How to uncompress a public key?
user2284570
# How to uncompress a public key?

(Asked by: username_0 on 2019-04-23)

Simple question but I couldn’t find the answer anywhere.

What’s the 65 bytes version of those public keys ?

```
0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898
02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27

```

which for reference yields according to Bitcoin core `getrawtransaction 5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f 1 "00000000000000001e76250b3725547b5887329cfe3a8bb930a70e66747384d3"` :

```
18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot
1Dh8oSChJWZQx5sr7ePsBNtw7uKMsNnYNC

```

with transaction output being :

```
1 04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28 0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898 02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27 3 OP_CHECKMULTISIG

```

So that while the first Public key is uncompressed, [they are no version uncompressed version of the 2 others keys on the Blockchain](https://www.blockchain.com/fr/btc/tx/5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f?show_adv=true) which means Bitcoin core is recovering the 2 addresses above from the compressed public keys (the first one being not included because the Public key is uncompressed).

**Tags:** public-key


---

## 2 answers

### Answer by username_2 on 2019-04-23. Score: 11 | Accepted answer

Points are decompressed by solving for `y` in the equation used for secp256k1's elliptic curve where `x` is the last 32 bytes of your public key. The equation is `y^2 = x^3 + 7`. You will get 2 possible `y` values, one even and one odd. The correct one is indicated by the prefix byte of your public key which indicates whether `y` is even or odd.

Note that all operations must be modulo `p` which is defined by secp256k1's spec as being `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F`.

This python script will decompress the two public keys that you have posted:

```
#! /usr/bin/env python3

import binascii

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F

def decompress_pubkey(pk):
    x = int.from_bytes(pk[1:33], byteorder='big')
    y_sq = (pow(x, 3, p) + 7) % p
    y = pow(y_sq, (p + 1) // 4, p)
    if y % 2 != pk[0] % 2:
        y = p - y
    y = y.to_bytes(32, byteorder='big')
    return b'\x04' + pk[1:33] + y

print(binascii.hexlify(decompress_pubkey(binascii.unhexlify('0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898'))).decode())
print(binascii.hexlify(decompress_pubkey(binascii.unhexlify('02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27'))).decode())

```

The uncompressed public keys are:

```
0429b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898d6881e81d2e0163348ff07b3a9a3968401572aa79c79e7edb522f41addc8e6ce
04f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f274d335b71c85e064f80191e1f7e2437afa676a3e2a5a5fafcf0d27940cd33e4b4

```

---

Pubkey decompression is completely different and unrelated to address generation. Addresses are generated by taking a public key as is (either compressed or uncompressed) hashing it, and then encoding it. The compression matters because the resulting serialized public will produce one hash (and thus one address) when it is compressed, and a different hash (and thus different address) when uncompressed.

Addresses are encoded by hashing the serialized public key with SHA256 and then with RIPEMD160. The resulting hash is encoded using [Base58 Check encoding](https://en.bitcoin.it/wiki/Base58Check_encoding).

In the transaction you provided, the three public keys:

```
04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28
0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898
02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27

```

have the following hashes respectively:

```
946cb2e08075bcbaf157e47bcb67eb2b2339d242
55af2ea3c45819c6c5ae710d29fcaaced5b00cc7
8b38a8d40e08362046dee55c1c94e7991d7dec75

```

Encoding those as version 0 addresses with Base 58 Check encoding results in the addresses you are expecting:

```
1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P
18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot
1Dh8oSChJWZQx5sr7ePsBNtw7uKMsNnYNC

```

The code I used for this is:

```
#! /usr/bin/env python3

import binascii
import hashlib

b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def sha256(s):
    return hashlib.new('sha256', s).digest()

def ripemd160(s):
    return hashlib.new('ripemd160', s).digest()

def hash256(s):
    return sha256(sha256(s))

def hash160(s):
    return ripemd160(sha256(s))

def encode(b):
    # Convert big-endian bytes to integer
    n = int('0x0' + binascii.hexlify(b).decode('utf8'), 16)

    # Divide that integer into bas58
    res = []
    while n > 0:
        n, r = divmod (n, 58)
        res.append(b58_digits[r])
    res = ''.join(res[::-1])

    # Encode leading zeros as base58 zeros
    import sys
    czero = b'\x00'
    if sys.version > '3':
        # In Python3 indexing a bytes returns numbers, not characters.
        czero = 0
    pad = 0
    for c in b:
        if c == czero: pad += 1
        else: break
    return b58_digits[0] * pad + res

def to_address(b, version):
    data = version + b
    checksum = hash256(data)[0:4]
    data += checksum
    return encode(data)

pk1 = binascii.unhexlify("0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898")
pk2 = binascii.unhexlify("02f15446771c5c585dd25d8d62df5195b77799aa8eac2f2196c54b73ca05f72f27")
pk3 = binascii.unhexlify("04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28")

h1 = hash160(pk1)
h2 = hash160(pk2)
h3 = hash160(pk3)

print(to_address(h3, b'\x00'))
print(to_address(h1, b'\x00'))
print(to_address(h2, b'\x00'))

```

(Base58 encoding function from <https://github.com/bitcoin-core/HWI/blob/master/hwilib/base58.py>)

As you can see, this does not do any point compression or decompression. Rather it takes the public key as it is and encodes it.

> **Comments:**
> **username_3**: @username_0 however care must be taken not to interchangeably use the compressed and uncompressed public keys. Addresses generated from uncompressed and compressed public keys are different.  
> **username_4**: @Andrew username_2 This is not exactly right, you're implementing "03 means nonsquare Y, 02 means square Y". It should odd/even.  
> **username_3**: @AndrewChow There is a slight error in the code. You need to check the sign of the y-coordinate generated from the modular sqrt and then check if its sign is equal to the one attached to the compressed public key. That is because you do not know whether the y you have generated is odd or even. You are doing it the other way around.  
> **username_3**: It should be more like: `y = y if y%2 == pk[0]%2 else p-y`  
> **username_2**: Whoops. I think it's correct now.  
> **username_3**: Yes. It was easy to overlook. You got both those uncompressed public keys correct by accident.  
> **username_0**: @username_3 but then, how does Bitcoin core do to get addresses from compressed PubKey in bare Multisig transactions ?  
> **username_3**: @username_0 Bitcoin Core by default uses compressed public keys. So the bare multi-sig addresses would be generated by base58encode of hash160(M<publickey1>...<PubkeyN>N). Note that if the public keys are uncompressed, the multi-sig address generated will be completely different than what is generated with compressed public keys.  
> **username_0**: @AndrewChow sorry : I used the wrong Public key in my question. May you update your answer ? Not only that it doesn’t work with the new Public keys since `0229b3e0919adc41a316aad4f41444d9bf3a9b639550f2aa735676ffff25ba3898 ` is `18p4JBHP3EAKCc4jqN8XzuEJtvq8G9NAot` which isn’t the result given by `0429B3E0919ADC41A316AAD4F41444D9BF3A9B639550F2AA735676FFFF25BA3898D6881E81D2E0163348FF07B3A9A3968401572AA79C79E7EDB522F41ADDC8E6CE` which gives `18EA4v85M4qiUHrs3Vs9awRm86HsStCGzi`. **So ʏᴏᴜʀ ᴀɴꜱᴡᴇʀ ɪꜱ ᴡʀᴏɴɢ !**  
> **username_0**: @username_3 I mean the 3 addresses you get with in vout 4 with `getrawtransaction 5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f 1 "00000000000000001e76250b3725547b5887329cfe3a8bb930a70e66747384d3"` By testing this answer, on the compressed public keys of that transaction you can see that **it’s wrong**. Do you have any ideas why ?  
> **username_3**: @username_0 As i mentioned in my first comment, addresses generated from compressed public key and uncompressed public key are different.  
> **username_2**: The answer is not wrong. You are misunderstanding how addresses are derived from public keys. The uncompressed and compressed versions of the same public key will produce two different addresses. Public keys are not compressed or uncompressed before address conversion, they are serialized as is (either compressed or not) and hashed and encoded.  
> **username_0**: @username_3 no, for the case I’m referring to [only the first public key in uncompressed](https://www.blockchain.com/fr/btc/tx/5ed3694e8a4fa8d3ec5c75eb6789492c69e65511522b220e94ab51da2b6dd53f?show_adv=true). There’s really uncompressed public keys on the ledger. Please see my last edit.  
> **username_2**: @username_0 I have already shown you how Bitcoin Core is getting addresses for the last two public keys which are compressed. It's the same process for the uncompressed address as well. I've updated my answer to generate its address as well.  
> **username_2**: @username_0 Can you explain what you think Bitcoin Core is doing? That way we can explain what it is that you have mistaken.  
> **username_0**: @AndrewChow ok. I simply thought uncompressing public key was required for address generation.  
> **username_5**: For anyone interested in the math: the magical line `y = pow(y_sq, (p + 1) // 4, p)` is due to `p` in the curve bitcoin uses being like `p % 4 == 3` otherwise you have to use an algorithm such as [Tonelli–Shanks](https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) to find `y`.  
> **username_6**: I don't think the second mod operation is needed for y_sq since pow(x, 3, p) + 7 will be always less than p.  

---

### Answer by username_1 on 2020-03-24. Score: 1

If you're looking for a quick utility to [compress](https://bitauth.github.io/bitcoin-ts/interfaces/secp256k1.html#compresspublickey)/[uncompress](https://bitauth.github.io/bitcoin-ts/interfaces/secp256k1.html#uncompresspublickey) Secp256k1 public keys, try [bitcoin-ts](https://github.com/bitauth/bitcoin-ts):

```
const {instantiateSecp256k1, hexToBin, binToHex} = require("bitcoin-ts")
const secp256k1 = await instantiateSecp256k1();

const compressed = hexToBin('02ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe');

const uncompressed = secp256k1.uncompressPublicKey(compressed);
console.log(binToHex(uncompressed));
// => 04ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe877677c668bd13603944e34f4818ee03cadd81a88542b8b4d5431264180e2c28

const recompressed = secp256k1.compressPublicKey(uncompressed);
console.log(binToHex(recompressed));
// => 02ad90e5b6bc86b3ec7fac2c5fbda7423fc8ef0d58df594c773fa05e2c281b2bfe

```

[Run in the browser →](https://repl.it/@bitjson/Decompress-Secp256k1-Public-Keys-with-bitcoin-ts)


---

