Ниже приведен код C Я только что закончил для целей, описанных в ОП.
#включают
#включают
#включают
#включают
#включают
#включают
/ * На основе libbase58 см https://github.com/luke-jr/libbase58 для справки. * /
/ * Возвращает версию действительного адреса Bitcoin или отрицательное значение, если * /
/ * Адрес недействителен. * /
INT validate_bitcoin_address (Const символ * адрес) {
статический Const int8_t b58digits_map [] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1,
-1, 9,10,11,12,13,14,15, 16, -1,17,18,19,20,21, -1,
22,23,24,25,26,27,28,29, 30,31,32, -1, -1, -1, -1, -1,
-1,33,34,35,36,37,38,39, 40,41,42,43, -1,44,45,46,
47,48,49,50,51,52,53,54, 55,56,57, -1, -1, -1, -1, -1,
};
символ без знака addrbin [25];
size_t addrbinsz = SizeOf (addrbin);
пустота * бен = (пустота *) addrbin;
size_t * binszp = &addrbinsz;
Const символ * b58 = адрес;
size_t b58sz = StrLen (адрес);
{
Const символ без знака * b58u = (недействительными *) B58;
неподписанный символ * BINU = бен;
uint32_t Outi [(25 + 3) / 4];
size_t outisz = (25 + 3) / 4;
uint64_t т;
uint32_t с;
size_t I, J;
uint8_t bytesleft = 25% 4;
uint32_t zeromask = bytesleft? (0xffffffff << (Bytesleft * 8)): 0;
без знака zerocount = 0;
если (! b58sz) b58sz = StrLen (b58);
MemSet (Outi, 0, SizeOf (Outi));
/ * Нули, просто подсчитывать * /
для (я = 0; я < b58sz && b58u [я] == '1'; ++ я) ++ zerocount;
для (; я < b58sz; ++ я) {
если (b58u [я] & 0x80) возвращает -1; / * High-бит, установленные на неверной цифре * /
если (b58digits_map [b58u [I]] == -1) -2 возврата; / * Invalid base58 цифра * /
с = (без знака) b58digits_map [b58u [I]];
для (J = outisz; j--;) {
т = ((uint64_t) Outi [J]) * 58 + с;
с = (т & 0x3f00000000) >> 32;
Outi [J] = т & 0xffffffff;
}
если (с) возвращение -3; / * Номер выходного слишком большой (перенос на следующую int32) * /
если (Outi [0] & zeromask) -4 возврата; / * Выход номер слишком большой (последний int32 заполнены слишком далеко) * /
}
J = 0;
Переключатель (bytesleft) {
Случай 3: * (BINU ++) = (Outi [0] & 0xff0000) >> 16;
Случай 2: * (BINU ++) = (Outi [0] & 0xFF00) >> 8;
Случай 1: * (BINU ++) = (Outi [0] & 0xff); ++ J;
по умолчанию: разрыв;
}
для (, J < outisz; ++ J) {
* (BINU ++) = (Outi [J] >> 0x18) & 0xff;
* (BINU ++) = (Outi [J] >> 0x10) & 0xff;
* (BINU ++) = (Outi [J] >> 8) & 0xff;
* (BINU ++) = (Outi [J] >> 0) & 0xff;
}
BINU = бен; / * Количество канонического количества base58 байт * /
для (я = 0; я < 25; ++ я) {
если (BINU [я]) перерыв;
--* Binszp;
}
* Binszp + = zerocount;
}
если (addrbinsz = 25!) возвращение -5;
если (addrbin [0]! = 0 && addrbin [0] = 5) возврат -6!;
{
символ без знака d1 [SHA256_DIGEST_LENGTH], d2 [SHA256_DIGEST_LENGTH];
SHA256 (SHA256 (addrbin, 21, d1), SHA256_DIGEST_LENGTH, d2);
если (memcmp (addrbin + 21, d2, 4)) возвращение -7;
}
вернуть addrbin [0];
}
INT основных (INT ARGC, символ * ARGV []) {
Int я;
для (я = 1; я < ARGC; ++ я) {
BOOL действует = (validate_bitcoin_address (ARGV [I]) >= 0);
Е ( "% S есть% s \ п", ARGV [я], действует? "ДЕЙСТВУЕТ." : "ИНВАЛИД!");
}
возвращать 0;
}