<p>In both cases, you are not generating the address that corresponds to the compressed public key.</p>

<p>In the first case, you are creating what looks to be an invalid address. At the very least, the private key it is using is incorrect because it has the compression byte. This will change the value that you get for the private key when it is decoded. In order to get the same outcome as the second case, you would need to drop an additional byte from the decoded WIF key as that byte specifies compression. The key you are using there is 33 bytes rather than the 32 bytes for actual private keys.</p>

<p>In the second case, you are not creating the compressed public key to generate the address. It is still using the uncompressed public key. Instead of using <code>fast_multiply</code> and creating the public key yourself, you should be using <code>privkey_to_pubkey</code>. <code>fast_multiply</code> is a mathematical operation, it has no concept of compressed public keys. However <code>privkey_to_pubkey</code> does so it will create the proper public key. Then you can use that public key to generate the address.</p>

<p>Instead of doing</p>

<pre><code>public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
</code></pre>

<p>you should be doing</p>

<pre><code>public_key = bitcoin.privkey_to_pubkey(pvt)
</code></pre>

CC BY-SA 3.0
2018-01-01T19:11:21.143Z
Thanks for your helpful answer. About your last paragraph, why can't I use an elliptic curve multiplication (there should be one under the hood, even in the compressed case, right?)? Also could you just post (for future reference, and to be sure) the line of code we should use instead of `fast_multiply`?
Basj
CC BY-SA 3.0
2018-01-01T19:19:30.070Z
Because compression occurs independently of the elliptic curve operations. Elliptic curve operations don't know what point compression is; they can only operate on the full curve. However libraries can use point compression, and that must happen separately from the EC operations.
Ava Chow
CC BY-SA 3.0
2018-01-01T19:23:01.820Z
Thanks @AndrewChow. I tried with `public_key = bitcoin.privkey_to_pubkey(pvt2)` but I still get `18dFF3EQoPxR44TygdGxHPMe3LSLFeQe4U` instead of the original address `1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA`. What can be wrong?
Basj
CC BY-SA 3.0
2018-01-01T19:27:15.347Z
Looking at the implementation of this `pybitcointools`, you don't need to decode the private key when you use `privkey_to_pubkey`. Rather it is decoded for you by that function itself. I will update my answer with the correct code.
Ava Chow
CC BY-SA 3.0
2018-01-01T19:29:24.100Z
Thanks a lot! I'm struggling to get `1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA` as output :)
Basj
CC BY-SA 3.0
2018-01-01T19:37:38.383Z
Did you try the most recent edit?
Ava Chow
CC BY-SA 3.0
2018-01-01T19:08:21.377Z
2018-01-01T19:27:25.347Z
2018-01-01T19:27:25.347Z
Ava Chow
<p>Based on the accepted answer's suggestion to use <code>privkey_to_pubkey</code>, I analyzed its code, and so this works as well:</p>

<pre><code>pvt = 'Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx'
pvtdecoded = base58.b58decode(pvt)
pvthex = binascii.hexlify(pvtdecoded)[2:-10]     # remove the first initial byte for version and 4 final bytes for checksum
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')     # decode as a decimal

# generate pubkey from pvtkey with elliptic curve multiplication
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
public_key = bitcoin.encode_pubkey(public_key, 'hex_compressed')
addr = bitcoin.pubkey_to_address(public_key)
print addr    # 1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA
</code></pre>

CC BY-SA 3.0
2018-01-01T19:55:35.497Z
2018-01-01T19:55:35.497Z
Basj
<p>I have created a new Electrum wallet, and here is an address:</p>

<pre><code>1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA
</code></pre>

<p>By right-clicking on it, I choose "Private key" which gives:</p>

<pre><code>Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx
</code></pre>

<p>Now I want to be able (to learn how it works) to go from this private key to the address, via elliptic curve multiplication.</p>

<p>Here is what I tried:</p>

<pre><code>import bitcoin #pybitcointools
import base58
import binascii

pvt = 'Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx'
pvtdecoded = base58.b58decode(pvt)
pvthex = binascii.hexlify(pvtdecoded)[2:-8]     # remove the first initial byte for version and 4 final bytes for checksum
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')    # decode as a decimal

# generate pubkey from pvtkey with elliptic curve multiplication
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
addr = bitcoin.pubkey_to_address(public_key)
print addr
</code></pre>

<p>which gives: <code>1LNSuE4NKHTyHygeKwnU1equ7MjPMhayxB</code> which is not the original address.</p>

<p><strong>What's wrong? How to recover the original address (<code>1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA</code>) from the Private key by using elliptic curve multiplication?</strong></p>

<hr>

<p><strong>Edit</strong>: As <code>Kz....Wx</code> private key looks like a WIF-compressed one, I tried to replace:</p>

<pre><code>pvt2 = bitcoin.decode_privkey(pvthex, 'hex')    # decode as a decimal
</code></pre>

<p>by</p>

<pre><code>pvt2 = bitcoin.decode_privkey('Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx', 'wif')
</code></pre>

<p>but then after elliptic curve multiplication, it gives another address, which is still not the good one! (<code>18dFF3EQoPxR44TygdGxHPMe3LSLFeQe4U</code>)</p>

CC BY-SA 3.0
2018-01-01T17:44:33.277Z
Note: I have read https://en.bitcoin.it/wiki/Wallet_import_format, and `WIF to private key`, but I'm still stuck.
Basj
<address><private-key><public-key><address-generation><secp256k1>
Private key exported from Electrum, unable to recreate Address with Python
Basj
# Private key exported from Electrum, unable to recreate Address with Python

(Asked by: username_0 on 2018-01-01)

I have created a new Electrum wallet, and here is an address:

```
1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA

```

By right-clicking on it, I choose "Private key" which gives:

```
Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx

```

Now I want to be able (to learn how it works) to go from this private key to the address, via elliptic curve multiplication.

Here is what I tried:

```
import bitcoin #pybitcointools
import base58
import binascii

pvt = 'Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx'
pvtdecoded = base58.b58decode(pvt)
pvthex = binascii.hexlify(pvtdecoded)[2:-8]     # remove the first initial byte for version and 4 final bytes for checksum
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')    # decode as a decimal

# generate pubkey from pvtkey with elliptic curve multiplication
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
addr = bitcoin.pubkey_to_address(public_key)
print addr

```

which gives: `1LNSuE4NKHTyHygeKwnU1equ7MjPMhayxB` which is not the original address.

**What's wrong? How to recover the original address (`1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA`) from the Private key by using elliptic curve multiplication?**

---

**Edit**: As `Kz....Wx` private key looks like a WIF-compressed one, I tried to replace:

```
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')    # decode as a decimal

```

by

```
pvt2 = bitcoin.decode_privkey('Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx', 'wif')

```

but then after elliptic curve multiplication, it gives another address, which is still not the good one! (`18dFF3EQoPxR44TygdGxHPMe3LSLFeQe4U`)

**Tags:** address, private-key, public-key, address-generation, secp256k1

> **Comments:**
> **username_0**: Note: I have read https://en.bitcoin.it/wiki/Wallet_import_format, and `WIF to private key`, but I'm still stuck.  

---

## 2 answers

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

In both cases, you are not generating the address that corresponds to the compressed public key.

In the first case, you are creating what looks to be an invalid address. At the very least, the private key it is using is incorrect because it has the compression byte. This will change the value that you get for the private key when it is decoded. In order to get the same outcome as the second case, you would need to drop an additional byte from the decoded WIF key as that byte specifies compression. The key you are using there is 33 bytes rather than the 32 bytes for actual private keys.

In the second case, you are not creating the compressed public key to generate the address. It is still using the uncompressed public key. Instead of using `fast_multiply` and creating the public key yourself, you should be using `privkey_to_pubkey`. `fast_multiply` is a mathematical operation, it has no concept of compressed public keys. However `privkey_to_pubkey` does so it will create the proper public key. Then you can use that public key to generate the address.

Instead of doing

```
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)

```

you should be doing

```
public_key = bitcoin.privkey_to_pubkey(pvt)

```

> **Comments:**
> **username_0**: Thanks for your helpful answer. About your last paragraph, why can't I use an elliptic curve multiplication (there should be one under the hood, even in the compressed case, right?)? Also could you just post (for future reference, and to be sure) the line of code we should use instead of `fast_multiply`?  
> **username_1**: Because compression occurs independently of the elliptic curve operations. Elliptic curve operations don't know what point compression is; they can only operate on the full curve. However libraries can use point compression, and that must happen separately from the EC operations.  
> **username_0**: Thanks @AndrewChow. I tried with `public_key = bitcoin.privkey_to_pubkey(pvt2)` but I still get `18dFF3EQoPxR44TygdGxHPMe3LSLFeQe4U` instead of the original address `1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA`. What can be wrong?  
> **username_1**: Looking at the implementation of this `pybitcointools`, you don't need to decode the private key when you use `privkey_to_pubkey`. Rather it is decoded for you by that function itself. I will update my answer with the correct code.  
> **username_0**: Thanks a lot! I'm struggling to get `1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA` as output :)  
> **username_1**: Did you try the most recent edit?  

---

### Answer by username_0 on 2018-01-01. Score: 0

Based on the accepted answer's suggestion to use `privkey_to_pubkey`, I analyzed its code, and so this works as well:

```
pvt = 'Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx'
pvtdecoded = base58.b58decode(pvt)
pvthex = binascii.hexlify(pvtdecoded)[2:-10]     # remove the first initial byte for version and 4 final bytes for checksum
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')     # decode as a decimal

# generate pubkey from pvtkey with elliptic curve multiplication
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
public_key = bitcoin.encode_pubkey(public_key, 'hex_compressed')
addr = bitcoin.pubkey_to_address(public_key)
print addr    # 1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA

```


---

