Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1dd03fa8d | ||
|
|
f4ef2ae23b | ||
|
|
66526fb70f | ||
|
|
c821364d6e | ||
|
|
d759139844 | ||
|
|
f0e2b756cd | ||
|
|
1c9930a246 | ||
|
|
afa117ae92 | ||
|
|
9cd68e803e | ||
|
|
4aaeea028c | ||
|
|
ccb7b43e9b | ||
|
|
cca7f63c6c | ||
|
|
6b23367527 | ||
|
|
48fdd386d2 | ||
|
|
1cb26b5bff | ||
|
|
bee00a6e88 | ||
|
|
a861d3c57f | ||
|
|
5df7d3b19a | ||
|
|
e77d2999fe | ||
|
|
8a92496475 | ||
|
|
ae5fe61864 | ||
|
|
e28341c60e | ||
|
|
16c2527608 | ||
|
|
bca0d4bebd | ||
|
|
cdeed0709e | ||
|
|
13dfa66514 |
48
.travis.yml
Normal file
48
.travis.yml
Normal file
@ -0,0 +1,48 @@
|
||||
os: linux
|
||||
language: c
|
||||
compiler: gcc
|
||||
sudo: false
|
||||
matrix:
|
||||
include:
|
||||
- compiler: ": Complete"
|
||||
env: CONFIGURE_OPTS="--enable-tool --enable-static --enable-shared" MAKE_CHECK=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- libgcrypt11-dev
|
||||
- compiler: ": No tool/tests"
|
||||
env: CONFIGURE_OPTS="--disable-tool --enable-static --enable-shared"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- compiler: ": Win32 - No tool/tests"
|
||||
env: CONFIGURE_OPTS="--disable-tool --host=i686-w64-mingw32 --enable-static --enable-shared"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-mingw-w64-i686
|
||||
- binutils-mingw-w64-i686
|
||||
- mingw-w64-i686-dev
|
||||
- compiler: ": Win64 - No tool/tests"
|
||||
env: CONFIGURE_OPTS="--disable-tool --host=x86_64-w64-mingw32 --enable-static --enable-shared"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-mingw-w64-x86-64
|
||||
- binutils-mingw-w64-x86-64
|
||||
- mingw-w64-x86-64-dev
|
||||
exclude:
|
||||
- compiler: gcc
|
||||
install:
|
||||
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi
|
||||
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi
|
||||
script:
|
||||
- unset CC
|
||||
- ./autogen.sh
|
||||
- ./configure $CONFIGURE_OPTS || tail -n 1000 config.log
|
||||
- make
|
||||
- test -z "$MAKE_CHECK" || make check
|
||||
- make install DESTDIR=$PWD/ii
|
||||
- cd ii && find
|
||||
20
INSTALL
Normal file
20
INSTALL
Normal file
@ -0,0 +1,20 @@
|
||||
Installation
|
||||
--------------------
|
||||
# Install libgcrypt first, e.g. via `brew install libgcrypt` on OS X or libgcrypt-dev on Linux
|
||||
# Generate the final build scripts
|
||||
./autogen.sh
|
||||
# Build the CLI and library
|
||||
./configure && make
|
||||
|
||||
Dependencies
|
||||
--------------------
|
||||
Many of the test scripts depend on the "xxd" tool to convert between hexadecimal and binary.
|
||||
If this tool is not installed on your Operating System, you can probably get it as part of
|
||||
the "vim" editor from https://www.vim.org/ or by installing the vim-share package.
|
||||
|
||||
Troubleshooting
|
||||
--------------------
|
||||
If libgcrypt isn't found after install, set AM_PATH_LIBGCRYPT env var to libgcrypt path
|
||||
prior to running autogen.sh. For example, on OS X with ver 1.7.6:
|
||||
|
||||
export AM_PATH_LIBGCRYPT="/usr/local/Cellar/libgcrypt/1.7.6/lib"
|
||||
@ -14,7 +14,7 @@ pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libbase58.pc
|
||||
|
||||
dist_noinst_SCRIPTS = autogen.sh
|
||||
dist_doc_DATA = AUTHORS COPYING README
|
||||
dist_doc_DATA = AUTHORS COPYING INSTALL README.md
|
||||
|
||||
if USE_TOOL
|
||||
bin_PROGRAMS = base58
|
||||
@ -33,10 +33,12 @@ TESTS = \
|
||||
tests/decode-zero.sh \
|
||||
tests/encode.sh \
|
||||
tests/encode-b58c.sh \
|
||||
tests/encode-b58c-high.sh \
|
||||
tests/encode-fail.sh \
|
||||
tests/encode-neg-index.sh \
|
||||
tests/encode-small.sh
|
||||
SH_LOG_COMPILER = /bin/sh
|
||||
AM_TESTS_ENVIRONMENT = PATH='$(srcdir)':"$$PATH"; export PATH;
|
||||
AM_TESTS_ENVIRONMENT = PATH='$(abs_top_builddir)':"$$PATH"; export PATH;
|
||||
TESTS_ENVIRONMENT = $(AM_TESTS_ENVIRONMENT)
|
||||
endif
|
||||
TEST_EXTENSIONS = .sh
|
||||
|
||||
@ -3,8 +3,11 @@ Initialisation
|
||||
|
||||
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.
|
||||
@ -15,7 +18,9 @@ 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.
|
||||
@ -28,7 +33,9 @@ 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.
|
||||
@ -39,7 +46,9 @@ 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
|
||||
@ -50,7 +59,8 @@ return false. Otherwise, it returns true to indicate success.
|
||||
Encoding Base58Check
|
||||
--------------------
|
||||
|
||||
Targetting base58check is done similarly to raw base58 encoding, but you must
|
||||
Targeting 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)
|
||||
58
base58.c
58
base58.c
@ -15,7 +15,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "libbase58.h"
|
||||
|
||||
@ -32,27 +31,34 @@ static const int8_t b58digits_map[] = {
|
||||
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
|
||||
};
|
||||
|
||||
typedef uint64_t b58_maxint_t;
|
||||
typedef uint32_t b58_almostmaxint_t;
|
||||
#define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8)
|
||||
static const b58_almostmaxint_t b58_almostmaxint_mask = ((((b58_maxint_t)1) << b58_almostmaxint_bits) - 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 outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t);
|
||||
b58_almostmaxint_t outi[outisz];
|
||||
b58_maxint_t t;
|
||||
b58_almostmaxint_t c;
|
||||
size_t i, j;
|
||||
uint8_t bytesleft = binsz % 4;
|
||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
||||
uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t);
|
||||
b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
|
||||
if (!b58sz)
|
||||
b58sz = strlen(b58);
|
||||
|
||||
memset(outi, 0, outisz * sizeof(*outi));
|
||||
for (i = 0; i < outisz; ++i) {
|
||||
outi[i] = 0;
|
||||
}
|
||||
|
||||
// Leading zeros, just count
|
||||
for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i)
|
||||
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
|
||||
++zerocount;
|
||||
|
||||
for ( ; i < b58sz; ++i)
|
||||
@ -66,9 +72,9 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
|
||||
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;
|
||||
t = ((b58_maxint_t)outi[j]) * 58 + c;
|
||||
c = t >> b58_almostmaxint_bits;
|
||||
outi[j] = t & b58_almostmaxint_mask;
|
||||
}
|
||||
if (c)
|
||||
// Output number too big (carry to the next int32)
|
||||
@ -79,24 +85,18 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
|
||||
}
|
||||
|
||||
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;
|
||||
if (bytesleft) {
|
||||
for (i = bytesleft; i > 0; --i) {
|
||||
*(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
|
||||
for (; j < outisz; ++j)
|
||||
{
|
||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
||||
for (i = sizeof(*outi); i > 0; --i) {
|
||||
*(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
// Count canonical base58 byte count
|
||||
@ -146,7 +146,7 @@ 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 i, j, high, zcount = 0;
|
||||
size_t size;
|
||||
|
||||
while (zcount < binsz && !bin[zcount])
|
||||
@ -163,6 +163,10 @@ bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
if (!j) {
|
||||
// Otherwise j wraps to maxint which is > high
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ dnl * under the terms of the standard MIT license. See COPYING for more details
|
||||
|
||||
AC_INIT(
|
||||
[libbase58],
|
||||
[0.1.3],
|
||||
[0.1.4],
|
||||
[luke_libbase58@dashjr.org],
|
||||
[libbase58])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
@ -18,7 +18,7 @@ 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:1:0])
|
||||
AC_SUBST([LIBBASE58_SO_VERSION], [0:2:0])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
libbase58.pc:libbase58.pc.in
|
||||
|
||||
3
tests/decode-highbit-prefix.sh
Normal file
3
tests/decode-highbit-prefix.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
hex=$(echo 993233 | xxd -r -p | base58 -d 25 || echo FAIL)
|
||||
test "x${hex}" = "xFAIL"
|
||||
3
tests/decode-highbit.sh
Normal file
3
tests/decode-highbit.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
hex=$(echo 319932 | xxd -r -p | base58 -d 25 || echo FAIL)
|
||||
test "x${hex}" = "xFAIL"
|
||||
3
tests/encode-b58c-high.sh
Executable file
3
tests/encode-b58c-high.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
b58=$(echo 'ff5a1fc5dd9e6f03819fca94a2d89669469667f9a0' | xxd -r -p | base58 -c)
|
||||
test x$b58 = x2mkQLxaN3Y4CwN5E9rdMWNgsXX7VS6UnfeT
|
||||
4
tests/encode-neg-index.sh
Executable file
4
tests/encode-neg-index.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# This input causes the loop iteration counter to go negative
|
||||
b58=$(echo '00CEF022FA' | xxd -r -p | base58)
|
||||
test x$b58 = x16Ho7Hs
|
||||
Loading…
Reference in New Issue
Block a user