<p>I think you have a fundamental misunderstanding of Base58 encoding. Base58checked is not fixed length; its length depends on the number of leading zero bytes in the input.</p>

<p>There should only be one leading "1" that signifies "main net" address type. A second leading "1" would indicate a whole leading zero byte (0x00) in the pubkey hash itself, which is not applicable in this case because your sha256+ripemd-160 is 0a33807d0764e0bc71677fbef234d4989d0c198e. It only has a leading zero nibble.</p>

CC BY-SA 3.0
2014-02-25T02:38:11.880Z
I'm talking about the zero you mention in `0a33`.  That zero in the RipeMD is messing me up... not sure what to do with it..
makerofthings7
CC BY-SA 3.0
2014-02-25T02:40:46.167Z
Yeah that is only a nibble (4 zero bits). You can only use "1" in the beginning for whole zero bytes (8 zero bits).
uminatsu
CC BY-SA 3.0
2014-02-25T02:53:03.693Z
This is what you should be doing: https://code.google.com/p/bitcoinj/source/browse/core/src/main/java/com/google/bitcoin/core/Base58.java#54
Diego Basch
CC BY-SA 3.0
2014-02-25T04:10:03.487Z
@makerofthings7 it is very simple to understand the rules of Base58 encoding. You first count the number of leading zero bytes, then remove them, then treat the remaining bytes as a big-endian integer and convert to base-58, and finally add as many "1" prefixes as the number of leading zero bytes.
uminatsu
CC BY-SA 3.0
2014-02-25T05:01:54.017Z
Note to self: The following uncompressed public key has 8 zero bits when encoded to Base58  `04448212C17B6D5FD88E316AFB1D79432D7BC983567CFD5945DFE2E54C2F2A5F69E234588C4C43EB7F1E7285C0F6CBC61A31385FADF7663305A6F4FF494D621F8D`
makerofthings7
CC BY-SA 3.0
2014-02-25T02:29:24.127Z
2014-02-25T04:02:48.330Z
2014-02-25T04:02:48.330Z
uminatsu
<p>The problem lies int my code's interpretation of zeroes in the most significant bits (MSB).  I've updated my code to give the correct base58hash code (as verified by the QT client).</p>

<p>Given that the Base58 checked encoding always works with 25 bytes (RIPEMD + Network + 4 byte Checksum)</p>

<p>The following public key has one MSB of zero</p>

<pre><code>04EF12BF0C1EC3646CE6828E7D59B4111381EB8A3DF2BBB89D53254AD70BE27498C76F6E2AB3B7FC15A69B0A44AC84659728146E46670E3C66B14222FAB82C8CF6
</code></pre>

<p>Since the MSB has two zero, the Base58 hash base one zero <code>1EVEDmVcV7iPvTkaw2gk89yVcCzPzaS6B7</code></p>

<hr>

<p>The following public key has a MSB of two zeros </p>

<pre><code>04BAE942CC53D51498CD2E1576C1C43F125302DEF76A8A470B818C8D6BB65A82D679232E294E6F2D1C78F35BAA272EF1585F2FFE8B88769B02FBCEDD070CE50D4B
</code></pre>

<p>Since the MSB has two zero, the Base58 hash base two zeros <code>11ujQcjgoMNmbmcBkk8CXLWQy8ZerMtuN</code></p>

<hr>

<p>The following public key has a MSB of three zeros</p>

<pre><code>04AD8A68DF6A4553BEDD234BF2D7BFB5F0C5830F13C3A5F814AAFC03E2C92602EC1047CFE67F14D499B55F57BBE104D29E9BF6C9849771B4E3AE46FFB76FE3DFCD
</code></pre>

<p>Since the MSB has three zeros, the Base58 hash three zeros 
<code>111oeV7wjVNCQttqY63jLFsg817aMEmTw</code></p>

CC BY-SA 4.0
2014-02-25T17:23:56.200Z
2018-09-17T16:03:03.057Z
2018-09-17T16:03:03.057Z
makerofthings7
<p>My understanding is that Base58Checked is always 34 bytes long, and isn't going to be less than 34 bytes even if the first or last bytes of the RipeMD are zero.  If this statement isn't true, then none of the following question matters.</p>

<p><strong>Short question</strong></p>

<p>What should the Base58Checked address be for the following public key?</p>

<pre><code>0414C7AB38D5CC0A39B3BF5F970C572736904D40A5879BBB05BBE16911D7F35DD3E25525877587BF91EE801393FACDED26FAFA173E457F5961BA11F602CC08FE5A
</code></pre>

<p><a href="http://gobittest.appspot.com/Address" rel="nofollow">This test website</a> says it should be <code>1vwTLMCesc1vijZbscYfnr7naV9MEy8dS</code>, however, when I look at the logic below, I think it should be <code>11vwTLMCesc1vijZbscYfnr7naV9MEy8dS</code>  (notice the second leading one)</p>

<p><strong>More information</strong></p>

<p>In this loop, the value <code>numberToShorten</code> decrements as I figure out what is zero for the last few rounds of the conversion.  (e.g. "1" for a value of zero, and "A" for a remainder of nine.</p>

<p>The following uncompressed public key is an example of one that leaves a zero for me to deal with when encoding:</p>

<pre><code>0414C7AB38D5CC0A39B3BF5F970C572736904D40A5879BBB05BBE16911D7F35DD3E25525877587BF91EE801393FACDED26FAFA173E457F5961BA11F602CC08FE5A
</code></pre>

<p>Here is my C# code:</p>

<pre><code>    public static String sBase58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    public static String EncodeBase58(BigInteger numberToShorten)
    {
        // WARNING: Beware of bignumber implementations that clip leading 0x00 bytes, or prepend extra 0x00 
        // bytes to indicate sign - your code must handle these cases properly or else you may generate valid-looking
        // addresses which can be sent to, but cannot be spent from - which would lead to the permanent loss of coins.)

        const int sizeWalletImportFormat = 51;
          BigInteger base58AlphabetLength = (BigInteger)sBase58Alphabet.Length;

        char[] result = new char[34];

        int i = 0;
        while (result.Length &gt; i &amp;&amp; numberToShorten &gt;= 0)
         { 
            var lNumberRemainder = BigInteger.Remainder(numberToShorten, base58AlphabetLength);
            result[result.Length - 1 - i] = sBase58Alphabet[(int)lNumberRemainder];

            if (i == 31 &amp;&amp; numberToShorten == 0)
                Console.WriteLine("found one");

            //Console.WriteLine("i = " + i);
            //Console.WriteLine("numberToShorten= " + numberToShorten + " (Divide this by 58 to get the value below)");
            //Console.WriteLine("lNumberRemainder = " + lNumberRemainder + " (Get this position in the Base58Array and append that character)");
            //Console.WriteLine("result = " + new string(result));

            if (numberToShorten == 0)
            {
                if (i != 33)
                {
                    // Debug
                    Console.WriteLine("i = " + i);
                    break;
                }
                break;
            } 

            numberToShorten = numberToShorten / base58AlphabetLength;
            i++;
        }
        var ret = new string(result, 33 - i, result.Length - (33 - i));

        return ret;
    }

    public static DecodedBase58Result DecodeBase58(String base58StringToExpand)
    { 
        DecodedBase58Result ret = new DecodedBase58Result();

        BigInteger base58AlphabetLength = (BigInteger)sBase58Alphabet.Length;

        BigInteger numberToExtend = BigInteger.Zero;
        var charsToDecode = base58StringToExpand.ToCharArray();
        for (int decodePosition = 0; decodePosition &lt;= charsToDecode.Length - 1; decodePosition++)
        {
            char sCurrentCharacter = charsToDecode[decodePosition];
            int index = sBase58Alphabet.IndexOf(sCurrentCharacter);
            if (index == -1)
                throw new Exception("Not a base58 address, " + sCurrentCharacter + " isn't a valid character.");

            numberToExtend = numberToExtend * base58AlphabetLength;
            numberToExtend = numberToExtend + index;

            //Console.WriteLine(" i = " + (base58StringToExpand.Length - decodePosition));
            //Console.WriteLine(" number = " + numberToExtend);
            //Console.WriteLine(" Result = " + ret);
        }

        ret.BigInt = numberToExtend;
        return ret;
    }
</code></pre>

<p>The truncated character-by-character building of the Base58 address is below.  The problem lies where <code>i=32</code></p>

<pre><code>i = 27
numberToShorten= 610398922 (Divide this by 58 to get the value below)
lNumberRemainder = 20 (Get this position in the Base58Array and append that character)
result =       MCesc1vijZbscYfnr7naV9MEy8dS

i = 28
numberToShorten= 10524119 (Divide this by 58 to get the value below)
lNumberRemainder = 19 (Get this position in the Base58Array and append that character)
result =      LMCesc1vijZbscYfnr7naV9MEy8dS

i = 29
numberToShorten= 181450 (Divide this by 58 to get the value below)
lNumberRemainder = 26 (Get this position in the Base58Array and append that character)
result =     TLMCesc1vijZbscYfnr7naV9MEy8dS

i = 30
numberToShorten= 3128 (Divide this by 58 to get the value below)
lNumberRemainder = 54 (Get this position in the Base58Array and append that character)
result =    wTLMCesc1vijZbscYfnr7naV9MEy8dS

i = 31
numberToShorten= 53 (Divide this by 58 to get the value below)
lNumberRemainder = 53 (Get this position in the Base58Array and append that character)
result =   vwTLMCesc1vijZbscYfnr7naV9MEy8dS

i = 32
numberToShorten= 0 (Divide this by 58 to get the value below)
lNumberRemainder = 0 (Get this position in the Base58Array and append that character)
result =  1vwTLMCesc1vijZbscYfnr7naV9MEy8dS

i = 33
numberToShorten= 0 (Divide this by 58 to get the value below)
lNumberRemainder = 0 (Get this position in the Base58Array and append that character)
result = 11vwTLMCesc1vijZbscYfnr7naV9MEy8dS
</code></pre>

CC BY-SA 3.0
2014-02-25T02:21:46.807Z
Your first statement isn't true. A Bitcoin address doesn't have to be 34 characters long. For example, see the first few: http://directory.io/
Diego Basch
<development><base58check>
What is the correct Base58 encoding for this uncompressed Public Key RipeMD hash with a zeros in bits 31, 32, or 33?
makerofthings7
# What is the correct Base58 encoding for this uncompressed Public Key RipeMD hash with a zeros in bits 31, 32, or 33?

(Asked by: username_0 on 2014-02-25)

My understanding is that Base58Checked is always 34 bytes long, and isn't going to be less than 34 bytes even if the first or last bytes of the RipeMD are zero. If this statement isn't true, then none of the following question matters.

**Short question**

What should the Base58Checked address be for the following public key?

```
0414C7AB38D5CC0A39B3BF5F970C572736904D40A5879BBB05BBE16911D7F35DD3E25525877587BF91EE801393FACDED26FAFA173E457F5961BA11F602CC08FE5A

```

[This test website](http://gobittest.appspot.com/Address) says it should be `1vwTLMCesc1vijZbscYfnr7naV9MEy8dS`, however, when I look at the logic below, I think it should be `11vwTLMCesc1vijZbscYfnr7naV9MEy8dS` (notice the second leading one)

**More information**

In this loop, the value `numberToShorten` decrements as I figure out what is zero for the last few rounds of the conversion. (e.g. "1" for a value of zero, and "A" for a remainder of nine.

The following uncompressed public key is an example of one that leaves a zero for me to deal with when encoding:

```
0414C7AB38D5CC0A39B3BF5F970C572736904D40A5879BBB05BBE16911D7F35DD3E25525877587BF91EE801393FACDED26FAFA173E457F5961BA11F602CC08FE5A

```

Here is my C# code:

```
    public static String sBase58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    public static String EncodeBase58(BigInteger numberToShorten)
    {
        // WARNING: Beware of bignumber implementations that clip leading 0x00 bytes, or prepend extra 0x00 
        // bytes to indicate sign - your code must handle these cases properly or else you may generate valid-looking
        // addresses which can be sent to, but cannot be spent from - which would lead to the permanent loss of coins.)

        const int sizeWalletImportFormat = 51;
          BigInteger base58AlphabetLength = (BigInteger)sBase58Alphabet.Length;

        char[] result = new char[34];

        int i = 0;
        while (result.Length > i && numberToShorten >= 0)
         { 
            var lNumberRemainder = BigInteger.Remainder(numberToShorten, base58AlphabetLength);
            result[result.Length - 1 - i] = sBase58Alphabet[(int)lNumberRemainder];

            if (i == 31 && numberToShorten == 0)
                Console.WriteLine("found one");

            //Console.WriteLine("i = " + i);
            //Console.WriteLine("numberToShorten= " + numberToShorten + " (Divide this by 58 to get the value below)");
            //Console.WriteLine("lNumberRemainder = " + lNumberRemainder + " (Get this position in the Base58Array and append that character)");
            //Console.WriteLine("result = " + new string(result));

            if (numberToShorten == 0)
            {
                if (i != 33)
                {
                    // Debug
                    Console.WriteLine("i = " + i);
                    break;
                }
                break;
            } 

            numberToShorten = numberToShorten / base58AlphabetLength;
            i++;
        }
        var ret = new string(result, 33 - i, result.Length - (33 - i));

        return ret;
    }

    public static DecodedBase58Result DecodeBase58(String base58StringToExpand)
    { 
        DecodedBase58Result ret = new DecodedBase58Result();

        BigInteger base58AlphabetLength = (BigInteger)sBase58Alphabet.Length;

        BigInteger numberToExtend = BigInteger.Zero;
        var charsToDecode = base58StringToExpand.ToCharArray();
        for (int decodePosition = 0; decodePosition <= charsToDecode.Length - 1; decodePosition++)
        {
            char sCurrentCharacter = charsToDecode[decodePosition];
            int index = sBase58Alphabet.IndexOf(sCurrentCharacter);
            if (index == -1)
                throw new Exception("Not a base58 address, " + sCurrentCharacter + " isn't a valid character.");

            numberToExtend = numberToExtend * base58AlphabetLength;
            numberToExtend = numberToExtend + index;

            //Console.WriteLine(" i = " + (base58StringToExpand.Length - decodePosition));
            //Console.WriteLine(" number = " + numberToExtend);
            //Console.WriteLine(" Result = " + ret);
        }

        ret.BigInt = numberToExtend;
        return ret;
    }

```

The truncated character-by-character building of the Base58 address is below. The problem lies where `i=32`

```
i = 27
numberToShorten= 610398922 (Divide this by 58 to get the value below)
lNumberRemainder = 20 (Get this position in the Base58Array and append that character)
result =       MCesc1vijZbscYfnr7naV9MEy8dS

i = 28
numberToShorten= 10524119 (Divide this by 58 to get the value below)
lNumberRemainder = 19 (Get this position in the Base58Array and append that character)
result =      LMCesc1vijZbscYfnr7naV9MEy8dS

i = 29
numberToShorten= 181450 (Divide this by 58 to get the value below)
lNumberRemainder = 26 (Get this position in the Base58Array and append that character)
result =     TLMCesc1vijZbscYfnr7naV9MEy8dS

i = 30
numberToShorten= 3128 (Divide this by 58 to get the value below)
lNumberRemainder = 54 (Get this position in the Base58Array and append that character)
result =    wTLMCesc1vijZbscYfnr7naV9MEy8dS

i = 31
numberToShorten= 53 (Divide this by 58 to get the value below)
lNumberRemainder = 53 (Get this position in the Base58Array and append that character)
result =   vwTLMCesc1vijZbscYfnr7naV9MEy8dS

i = 32
numberToShorten= 0 (Divide this by 58 to get the value below)
lNumberRemainder = 0 (Get this position in the Base58Array and append that character)
result =  1vwTLMCesc1vijZbscYfnr7naV9MEy8dS

i = 33
numberToShorten= 0 (Divide this by 58 to get the value below)
lNumberRemainder = 0 (Get this position in the Base58Array and append that character)
result = 11vwTLMCesc1vijZbscYfnr7naV9MEy8dS

```

**Tags:** development, base58check

> **Comments:**
> **username_1**: Your first statement isn't true. A Bitcoin address doesn't have to be 34 characters long. For example, see the first few: http://directory.io/  

---

## 2 answers

### Answer by username_2 on 2014-02-25. Score: 1 | Accepted answer

I think you have a fundamental misunderstanding of Base58 encoding. Base58checked is not fixed length; its length depends on the number of leading zero bytes in the input.

There should only be one leading "1" that signifies "main net" address type. A second leading "1" would indicate a whole leading zero byte (0x00) in the pubkey hash itself, which is not applicable in this case because your sha256+ripemd-160 is 0a33807d0764e0bc71677fbef234d4989d0c198e. It only has a leading zero nibble.

> **Comments:**
> **username_0**: I'm talking about the zero you mention in `0a33`.  That zero in the RipeMD is messing me up... not sure what to do with it..  
> **username_2**: Yeah that is only a nibble (4 zero bits). You can only use "1" in the beginning for whole zero bytes (8 zero bits).  
> **username_1**: This is what you should be doing: https://code.google.com/p/bitcoinj/source/browse/core/src/main/java/com/google/bitcoin/core/Base58.java#54  
> **username_2**: @username_0 it is very simple to understand the rules of Base58 encoding. You first count the number of leading zero bytes, then remove them, then treat the remaining bytes as a big-endian integer and convert to base-58, and finally add as many "1" prefixes as the number of leading zero bytes.  
> **username_0**: Note to self: The following uncompressed public key has 8 zero bits when encoded to Base58  `04448212C17B6D5FD88E316AFB1D79432D7BC983567CFD5945DFE2E54C2F2A5F69E234588C4C43EB7F1E7285C0F6CBC61A31385FADF7663305A6F4FF494D621F8D`  

---

### Answer by username_0 on 2014-02-25. Score: 0

The problem lies int my code's interpretation of zeroes in the most significant bits (MSB). I've updated my code to give the correct base58hash code (as verified by the QT client).

Given that the Base58 checked encoding always works with 25 bytes (RIPEMD + Network + 4 byte Checksum)

The following public key has one MSB of zero

```
04EF12BF0C1EC3646CE6828E7D59B4111381EB8A3DF2BBB89D53254AD70BE27498C76F6E2AB3B7FC15A69B0A44AC84659728146E46670E3C66B14222FAB82C8CF6

```

Since the MSB has two zero, the Base58 hash base one zero `1EVEDmVcV7iPvTkaw2gk89yVcCzPzaS6B7`

---

The following public key has a MSB of two zeros

```
04BAE942CC53D51498CD2E1576C1C43F125302DEF76A8A470B818C8D6BB65A82D679232E294E6F2D1C78F35BAA272EF1585F2FFE8B88769B02FBCEDD070CE50D4B

```

Since the MSB has two zero, the Base58 hash base two zeros `11ujQcjgoMNmbmcBkk8CXLWQy8ZerMtuN`

---

The following public key has a MSB of three zeros

```
04AD8A68DF6A4553BEDD234BF2D7BFB5F0C5830F13C3A5F814AAFC03E2C92602EC1047CFE67F14D499B55F57BBE104D29E9BF6C9849771B4E3AE46FFB76FE3DFCD

```

Since the MSB has three zeros, the Base58 hash three zeros
`111oeV7wjVNCQttqY63jLFsg817aMEmTw`


---

