将比特币Base58地址解码为字节数组

时间:2014-09-15 19:03:54

标签: c# c++ bitcoin

我试图将比特币地址从Base58字符串解码为字节数组,为此,我将原始函数从用C ++编写的Satoshi存储库(https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp)重新编写为c#(我和#39 ; m using)。

原始代码

static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char *psz, std::vector<unsigned char>& vch) {
    // Skip leading spaces.
    while (*psz && isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char *ch = strchr(pszBase58, *psz);
        if (ch == NULL)
            return false;
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    std::vector<unsigned char>::iterator it = b256.begin();
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
      vch.push_back(*(it++));
    return true;
}

我的重写c#版本

 private static string Base58characters = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
public static bool Decode(string source, ref byte[] destination)
        {
            int i = 0;
            while (i < source.Length)
            {
                if (source[i] == 0 || !Char.IsWhiteSpace(source[i]))
                {
                    break;
                }
                i++;
            }
            int zeros = 0;
            while (source[i] == '1')
            {
                zeros++;
                i++;
            }
            byte[] b256 = new byte[(source.Length - i) * 733 / 1000 + 1];
            while (i < source.Length && !Char.IsWhiteSpace(source[i]))
            {
                int ch = Base58characters.IndexOf(source[i]);
                if (ch == -1) //null
                {
                    return false;
            }
            int carry = Base58characters.IndexOf(source[i]);
            for (int k = b256.Length - 1; k > 0; k--)
            {
                carry += 58 * b256[k];
                b256[k] = (byte)(carry % 256);
                carry /= 256;
            }
            i++;
        }
        while (i < source.Length && Char.IsWhiteSpace(source[i]))
        {
            i++;
        }
        if (i != source.Length)
        {
            return false;
        }
        int j = 0;
        while (j < b256.Length && b256[j] == 0)
        {
            j++;
        }
        destination = new byte[zeros + (b256.Length - j)];
        for (int kk = 0; kk < destination.Length; kk++)
        {
            if (kk < zeros)
            {
                destination[kk] = 0x00;
            }
            else
            {
                destination[kk] = b256[j++];
            }
        }
        return true;
    }

我用于从字节数组转换为HexString

的函数
public static string ByteArrayToHexString(byte[] source)
        {
            return BitConverter.ToString(source).Replace("-", "");
        }

要测试一切是否正常,我已经在线使用了测试用例(https://github.com/ThePiachu/Bitcoin-Unit-Tests/blob/master/Address/Address%20Generation%20Test%201.txt)。好的是,97%的测试正确通过但是3有一点错误,我不知道它来自哪里。所以我对你的要求是指出这些测试可能出错的地方或重写的地方我犯了错误。提前谢谢。

发生错误的测试用例分别为1,21和25。

1。 输入: 16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM 输出: 000966776006953D5567439E5E39F86A0D273BEED61967F6 应该: 00010966776006953D5567439E5E39F86A0D273BEED61967F6

21。 输入: 1v3VUYGogXD7S1E8kipahj7QXgC568dz1 输出: 0008201462985DF5255E4A6C9D493C932FAC98EF791E2F22 应该: 000A08201462985DF5255E4A6C9D493C932FAC98EF791E2F22

25。 输入: 1axVFjCkMWDFCHjQHf99AsszXTuzxLxxg 输出: 006C0B8995C7464E89F6760900EA6978DF18157388421561 应该: 00066C0B8995C7464E89F6760900EA6978DF18157388421561

1 个答案:

答案 0 :(得分:2)

在你的for循环中:

for (int k = b256.Length - 1; k > 0; k--)

循环条件应为k >= 0,这样就不会跳过b256中的第一个字节。