Embedded SDK
Embedded SDK
base58.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * (c) 2020 Ledger SAS.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 #include <stddef.h> // size_t
18 #include <stdint.h> // uint*_t
19 #include <string.h> // memmove, memset
20 #include <stdbool.h> // bool
21 
22 #include "base58.h"
23 
24 uint8_t const BASE58_TABLE[] = {
25  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
26  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
27  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
28  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
29  0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xFF, 0xFF, //
30  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, //
31  0x10, 0xFF, 0x11, 0x12, 0x13, 0x14, 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, //
32  0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
33  0xFF, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //
34  0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, //
35  0x37, 0x38, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF //
36 };
37 
38 char const BASE58_ALPHABET[] = {
39  '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', //
40  'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', //
41  'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', //
42  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' //
43 };
44 
45 int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len)
46 {
47  uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0};
48  uint8_t buffer[MAX_DEC_INPUT_SIZE] = {0};
49  uint8_t j;
50  uint8_t start_at;
51  uint8_t zero_count = 0;
52 
53  if (in_len > MAX_DEC_INPUT_SIZE || in_len < 2) {
54  return -1;
55  }
56 
57  memmove(tmp, in, in_len);
58 
59  for (uint8_t i = 0; i < in_len; i++) {
60  if (in[i] >= sizeof(BASE58_TABLE)) {
61  return -1;
62  }
63 
64  tmp[i] = BASE58_TABLE[(int) in[i]];
65 
66  if (tmp[i] == 0xFF) {
67  return -1;
68  }
69  }
70 
71  while ((zero_count < in_len) && (tmp[zero_count] == 0)) {
72  ++zero_count;
73  }
74 
75  j = in_len;
76  start_at = zero_count;
77  while (start_at < in_len) {
78  uint16_t remainder = 0;
79  for (uint8_t div_loop = start_at; div_loop < in_len; div_loop++) {
80  uint16_t digit256 = (uint16_t) (tmp[div_loop] & 0xFF);
81  uint16_t tmp_div = remainder * 58 + digit256;
82  tmp[div_loop] = (uint8_t) (tmp_div / 256);
83  remainder = tmp_div % 256;
84  }
85 
86  if (tmp[start_at] == 0) {
87  ++start_at;
88  }
89 
90  buffer[--j] = (uint8_t) remainder;
91  }
92 
93  while ((j < in_len) && (buffer[j] == 0)) {
94  ++j;
95  }
96 
97  int length = in_len - (j - zero_count);
98 
99  if ((int) out_len < length) {
100  return -1;
101  }
102 
103  memmove(out, buffer + j - zero_count, length);
104 
105  return length;
106 }
107 
108 int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len)
109 {
110  uint8_t buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0};
111  size_t i, j;
112  size_t stop_at;
113  size_t zero_count = 0;
114  size_t output_size;
115 
116  if (in_len > MAX_ENC_INPUT_SIZE) {
117  return -1;
118  }
119 
120  while ((zero_count < in_len) && (in[zero_count] == 0)) {
121  ++zero_count;
122  }
123 
124  output_size = (in_len - zero_count) * 138 / 100 + 1;
125  stop_at = output_size - 1;
126  for (size_t start_at = zero_count; start_at < in_len; start_at++) {
127  int carry = in[start_at];
128  for (j = output_size - 1; (int) j >= 0; j--) {
129  carry += 256 * buffer[j];
130  buffer[j] = carry % 58;
131  carry /= 58;
132 
133  if (j <= stop_at - 1 && carry == 0) {
134  break;
135  }
136  }
137  stop_at = j;
138  }
139 
140  j = 0;
141  while (j < output_size && buffer[j] == 0) {
142  j += 1;
143  }
144 
145  if (out_len < zero_count + output_size - j) {
146  return -1;
147  }
148 
149  memset(out, BASE58_ALPHABET[0], zero_count);
150 
151  i = zero_count;
152  while (j < output_size) {
153  out[i++] = BASE58_ALPHABET[buffer[j++]];
154  }
155 
156  return i;
157 }
char const BASE58_ALPHABET[]
Definition: base58.c:38
uint8_t const BASE58_TABLE[]
Definition: base58.c:24
int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len)
Definition: base58.c:108
int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len)
Definition: base58.c:45
#define MAX_DEC_INPUT_SIZE
Definition: base58.h:10
#define MAX_ENC_INPUT_SIZE
Definition: base58.h:14
unsigned short uint16_t
Definition: usbd_conf.h:54
unsigned char uint8_t
Definition: usbd_conf.h:53