user98139: 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  ypub6X7aFbqxwbJHJQqUhfTEZDWxVT8qbu4qjN8fCz9ADRuAwaZQ243YiB1w5yTE2qRJzRJ3Kza9DbefU8pnqjk3GEmn6g9usvkZZrP94VcBVdz
but it returns ypub6X7aFbqxwbJHJQqUhfTEZDWxVT8qbu4qjN8fCz9ADRuAwaZQ243YiB1w5yTE2qRJzRJ3Kza9DbefU8pnqjk3GEmn6g9usvkZZrP94YkSjSS
The code is adapted from this function 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)


user48884: 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.

98139: <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>
 48884: <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>
