pax_global_header00006660000000000000000000000064125342141050014507gustar00rootroot0000000000000052 comment=16c2527608053d2cc2fa05b2e3b5ae96065d1410 libbase58-0.1.4/000077500000000000000000000000001253421410500132675ustar00rootroot00000000000000libbase58-0.1.4/.gitignore000066400000000000000000000003071253421410500152570ustar00rootroot00000000000000*~ *.pc *.la *.o libtool ltmain.sh missing install-sh depcomp configure config.* *.lo autom4te.cache ar-lib test-driver aclocal.m4 Makefile Makefile.in .deps *.log .libs ii *.tar* base58 tests/*.trs libbase58-0.1.4/AUTHORS000066400000000000000000000001101253421410500143270ustar00rootroot00000000000000Luke Dashjr Huang Le <4tarhl@gmail.com> libbase58-0.1.4/COPYING000066400000000000000000000020371253421410500143240ustar00rootroot00000000000000Copyright (c) 2014 Luke Dashjr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libbase58-0.1.4/Makefile.am000066400000000000000000000022101253421410500153160ustar00rootroot00000000000000# Copyright 2014 Luke Dashjr # # This program is free software; you can redistribute it and/or modify it # under the terms of the standard MIT license. See COPYING for more details. lib_LTLIBRARIES = libbase58.la libbase58_la_SOURCES = base58.c libbase58_la_LDFLAGS = -version-info $(LIBBASE58_SO_VERSION) -no-undefined libbase58_includedir = $(includedir) libbase58_include_HEADERS = libbase58.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libbase58.pc dist_noinst_SCRIPTS = autogen.sh dist_doc_DATA = AUTHORS COPYING README if USE_TOOL bin_PROGRAMS = base58 base58_SOURCES = clitool.c base58_CFLAGS = $(LIBGCRYPT_CFLAGS) base58_LDADD = libbase58.la $(LIBGCRYPT_LIBS) TESTS = \ tests/decode.sh \ tests/decode-b58c.sh \ tests/decode-b58c-fail.sh \ tests/decode-b58c-null.sh \ tests/decode-b58c-toolong.sh \ tests/decode-b58c-tooshort.sh \ tests/decode-small.sh \ tests/decode-zero.sh \ tests/encode.sh \ tests/encode-b58c.sh \ tests/encode-fail.sh \ tests/encode-small.sh SH_LOG_COMPILER = /bin/sh AM_TESTS_ENVIRONMENT = PATH='$(srcdir)':"$$PATH"; export PATH; TESTS_ENVIRONMENT = $(AM_TESTS_ENVIRONMENT) endif TEST_EXTENSIONS = .sh libbase58-0.1.4/README000066400000000000000000000042601253421410500141510ustar00rootroot00000000000000Initialisation -------------- Before you can use libbase58 for base58check, you must provide a SHA256 function. The required function signature is: bool my_sha256(void *digest, const void *data, size_t datasz) Simply assign your function to b58_sha256_impl: b58_sha256_impl = my_sha256; This is only required if base58check is used. Raw base58 does not need SHA256. Decoding Base58 --------------- Simply allocate a buffer to store the binary data in, and set a variable with the buffer size, and call the b58tobin function: bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz) The "canonical" base58 byte length will be assigned to binsz on success, which may be larger than the actual buffer if the input has many leading zeros. Regardless of the canonical byte length, the full binary buffer will be used. If b58sz is zero, it will be initialised with strlen(b58); note that a true zero-length base58 string is not supported here. Validating Base58Check ---------------------- After calling b58tobin, you can validate base58check data using the b58check function: int b58check(const void *bin, size_t binsz, const char *b58, size_t b58sz) Call it with the same buffers used for b58tobin. If the return value is negative, an error occurred. Otherwise, the return value is the base58check "version" byte from the decoded data. Encoding Base58 --------------- Allocate a string to store the base58 content, create a size_t variable with the size of that allocation, and call: bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) Note that you must pass a pointer to the string size variable, not the size itself. When b58enc returns, the variable will be modified to contain the actual number of bytes used (including the null terminator). If encoding fails for any reason, or if the string buffer is not large enough for the result, b58enc will return false. Otherwise, it returns true to indicate success. Encoding Base58Check -------------------- Targetting base58check is done similarly to raw base58 encoding, but you must also provide a version byte: bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz) libbase58-0.1.4/autogen.sh000077500000000000000000000004701253421410500152710ustar00rootroot00000000000000#!/bin/sh -e # Written by Luke Dashjr in 2012 # This program is released under the terms of the Creative Commons "CC0 1.0 Universal" license and/or copyright waiver. if test -z "$srcdir"; then srcdir=`dirname "$0"` if test -z "$srcdir"; then srcdir=. fi fi autoreconf --force --install --verbose "$srcdir" libbase58-0.1.4/base58.c000066400000000000000000000110661253421410500145260ustar00rootroot00000000000000/* * Copyright 2012-2014 Luke Dashjr * * This program is free software; you can redistribute it and/or modify it * under the terms of the standard MIT license. See COPYING for more details. */ #ifndef WIN32 #include #else #include #endif #include #include #include #include #include #include "libbase58.h" bool (*b58_sha256_impl)(void *, const void *, size_t) = NULL; static 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, }; bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) { size_t binsz = *binszp; const unsigned char *b58u = (void*)b58; unsigned char *binu = bin; size_t outisz = (binsz + 3) / 4; uint32_t outi[outisz]; uint64_t t; uint32_t c; size_t i, j; uint8_t bytesleft = binsz % 4; uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; unsigned zerocount = 0; if (!b58sz) b58sz = strlen(b58); memset(outi, 0, outisz * sizeof(*outi)); // Leading zeros, just count for (i = 0; i < b58sz && b58u[i] == '1'; ++i) ++zerocount; for ( ; i < b58sz; ++i) { if (b58u[i] & 0x80) // High-bit set on invalid digit return false; if (b58digits_map[b58u[i]] == -1) // Invalid base58 digit return false; c = (unsigned)b58digits_map[b58u[i]]; for (j = outisz; j--; ) { t = ((uint64_t)outi[j]) * 58 + c; c = (t & 0x3f00000000) >> 32; outi[j] = t & 0xffffffff; } if (c) // Output number too big (carry to the next int32) return false; if (outi[0] & zeromask) // Output number too big (last int32 filled too far) return false; } j = 0; switch (bytesleft) { case 3: *(binu++) = (outi[0] & 0xff0000) >> 16; case 2: *(binu++) = (outi[0] & 0xff00) >> 8; case 1: *(binu++) = (outi[0] & 0xff); ++j; default: break; } for (; j < outisz; ++j) { *(binu++) = (outi[j] >> 0x18) & 0xff; *(binu++) = (outi[j] >> 0x10) & 0xff; *(binu++) = (outi[j] >> 8) & 0xff; *(binu++) = (outi[j] >> 0) & 0xff; } // Count canonical base58 byte count binu = bin; for (i = 0; i < binsz; ++i) { if (binu[i]) break; --*binszp; } *binszp += zerocount; return true; } static bool my_dblsha256(void *hash, const void *data, size_t datasz) { uint8_t buf[0x20]; return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf)); } int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) { unsigned char buf[32]; const uint8_t *binc = bin; unsigned i; if (binsz < 4) return -4; if (!my_dblsha256(buf, bin, binsz - 4)) return -2; if (memcmp(&binc[binsz - 4], buf, 4)) return -1; // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) {} // Just finding the end of zeros, nothing to do in loop if (binc[i] == '\0' || base58str[i] == '1') return -3; return binc[0]; } static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) { const uint8_t *bin = data; int carry; ssize_t i, j, high, zcount = 0; size_t size; while (zcount < binsz && !bin[zcount]) ++zcount; size = (binsz - zcount) * 138 / 100 + 1; uint8_t buf[size]; memset(buf, 0, size); for (i = zcount, high = size - 1; i < binsz; ++i, high = j) { for (carry = bin[i], j = size - 1; (j > high) || carry; --j) { carry += 256 * buf[j]; buf[j] = carry % 58; carry /= 58; } } for (j = 0; j < size && !buf[j]; ++j); if (*b58sz <= zcount + size - j) { *b58sz = zcount + size - j + 1; return false; } if (zcount) memset(b58, '1', zcount); for (i = zcount; j < size; ++i, ++j) b58[i] = b58digits_ordered[buf[j]]; b58[i] = '\0'; *b58sz = i + 1; return true; } bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz) { uint8_t buf[1 + datasz + 0x20]; uint8_t *hash = &buf[1 + datasz]; buf[0] = ver; memcpy(&buf[1], data, datasz); if (!my_dblsha256(hash, buf, datasz + 1)) { *b58c_sz = 0; return false; } return b58enc(b58c, b58c_sz, buf, 1 + datasz + 4); } libbase58-0.1.4/clitool.c000066400000000000000000000044201253421410500151000ustar00rootroot00000000000000/* * Copyright 2014 Luke Dashjr * * This program is free software; you can redistribute it and/or modify it * under the terms of the standard MIT license. See COPYING for more details. */ #include #include #include #include #include #include #include #include #include "libbase58.h" static bool my_sha256(void *digest, const void *data, size_t datasz) { gcry_md_hash_buffer(GCRY_MD_SHA256, digest, data, datasz); return true; } static void usage(const char *prog) { fprintf(stderr, "Usage: %s [-c] [-d] [data]\n", prog); fprintf(stderr, "\t-c Use base58check (default: raw base58)\n"); fprintf(stderr, "\t-d Decode bytes\n"); exit(1); } int main(int argc, char **argv) { bool b58c = false; size_t decode = 0; int opt; while ( (opt = getopt(argc, argv, "cd:h")) != -1) { switch (opt) { case 'c': b58c = true; b58_sha256_impl = my_sha256; break; case 'd': { int i = atoi(optarg); if (i < 0 || (uintmax_t)i >= SIZE_MAX) usage(argv[0]); decode = (size_t)i; break; } default: usage(argv[0]); } } size_t rt; union { uint8_t *b; char *s; } r; if (optind >= argc) { rt = 0; r.b = NULL; while (!feof(stdin)) { r.b = realloc(r.b, rt + 0x100); rt += fread(&r.b[rt], 1, 0x100, stdin); } if (decode) while (isspace(r.s[rt-1])) --rt; } else { r.s = argv[optind]; rt = strlen(argv[optind]); } if (decode) { uint8_t bin[decode]; size_t ssz = decode; if (!b58tobin(bin, &ssz, r.s, rt)) return 2; if (b58c) { int chk = b58check(bin, decode, r.s, rt); if (chk < 0) return chk; if (fwrite(bin, decode, 1, stdout) != 1) return 3; } else { // Raw base58 doesn't check length match uint8_t cbin[ssz]; if (ssz > decode) { size_t zeros = ssz - decode; memset(cbin, 0, zeros); memcpy(&cbin[zeros], bin, decode); } else memcpy(cbin, &bin[decode - ssz], ssz); if (fwrite(cbin, ssz, 1, stdout) != 1) return 3; } } else { size_t ssz = rt * 2; char s[ssz]; bool rv; if (b58c) rv = rt && b58check_enc(s, &ssz, r.b[0], &r.b[1], rt-1); else rv = b58enc(s, &ssz, r.b, rt); if (!rv) return 2; puts(s); } } libbase58-0.1.4/configure.ac000066400000000000000000000023471253421410500155630ustar00rootroot00000000000000dnl * Copyright 2012-2014 Luke Dashjr dnl * dnl * This program is free software; you can redistribute it and/or modify it dnl * under the terms of the standard MIT license. See COPYING for more details. AC_INIT( [libbase58], [0.1.4], [luke_libbase58@dashjr.org], [libbase58]) AC_CONFIG_AUX_DIR([.]) AC_PREREQ([2.59]) AM_INIT_AUTOMAKE([1.11 -Wall dist-xz foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_PROG_CC_C99 m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) LT_INIT([]) # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html AC_SUBST([LIBBASE58_SO_VERSION], [0:2:0]) AC_CONFIG_FILES([Makefile libbase58.pc:libbase58.pc.in ]) AC_CHECK_LIB([ws2_32], [strchr]) m4_ifdef([AM_PATH_LIBGCRYPT], [ AC_ARG_ENABLE([tool], [AC_HELP_STRING([--disable-tool],[Compile command line base58 tool (default enabled)])], [use_tool=$enableval], [use_tool=auto]) if test x$use_tool != xno; then AM_PATH_LIBGCRYPT([],[ use_tool=yes ],[ if test x$use_tool = xyes; then AC_MSG_ERROR([libgcrypt not found; use --disable-tool]) fi use_tool=no ]) fi ],[ m4_warn([syntax], [AM_PATH_LIBGCRYPT missing; CLI tool will not be available]) ]) AM_CONDITIONAL([USE_TOOL], [test x$use_tool = xyes]) AC_OUTPUT libbase58-0.1.4/libbase58.h000066400000000000000000000010641253421410500152170ustar00rootroot00000000000000#ifndef LIBBASE58_H #define LIBBASE58_H #include #include #ifdef __cplusplus extern "C" { #endif extern bool (*b58_sha256_impl)(void *, const void *, size_t); extern bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz); extern int b58check(const void *bin, size_t binsz, const char *b58, size_t b58sz); extern bool b58enc(char *b58, size_t *b58sz, const void *bin, size_t binsz); extern bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz); #ifdef __cplusplus } #endif #endif libbase58-0.1.4/libbase58.pc.in000066400000000000000000000003521253421410500157760ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: @PACKAGE_NAME@ Description: Library for Bitcoin's base58 encoding. Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lbase58 Cflags: -I${includedir} libbase58-0.1.4/tests/000077500000000000000000000000001253421410500144315ustar00rootroot00000000000000libbase58-0.1.4/tests/decode-b58c-fail.sh000077500000000000000000000001111253421410500176540ustar00rootroot00000000000000#!/bin/sh ! base58 -d 25 -c 19DXstMaV43WpYg4ceREiiTv2UntmoiA9a >/dev/nulllibbase58-0.1.4/tests/decode-b58c-null.sh000077500000000000000000000001341253421410500177200ustar00rootroot00000000000000#!/bin/sh hex=$(base58 -d 25 -c 19DXstMaV43WpYg4ceREiiTv2UntmoiA9a | xxd -p) test x$hex = x libbase58-0.1.4/tests/decode-b58c-toolong.sh000077500000000000000000000001141253421410500204250ustar00rootroot00000000000000#!/bin/sh ! base58 -d 25 -c 1119DXstMaV43WpYg4ceREiiTv2UntmoiA9a >/dev/null libbase58-0.1.4/tests/decode-b58c-tooshort.sh000077500000000000000000000001021253421410500206220ustar00rootroot00000000000000#!/bin/sh ! base58 -d 25 -c 111111111111111111114oLvT2 >/dev/null libbase58-0.1.4/tests/decode-b58c.sh000077500000000000000000000002071253421410500167510ustar00rootroot00000000000000#!/bin/sh hex=$(base58 -d 25 -c 19DXstMaV43WpYg4ceREiiTv2UntmoiA9j | xxd -p) test x$hex != x005a1fc5dd9e6f03819fca94a2d89669469667f9a1 libbase58-0.1.4/tests/decode-highbit-prefix.sh000066400000000000000000000001361253421410500211170ustar00rootroot00000000000000#!/bin/sh hex=$(echo 993233 | xxd -r -p | base58 -d 25 || echo FAIL) test "x${hex}" = "xFAIL" libbase58-0.1.4/tests/decode-highbit.sh000066400000000000000000000001361253421410500176240ustar00rootroot00000000000000#!/bin/sh hex=$(echo 319932 | xxd -r -p | base58 -d 25 || echo FAIL) test "x${hex}" = "xFAIL" libbase58-0.1.4/tests/decode-small.sh000077500000000000000000000000711253421410500173170ustar00rootroot00000000000000#!/bin/sh hex=$(base58 -d 4 2 | xxd -p) test x$hex = x01 libbase58-0.1.4/tests/decode-zero.sh000077500000000000000000000001111253421410500171610ustar00rootroot00000000000000#!/bin/sh hex=$(base58 -d 25 111111 | xxd -p) test x$hex = x000000000000 libbase58-0.1.4/tests/decode.sh000077500000000000000000000002131253421410500162070ustar00rootroot00000000000000#!/bin/sh hex=$(base58 -d 50 19DXstMaV43WpYg4ceREiiTv2UntmoiA9j | xxd -p) test x$hex = x005a1fc5dd9e6f03819fca94a2d89669469667f9a074655946 libbase58-0.1.4/tests/encode-b58c.sh000077500000000000000000000002141253421410500167610ustar00rootroot00000000000000#!/bin/sh b58=$(echo '005a1fc5dd9e6f03819fca94a2d89669469667f9a0' | xxd -r -p | base58 -c) test x$b58 = x19DXstMaV43WpYg4ceREiiTv2UntmoiA9j libbase58-0.1.4/tests/encode-fail.sh000077500000000000000000000002221253421410500171320ustar00rootroot00000000000000#!/bin/sh b58=$(echo '005a1fc5dd9e6f03819fca94a2d89669469667f9a174655946' | xxd -r -p | base58) test x$b58 != x19DXstMaV43WpYg4ceREiiTv2UntmoiA9j libbase58-0.1.4/tests/encode-small.sh000077500000000000000000000000521253421410500173300ustar00rootroot00000000000000#!/bin/sh b58=$(base58 1) test x$b58 = xr libbase58-0.1.4/tests/encode.sh000077500000000000000000000002211253421410500162200ustar00rootroot00000000000000#!/bin/sh b58=$(echo '005a1fc5dd9e6f03819fca94a2d89669469667f9a074655946' | xxd -r -p | base58) test x$b58 = x19DXstMaV43WpYg4ceREiiTv2UntmoiA9j