user1878: 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 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


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

1878: <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>
 13751: <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>
