Skip to content

Commit

Permalink
Merge pull request #76 from jibeee/master
Browse files Browse the repository at this point in the history
    Fixes for base 58 encoding and decoding
  • Loading branch information
BTChip github committed Nov 12, 2018
1 parent 992a2f4 commit 8866872
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 102 deletions.
11 changes: 7 additions & 4 deletions include/btchip_base58.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@

#define BTCHIP_BASE58_H

unsigned char btchip_decode_base58(unsigned char WIDE *in, unsigned char length,
unsigned char *out, unsigned char maxoutlen);
unsigned char btchip_encode_base58(unsigned char WIDE *in, unsigned char length,
unsigned char *out, unsigned char maxoutlen);
#include <stdlib.h>

int btchip_decode_base58(const char WIDE *in, size_t length,
unsigned char *out, size_t *outlen);

int btchip_encode_base58(const unsigned char WIDE *in, size_t length,
unsigned char *out, size_t *outlen);

#endif
203 changes: 107 additions & 96 deletions src/btchip_base58.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,107 +17,118 @@

#include "btchip_internal.h"

unsigned char btchip_decode_base58(unsigned char WIDE *in, unsigned char length,
unsigned char *out,
unsigned char maxoutlen) {
unsigned char tmp[164];
unsigned char buffer[164];
unsigned char i;
unsigned char j;
unsigned char startAt;
unsigned char zeroCount = 0;
if (length > sizeof(tmp)) {
THROW(INVALID_PARAMETER);
}
os_memmove(tmp, in, length);
L_DEBUG_BUF(("To decode\n", tmp, length));
for (i = 0; i < length; i++) {
if (in[i] > 128) {
THROW(EXCEPTION);
}
tmp[i] = BASE58TABLE[in[i]];
if (tmp[i] == 0xff) {
THROW(EXCEPTION);
}
}
while ((zeroCount < length) && (tmp[zeroCount] == 0)) {
++zeroCount;
#define MAX_DEC_INPUT_SIZE 164
#define MAX_ENC_INPUT_SIZE 120

int btchip_decode_base58(const char WIDE *in, size_t length,
unsigned char *out, size_t *outlen) {
unsigned char tmp[MAX_DEC_INPUT_SIZE];
unsigned char buffer[MAX_DEC_INPUT_SIZE] = {0};
unsigned char i;
unsigned char j;
unsigned char startAt;
unsigned char zeroCount = 0;
if (length > MAX_DEC_INPUT_SIZE) {
return -1;
}
os_memmove(tmp, in, length);
L_DEBUG_BUF(("To decode\n", tmp, length));
for (i = 0; i < length; i++) {
if (in[i] >= sizeof(BASE58TABLE)) {
return -1;
}
j = length;
startAt = zeroCount;
while (startAt < length) {
unsigned short remainder = 0;
unsigned char divLoop;
for (divLoop = startAt; divLoop < length; divLoop++) {
unsigned short digit256 = (unsigned short)(tmp[divLoop] & 0xff);
unsigned short tmpDiv = remainder * 58 + digit256;
tmp[divLoop] = (unsigned char)(tmpDiv / 256);
remainder = (tmpDiv % 256);
}
if (tmp[startAt] == 0) {
++startAt;
}
buffer[--j] = (unsigned char)remainder;
tmp[i] = BASE58TABLE[(int)in[i]];
if (tmp[i] == 0xff) {
return -1;
}
while ((j < length) && (buffer[j] == 0)) {
++j;
}
while ((zeroCount < length) && (tmp[zeroCount] == 0)) {
++zeroCount;
}
j = length;
startAt = zeroCount;
while (startAt < length) {
unsigned short remainder = 0;
unsigned char divLoop;
for (divLoop = startAt; divLoop < length; divLoop++) {
unsigned short digit256 = (unsigned short)(tmp[divLoop] & 0xff);
unsigned short tmpDiv = remainder * 58 + digit256;
tmp[divLoop] = (unsigned char)(tmpDiv / 256);
remainder = (tmpDiv % 256);
}
length = length - (j - zeroCount);
if (maxoutlen < length) {
L_DEBUG_APP(("Decode overflow %d %d\n", length, maxoutlen));
THROW(EXCEPTION_OVERFLOW);
if (tmp[startAt] == 0) {
++startAt;
}
os_memmove(out, buffer + j - zeroCount, length);
L_DEBUG_BUF(("Decoded\n", out, length));
return length;
buffer[--j] = (unsigned char)remainder;
}
while ((j < length) && (buffer[j] == 0)) {
++j;
}
length = length - (j - zeroCount);
if (*outlen < length) {
L_DEBUG_APP(("Decode overflow %d %d\n", length, *outlen));
return -1;
}

os_memmove(out, buffer + j - zeroCount, length);
L_DEBUG_BUF(("Decoded\n", out, length));
*outlen = length;
return 0;
}

unsigned char btchip_encode_base58(unsigned char WIDE *in, unsigned char length,
unsigned char *out,
unsigned char maxoutlen) {
unsigned char tmp[164];
unsigned char buffer[164];
unsigned char j;
unsigned char startAt;
unsigned char zeroCount = 0;
if (length > sizeof(tmp)) {
THROW(INVALID_PARAMETER);
}
os_memmove(tmp, in, length);
L_DEBUG_APP(("Length to encode %d\n", length));
L_DEBUG_BUF(("To encode\n", tmp, length));
while ((zeroCount < length) && (tmp[zeroCount] == 0)) {
++zeroCount;
}
j = 2 * length;
startAt = zeroCount;
while (startAt < length) {
unsigned short remainder = 0;
unsigned char divLoop;
for (divLoop = startAt; divLoop < length; divLoop++) {
unsigned short digit256 = (unsigned short)(tmp[divLoop] & 0xff);
unsigned short tmpDiv = remainder * 256 + digit256;
tmp[divLoop] = (unsigned char)(tmpDiv / 58);
remainder = (tmpDiv % 58);
}
if (tmp[startAt] == 0) {
++startAt;
}
buffer[--j] = (unsigned char)BASE58ALPHABET[remainder];
}
while ((j < (2 * length)) && (buffer[j] == BASE58ALPHABET[0])) {
++j;
}
while (zeroCount-- > 0) {
buffer[--j] = BASE58ALPHABET[0];
}
length = 2 * length - j;
if (maxoutlen < length) {
L_DEBUG_APP(("Encode overflow %d %d\n", length, maxoutlen));
THROW(EXCEPTION_OVERFLOW);
int btchip_encode_base58(const unsigned char WIDE *in, size_t length,
unsigned char *out, size_t *outlen) {
unsigned char buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0};
size_t i = 0, j;
size_t startAt, stopAt;
size_t zeroCount = 0;
size_t outputSize;

if (length > MAX_ENC_INPUT_SIZE) {
return -1;
}

L_DEBUG_APP(("Length to encode %d\n", length));
L_DEBUG_BUF(("To encode\n", in, length));

while ((zeroCount < length) && (in[zeroCount] == 0)) {
++zeroCount;
}

outputSize = (length - zeroCount) * 138 / 100 + 1;
stopAt = outputSize - 1;
for (startAt = zeroCount; startAt < length; startAt++) {
int carry = in[startAt];
for (j = outputSize - 1; (int)j >= 0; j--) {
carry += 256 * buffer[j];
buffer[j] = carry % 58;
carry /= 58;

if (j < stopAt - 1 && carry == 0) {
break;
}
}
os_memmove(out, (buffer + j), length);
L_DEBUG_APP(("Length encoded %d\n", length));
L_DEBUG_BUF(("Encoded\n", out, length));
return length;
stopAt = j;
}

j = 0;
while (j < outputSize && buffer[j] == 0) {
j += 1;
}

if (*outlen < zeroCount + outputSize - j) {
*outlen = zeroCount + outputSize - j;
return -1;
}

os_memset(out, BASE58ALPHABET[0], zeroCount);

i = zeroCount;
while (j < outputSize) {
out[i++] = BASE58ALPHABET[buffer[j++]];
}
*outlen = i;
L_DEBUG_APP(("Length encoded %d\n", i));
L_DEBUG_BUF(("Encoded\n", out, i));
return 0;
}
14 changes: 12 additions & 2 deletions src/btchip_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ unsigned short btchip_public_key_to_encoded_base58(
unsigned char checksumBuffer[32];
cx_sha256_t hash;
unsigned char versionSize = (version > 255 ? 2 : 1);
size_t outputLen;

if (!alreadyHashed) {
L_DEBUG_BUF(("To hash\n", in, inlen));
Expand All @@ -258,7 +259,12 @@ unsigned short btchip_public_key_to_encoded_base58(

L_DEBUG_BUF(("Checksum\n", checksumBuffer, 4));
os_memmove(tmpBuffer + 20 + versionSize, checksumBuffer, 4);
return btchip_encode_base58(tmpBuffer, 24 + versionSize, out, outlen);

outputLen = outlen;
if (btchip_encode_base58(tmpBuffer, 24 + versionSize, out, &outputLen) < 0) {
THROW(EXCEPTION);
}
return outputLen;
}

void btchip_swap_bytes(unsigned char *target, unsigned char *source,
Expand All @@ -275,7 +281,11 @@ unsigned short btchip_decode_base58_address(unsigned char WIDE *in,
unsigned short outlen) {
unsigned char hashBuffer[32];
cx_sha256_t hash;
outlen = btchip_decode_base58(in, inlen, out, outlen);
size_t outputLen = outlen;
if (btchip_decode_base58((char *)in, inlen, out, &outputLen) < 0) {
THROW(EXCEPTION);
}
outlen = outputLen;

// Compute hash to verify address
cx_sha256_init(&hash);
Expand Down

0 comments on commit 8866872

Please sign in to comment.