libbtc
bitcoinclibrary
base58.c
Go to the documentation of this file.
1 
24 #include "btc/base58.h"
25 
26 #include <string.h>
27 #include <sys/types.h>
28 
29 #include "sha2.h"
30 
31 static const int8_t b58digits_map[] = {
32  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1,
36  -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1,
37  22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1,
38  -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46,
39  47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,
40 };
41 
42 int btc_base58_decode(void *bin, size_t *binszp, const char *b58)
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 }
126 
127 int btc_b58check(const void *bin, size_t binsz, const char *base58str)
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 }
150 
151 static const char b58digits_ordered[] =
152  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
153 
154 int btc_base58_encode(char *b58, size_t *b58sz, const void *data, size_t binsz)
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 }
197 
198 int btc_base58_encode_check(const uint8_t *data, int datalen, char *str, int strsize)
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 }
218 
219 int btc_base58_decode_check(const char *str, uint8_t *data, size_t datalen)
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
void sha256_Raw(const sha2_byte *data, size_t len, uint8_t digest[SHA256_DIGEST_LENGTH])
Definition: sha2.c:652
int btc_base58_decode_check(const char *str, uint8_t *data, size_t datalen)
Definition: base58.c:219
static const int8_t b58digits_map[]
Definition: base58.c:31
int btc_b58check(const void *bin, size_t binsz, const char *base58str)
Definition: base58.c:127
static const char b58digits_ordered[]
Definition: base58.c:151
int btc_base58_encode(char *b58, size_t *b58sz, const void *data, size_t binsz)
Definition: base58.c:154
int btc_base58_encode_check(const uint8_t *data, int datalen, char *str, int strsize)
Definition: base58.c:198