libbtc
bitcoinclibrary
Functions | Variables
base58.c File Reference
#include "btc/base58.h"
#include <string.h>
#include <sys/types.h>
#include "sha2.h"

Go to the source code of this file.

Functions

int btc_base58_decode (void *bin, size_t *binszp, const char *b58)
 
int btc_b58check (const void *bin, size_t binsz, const char *base58str)
 
int btc_base58_encode (char *b58, size_t *b58sz, const void *data, size_t binsz)
 
int btc_base58_encode_check (const uint8_t *data, int datalen, char *str, int strsize)
 
int btc_base58_decode_check (const char *str, uint8_t *data, size_t datalen)
 

Variables

static const int8_t b58digits_map []
 
static const char b58digits_ordered []
 

Function Documentation

int btc_b58check ( const void *  bin,
size_t  binsz,
const char *  base58str 
)

Definition at line 127 of file base58.c.

References sha256_Raw().

Referenced by btc_base58_decode_check().

128 {
129  unsigned char buf[32];
130  const uint8_t *binc = bin;
131  unsigned i;
132  if (binsz < 4) {
133  return -4;
134  }
135  sha256_Raw(bin, binsz - 4, buf);
136  sha256_Raw(buf, 32, buf);
137  if (memcmp(&binc[binsz - 4], buf, 4)) {
138  return -1;
139  }
140 
141  // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
142  for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) {
143  } // Just finding the end of zeros, nothing to do in loop
144  if (binc[i] == '\0' || base58str[i] == '1') {
145  return -3;
146  }
147 
148  return binc[0];
149 }
void sha256_Raw(const sha2_byte *data, size_t len, uint8_t digest[SHA256_DIGEST_LENGTH])
Definition: sha2.c:652
int btc_base58_decode ( void *  bin,
size_t *  binszp,
const char *  b58 
)

Definition at line 42 of file base58.c.

References b58digits_map.

Referenced by btc_base58_decode_check().

43 {
44  size_t binsz = *binszp;
45  const unsigned char *b58u = (const void *)b58;
46  unsigned char *binu = bin;
47  size_t outisz = (binsz + 3) / 4;
48  uint32_t outi[outisz];
49  uint64_t t;
50  uint32_t c;
51  size_t i, j;
52  uint8_t bytesleft = binsz % 4;
53  uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
54  unsigned zerocount = 0;
55  size_t b58sz;
56 
57  b58sz = strlen(b58);
58 
59  memset(outi, 0, outisz * sizeof(*outi));
60 
61  // Leading zeros, just count
62  for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) {
63  ++zerocount;
64  }
65 
66  for ( ; i < b58sz; ++i) {
67  if (b58u[i] & 0x80) {
68  // High-bit set on invalid digit
69  return false;
70  }
71  if (b58digits_map[b58u[i]] == -1) {
72  // Invalid base58 digit
73  return false;
74  }
75  c = (unsigned)b58digits_map[b58u[i]];
76  for (j = outisz; j--; ) {
77  t = ((uint64_t)outi[j]) * 58 + c;
78  c = (t & 0x3f00000000) >> 32;
79  outi[j] = t & 0xffffffff;
80  }
81  if (c) {
82  // Output number too big (carry to the next int32)
83  memset(outi, 0, outisz * sizeof(*outi));
84  return false;
85  }
86  if (outi[0] & zeromask) {
87  // Output number too big (last int32 filled too far)
88  memset(outi, 0, outisz * sizeof(*outi));
89  return false;
90  }
91  }
92 
93  j = 0;
94  switch (bytesleft) {
95  case 3:
96  *(binu++) = (outi[0] & 0xff0000) >> 16;
97  case 2:
98  *(binu++) = (outi[0] & 0xff00) >> 8;
99  case 1:
100  *(binu++) = (outi[0] & 0xff);
101  ++j;
102  default:
103  break;
104  }
105 
106  for (; j < outisz; ++j) {
107  *(binu++) = (outi[j] >> 0x18) & 0xff;
108  *(binu++) = (outi[j] >> 0x10) & 0xff;
109  *(binu++) = (outi[j] >> 8) & 0xff;
110  *(binu++) = (outi[j] >> 0) & 0xff;
111  }
112 
113  // Count canonical base58 byte count
114  binu = bin;
115  for (i = 0; i < binsz; ++i) {
116  if (binu[i]) {
117  break;
118  }
119  --*binszp;
120  }
121  *binszp += zerocount;
122 
123  memset(outi, 0, outisz * sizeof(*outi));
124  return true;
125 }
static const int8_t b58digits_map[]
Definition: base58.c:31
int btc_base58_decode_check ( const char *  str,
uint8_t *  data,
size_t  datalen 
)

Definition at line 219 of file base58.c.

References btc_b58check(), and btc_base58_decode().

Referenced by btc_hdnode_deserialize(), and btc_tx_add_address_out().

220 {
221  int ret;
222  size_t strl = strlen(str);
223 
224  /* buffer needs to be at least the strsize, will be used
225  for the whole decoding */
226  if (strl > 128 || datalen < strl) {
227  return 0;
228  }
229 
230  size_t binsize = strl;
231  if (btc_base58_decode(data, &binsize, str) != true) {
232  ret = 0;
233  }
234 
235  memmove(data, data+strl-binsize, binsize);
236  memset(data+binsize, 0, datalen-binsize);
237 
238  if (btc_b58check(data, binsize, str) < 0) {
239  ret = 0;
240  } else {
241  ret = binsize;
242  }
243  return ret;
244 }
int btc_base58_decode(void *bin, size_t *binszp, const char *b58)
Definition: base58.c:42
int btc_b58check(const void *bin, size_t binsz, const char *base58str)
Definition: base58.c:127
int btc_base58_encode ( char *  b58,
size_t *  b58sz,
const void *  data,
size_t  binsz 
)

Definition at line 154 of file base58.c.

References b58digits_ordered.

Referenced by btc_base58_encode_check().

155 {
156  const uint8_t *bin = data;
157  int carry;
158  ssize_t i, j, high, zcount = 0;
159  size_t size;
160 
161  while (zcount < (ssize_t)binsz && !bin[zcount]) {
162  ++zcount;
163  }
164 
165  size = (binsz - zcount) * 138 / 100 + 1;
166  uint8_t buf[size];
167  memset(buf, 0, size);
168 
169  for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) {
170  for (carry = bin[i], j = size - 1; (j > high) || carry; --j) {
171  carry += 256 * buf[j];
172  buf[j] = carry % 58;
173  carry /= 58;
174  }
175  }
176 
177  for (j = 0; j < (ssize_t)size && !buf[j]; ++j);
178 
179  if (*b58sz <= zcount + size - j) {
180  *b58sz = zcount + size - j + 1;
181  memset(buf, 0, size);
182  return false;
183  }
184 
185  if (zcount) {
186  memset(b58, '1', zcount);
187  }
188  for (i = zcount; j < (ssize_t)size; ++i, ++j) {
189  b58[i] = b58digits_ordered[buf[j]];
190  }
191  b58[i] = '\0';
192  *b58sz = i + 1;
193 
194  memset(buf, 0, size);
195  return true;
196 }
static const char b58digits_ordered[]
Definition: base58.c:151
int btc_base58_encode_check ( const uint8_t *  data,
int  len,
char *  str,
int  strsize 
)

Copyright (c) 2013-2014 Tomas Dzetkulic Copyright (c) 2013-2014 Pavol Rusnak

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.

Definition at line 198 of file base58.c.

References btc_base58_encode(), and sha256_Raw().

Referenced by btc_hdnode_serialize().

199 {
200  int ret;
201  if (datalen > 128) {
202  return 0;
203  }
204  uint8_t buf[datalen + 32];
205  uint8_t *hash = buf + datalen;
206  memcpy(buf, data, datalen);
207  sha256_Raw(data, datalen, hash);
208  sha256_Raw(hash, 32, hash);
209  size_t res = strsize;
210  if (btc_base58_encode(str, &res, buf, datalen + 4) != true) {
211  ret = 0;
212  } else {
213  ret = res;
214  }
215  memset(buf, 0, sizeof(buf));
216  return ret;
217 }
void sha256_Raw(const sha2_byte *data, size_t len, uint8_t digest[SHA256_DIGEST_LENGTH])
Definition: sha2.c:652
int btc_base58_encode(char *b58, size_t *b58sz, const void *data, size_t binsz)
Definition: base58.c:154

Variable Documentation

const int8_t b58digits_map[]
static
Initial value:
= {
-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,
}

Copyright (c) 2012-2014 Luke Dashjr Copyright (c) 2013-2014 Pavol Rusnak

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.

Definition at line 31 of file base58.c.

Referenced by btc_base58_decode().

const char b58digits_ordered[]
static
Initial value:
=
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

Definition at line 151 of file base58.c.

Referenced by btc_base58_encode().