<p>The <code>base58.b58decode</code> and <code>base58.b58encode</code> functions <em>only</em> do the Base 58 decode/encode. However xpubs are encoded with Base 58 <strong>Check</strong> encoding. The difference is that Base 58 Check encoding computes a checksum of the payload and appends the first 4 bytes of that to the payload before the base 58 encoding.</p>
<p>You need to be using <code>base58.b58decode_check</code> and <code>base58.b58encode_check</code> which will drop the checksum for the decode, and add the checksum for the encode.</p>

CC BY-SA 4.0
2020-09-02T00:25:11.470Z
2020-09-02T00:25:11.470Z
Ava Chow
<p>The code below is generating an YPub from XPub with the last 6 digits wrong.</p>
<p>How can I verify what's happening and fix this error?</p>
<p>e.g.:
It should be  ypub6X7aFbqxwbJHJQqUhfTEZDWxVT8qbu4qjN8fCz9ADRuAwaZQ243YiB1w5yTE2qRJzRJ3Kza9DbefU8pnqjk3GEmn6g9usvkZZrP94<strong>VcBVdz</strong></p>
<p>but it returns ypub6X7aFbqxwbJHJQqUhfTEZDWxVT8qbu4qjN8fCz9ADRuAwaZQ243YiB1w5yTE2qRJzRJ3Kza9DbefU8pnqjk3GEmn6g9usvkZZrP94<strong>YkSjSS</strong></p>
<p>The code is adapted from <a href="https://github.com/unchained-capital/unchained-bitcoin/blob/4d1a60d0d11d23543b50613748b8bd0b4c93b42c/src/keys.js#L188" rel="nofollow noreferrer">this function</a> in JS, that works well.</p>
<pre><code>import hashlib
import base58

prefixesPub =  {
  'xpub': '0488b21e',
  'ypub': '049d7cb2',
  'Ypub': '0295b43f',
  'zpub': '04b24746',
  'Zpub': '02aa7ed3',
  'tpub': '043587cf',
  'upub': '044a5262',
  'Upub': '024289ef',
  'vpub': '045f1cf6',
  'Vpub': '02575483'
}

def convert_pub_key(_xpub, target_prefix):
  decoded_extended_publicKey = base58.b58decode(_xpub.strip())
  extended_public_key_no_prefix = decoded_extended_publicKey[4:]
  extended_public_key_new_prefix = bytes.fromhex(prefixesPub[target_prefix]) + extended_public_key_no_prefix
  print(base58.b58encode(extended_public_key_new_prefix))

pub_key = &quot;xpub6CHJwwB3nukoT7eMsJfcM8RTKUzPfH5LpFcSRbFGqRXHtUkAmPsz67Mo4mVe2vmPanBEaWyakwJ7arDE83L2U16BELTVJ1w5J8KVfyMqtzE&quot;
prefix = &quot;ypub&quot;
convert_pub_key(pub_key, prefix)
</code></pre>

<python><xpub>
XPub to YPub Converter (python) - Last digits wrong
le0
# XPub to YPub Converter (python) - Last digits wrong

(Asked by: username_0 on 2020-09-01)

The code below is generating an YPub from XPub with the last 6 digits wrong.

How can I verify what's happening and fix this error?

e.g.:
It should be ypub6X7aFbqxwbJHJQqUhfTEZDWxVT8qbu4qjN8fCz9ADRuAwaZQ243YiB1w5yTE2qRJzRJ3Kza9DbefU8pnqjk3GEmn6g9usvkZZrP94**VcBVdz**

but it returns ypub6X7aFbqxwbJHJQqUhfTEZDWxVT8qbu4qjN8fCz9ADRuAwaZQ243YiB1w5yTE2qRJzRJ3Kza9DbefU8pnqjk3GEmn6g9usvkZZrP94**YkSjSS**

The code is adapted from [this function](https://github.com/unchained-capital/unchained-bitcoin/blob/4d1a60d0d11d23543b50613748b8bd0b4c93b42c/src/keys.js#L188) in JS, that works well.

```
import hashlib
import base58

prefixesPub =  {
  'xpub': '0488b21e',
  'ypub': '049d7cb2',
  'Ypub': '0295b43f',
  'zpub': '04b24746',
  'Zpub': '02aa7ed3',
  'tpub': '043587cf',
  'upub': '044a5262',
  'Upub': '024289ef',
  'vpub': '045f1cf6',
  'Vpub': '02575483'
}

def convert_pub_key(_xpub, target_prefix):
  decoded_extended_publicKey = base58.b58decode(_xpub.strip())
  extended_public_key_no_prefix = decoded_extended_publicKey[4:]
  extended_public_key_new_prefix = bytes.fromhex(prefixesPub[target_prefix]) + extended_public_key_no_prefix
  print(base58.b58encode(extended_public_key_new_prefix))

pub_key = "xpub6CHJwwB3nukoT7eMsJfcM8RTKUzPfH5LpFcSRbFGqRXHtUkAmPsz67Mo4mVe2vmPanBEaWyakwJ7arDE83L2U16BELTVJ1w5J8KVfyMqtzE"
prefix = "ypub"
convert_pub_key(pub_key, prefix)

```

**Tags:** python, xpub


---

## 1 answers

### Answer by username_1 on 2020-09-02. Score: 1 | Accepted answer

The `base58.b58decode` and `base58.b58encode` functions *only* do the Base 58 decode/encode. However xpubs are encoded with Base 58 **Check** encoding. The difference is that Base 58 Check encoding computes a checksum of the payload and appends the first 4 bytes of that to the payload before the base 58 encoding.

You need to be using `base58.b58decode_check` and `base58.b58encode_check` which will drop the checksum for the decode, and add the checksum for the encode.


---

