Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
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
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
38char 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
45int 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
108int 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