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

本文关键字:地址 到字节 数组 Base58 解码 | 更新日期: 2023-09-27 18:22:07

我正试图将Base58字符串中的比特币地址解码为字节数组,为此,我重写了Satoshi存储库中的原始函数(https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp),用c++编写,到c#(我正在使用)。

原始代码

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;
}

Mine重写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。输入:16UwLL9风险3QfPqBUvKofHmBq7wMtjvM输出:000966776006953D5567439E5E39F86A0D273BEED61967F6应为:00010966776006953D5567439E5E39F86A0D273BEED61967F6

21。输入:1v3VUYGogXD7S1E8ipahj7QXgC568dz1输出:0008201462985DF5255E4A6C9D493C932FAC98EF791E2F22应为:000A08201462985DF5255E4A6C9D493C932FAC98EF791E2F22

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

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

在for循环中:

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

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