解码比特币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
在for循环中:
for (int k = b256.Length - 1; k > 0; k--)
循环条件应该是k >= 0
,这样就不会跳过b256
中的第一个字节。