user9382: Converting the BIP32 version bytes - x04\x88\xad\xe4 - from base256 to base58 and base58Check returns 7irrX and 1kz713TZjju, respectively.
I thought the version bytes represented xprv. What am I missing?
I'm using pybitcointools, if that makes a difference.

user10377: To complement the answer above, the Bitcoin chainparams.cpp file contains the following information to assist in achieving BIP 32 compliance:
Mainnet:
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >();

Testnet:
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();

The bitcoin-explorer (bx) command is used below, with the 3rd worst possible brain wallet seed in the world. Additionally, bx was compiled for using testnet not mainnet. Hence, focus on where 04358394 for tprv and 043587cf for tpub that appears in the examples below.
% echo '0' | bx base16-encode | bx sha512 | bx hd-new 
tprv8ZgxMBicQKsPdcvudXaExR6Wdz5VgdjGeZHsw5bjnypoxrCxnYsyVq2v9cPTzDsnyLAL1v4Z2tM3Rp2AA6vv9WDbNBtui5QEZTWYucefZox
% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx base58check-decode
wrapper
{
    checksum 3287061687
    payload 3583940000000000000000004b0dc73821a026c0c71d07a7655968352b52d7e5896dd3907df121f914f9743900a6b53d2f0e384dc6ced2caeb36f0c9cc6f3ab0677f73c31aca87b62bbcc9fe78
    version 4
}

% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx base58-decode
043583940000000000000000004b0dc73821a026c0c71d07a7655968352b52d7e5896dd3907df121f914f9743900a6b53d2f0e384dc6ced2caeb36f0c9cc6f3ab0677f73c31aca87b62bbcc9fe78b794ecc3
% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx hd-public
tpubD9nYDjxx7QwpsEhUiS7MDJ68p25nu9yxEt1AofKmEjmL3kozwA3z8G4Cm556YCYYJwfnix2GLVTtCHZq79R8UsRZBJVRPtD9HKNQBzDZVo4
% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx hd-public | bx base58-decode
043587cf01cf633b1c00000000c023d310564ead16b50e678b2ff20e2d0a0f210fcf9c603ebd16f17d0510663802605d719a28b2707dcc9d7a2b804ba70242330e7010161aec4f86a0771d9909e504b705bf

user18196: Just like in regular bitcoin addresses (or anything base 58 encoded), the version bytes don't get encoded by themselves. As described in the Serialization format section, there is 78 byte payload that gets versioned and checksumed before then being encoded into base 58:


4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private; testnet: 0x043587CF public, 0x04358394 private)
1 byte: depth: 0x00 for master nodes, 0x01 for level-1 derived keys, ....
4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
4 bytes: child number. This is ser32(i) for i in xi = xpar/i, with xi the key > - being serialized. (0x00000000 if master key)
32 bytes: the chain code
33 bytes: the public key or private key data (serP(K) for public keys, 0x00 || ser256(k) for private keys)


There's not a byte-to-character mapping when you do base58 serialization of a multi-byte structure. It's not like 0x04 becomes 'x', 0x88 becomes 'p', etc. Rather, the whole 86 (78 payload + 4 version + 4 checksum) byte structure gets encoded to something that starts with 'xpriv' when the 4 most significant bytes of the 86 bytes structure are [0x04, 0x88, 0xad, 0xe4].

9382: <p>Converting the BIP32 version bytes - <code>x04\x88\xad\xe4</code> - from base256 to base58 and base58Check returns <code>7irrX</code> and <code>1kz713TZjju</code>, respectively.</p>

<p>I thought the version bytes represented <code>xprv</code>. What am I missing?</p>

<p>I'm using <em>pybitcointools</em>, if that makes a difference.</p>
 10377: <p>To complement the answer above, the Bitcoin <a href="https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.cpp" rel="nofollow">chainparams.cpp</a> file contains the following information to assist in achieving BIP 32 compliance:</p>

<p>Mainnet:</p>

<pre><code>base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container&lt;std::vector&lt;unsigned char&gt; &gt;();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container&lt;std::vector&lt;unsigned char&gt; &gt;();
</code></pre>

<p>Testnet:</p>

<pre><code>base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container&lt;std::vector&lt;unsigned char&gt; &gt;();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container&lt;std::vector&lt;unsigned char&gt; &gt;();
</code></pre>

<p>The bitcoin-explorer (bx) command is used below, with the 3rd worst possible brain wallet seed in the world. Additionally, bx was compiled for using testnet not mainnet. Hence, focus on where <strong>04358394</strong> for <strong>tprv</strong> and <strong>043587cf</strong> for <strong>tpub</strong> that appears in the examples below.</p>

<p>% echo '0' | bx base16-encode | bx sha512 | bx hd-new 
<code>tprv8ZgxMBicQKsPdcvudXaExR6Wdz5VgdjGeZHsw5bjnypoxrCxnYsyVq2v9cPTzDsnyLAL1v4Z2tM3Rp2AA6vv9WDbNBtui5QEZTWYucefZox</code></p>

<p>% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx base58check-decode</p>

<pre><code>wrapper
{
    checksum 3287061687
    payload 3583940000000000000000004b0dc73821a026c0c71d07a7655968352b52d7e5896dd3907df121f914f9743900a6b53d2f0e384dc6ced2caeb36f0c9cc6f3ab0677f73c31aca87b62bbcc9fe78
    version 4
}
</code></pre>

<p>% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx base58-decode
<code>04358394</code>0000000000000000004b0dc73821a026c0c71d07a7655968352b52d7e5896dd3907df121f914f9743900a6b53d2f0e384dc6ced2caeb36f0c9cc6f3ab0677f73c31aca87b62bbcc9fe78<code>b794ecc3</code></p>

<p>% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx hd-public
<code>tpubD9nYDjxx7QwpsEhUiS7MDJ68p25nu9yxEt1AofKmEjmL3kozwA3z8G4Cm556YCYYJwfnix2GLVTtCHZq79R8UsRZBJVRPtD9HKNQBzDZVo4</code></p>

<p>% echo '0' | bx base16-encode | bx sha512 | bx hd-new | bx hd-public | bx base58-decode
<code>043587cf</code>01cf633b1c00000000c023d310564ead16b50e678b2ff20e2d0a0f210fcf9c603ebd16f17d0510663802605d719a28b2707dcc9d7a2b804ba70242330e7010161aec4f86a0771d9909e504b705bf</p>
 18196: <p>Just like in regular bitcoin addresses (or anything base 58 encoded), the version bytes don't get encoded by themselves. As described in the <a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#serialization-format" rel="nofollow">Serialization format</a> section, there is 78 byte payload that gets versioned and checksumed before then being encoded into base 58:</p>

<blockquote>
  <ul>
  <li>4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private; testnet: 0x043587CF public, 0x04358394 private)</li>
  <li>1 byte: depth: 0x00 for master nodes, 0x01 for level-1 derived keys, ....</li>
  <li>4 bytes: the fingerprint of the parent's key (0x00000000 if master key)</li>
  <li>4 bytes: child number. This is ser32(i) for i in xi = xpar/i, with xi the key > - being serialized. (0x00000000 if master key)</li>
  <li>32 bytes: the chain code</li>
  <li>33 bytes: the public key or private key data (serP(K) for public keys, 0x00 || ser256(k) for private keys)</li>
  </ul>
</blockquote>

<p>There's not a byte-to-character mapping when you do base58 serialization of a multi-byte structure. It's not like 0x04 becomes 'x', 0x88 becomes 'p', etc. Rather, the whole 86 (78 payload + 4 version + 4 checksum) byte structure gets encoded to something that starts with 'xpriv' when the 4 most significant bytes of the 86 bytes structure are [0x04, 0x88, 0xad, 0xe4].</p>
