rippled
Loading...
Searching...
No Matches
libxrpl/basics/base64.cpp
1// Distributed under the Boost Software License, Version 1.0. (See accompanying
2// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3//
4
5/*
6 Portions from http://www.adp-gmbh.ch/cpp/common/base64.html
7 Copyright notice:
8
9 base64.cpp and base64.h
10
11 Copyright (C) 2004-2008 René Nyffenegger
12
13 This source code is provided 'as-is', without any express or implied
14 warranty. In no event will the author be held liable for any damages
15 arising from the use of this software.
16
17 Permission is granted to anyone to use this software for any purpose,
18 including commercial applications, and to alter it and redistribute it
19 freely, subject to the following restrictions:
20
21 1. The origin of this source code must not be misrepresented; you must not
22 claim that you wrote the original source code. If you use this source code
23 in a product, an acknowledgment in the product documentation would be
24 appreciated but is not required.
25
26 2. Altered source versions must be plainly marked as such, and must not be
27 misrepresented as being the original source code.
28
29 3. This notice may not be removed or altered from any source distribution.
30
31 René Nyffenegger rene.nyffenegger@adp-gmbh.ch
32
33*/
34
35#include <xrpl/basics/base64.h>
36
37#include <cstddef>
38#include <cstdint>
39#include <string>
40#include <string_view>
41#include <utility>
42
43namespace xrpl {
44
45namespace base64 {
46
47inline char const*
49{
50 static char constexpr tab[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
51 return &tab[0];
52}
53
54inline signed char const*
56{
57 static signed char constexpr tab[] = {
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
61 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
62 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
63 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
64 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
65 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
72 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
74 };
75 return &tab[0];
76}
77
80{
81 return 4 * ((n + 2) / 3);
82}
83
86{
87 return ((n / 4) * 3) + 2;
88}
89
103encode(void* dest, void const* src, std::size_t len)
104{
105 char* out = static_cast<char*>(dest);
106 char const* in = static_cast<char const*>(src);
107 auto const tab = base64::get_alphabet();
108
109 for (auto n = len / 3; n--;)
110 {
111 *out++ = tab[(in[0] & 0xfc) >> 2];
112 *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
113 *out++ = tab[((in[2] & 0xc0) >> 6) + ((in[1] & 0x0f) << 2)];
114 *out++ = tab[in[2] & 0x3f];
115 in += 3;
116 }
117
118 switch (len % 3)
119 {
120 case 2:
121 *out++ = tab[(in[0] & 0xfc) >> 2];
122 *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
123 *out++ = tab[(in[1] & 0x0f) << 2];
124 *out++ = '=';
125 break;
126
127 case 1:
128 *out++ = tab[(in[0] & 0xfc) >> 2];
129 *out++ = tab[((in[0] & 0x03) << 4)];
130 *out++ = '=';
131 *out++ = '=';
132 break;
133
134 case 0:
135 break;
136 }
137
138 return out - static_cast<char*>(dest);
139}
140
153decode(void* dest, char const* src, std::size_t len)
154{
155 char* out = static_cast<char*>(dest);
156 auto in = reinterpret_cast<unsigned char const*>(src);
157 unsigned char c3[3]{}, c4[4]{};
158 int i = 0;
159 int j = 0;
160
161 auto const inverse = base64::get_inverse();
162
163 while (len-- && *in != '=')
164 {
165 auto const v = inverse[*in];
166 if (v == -1)
167 break;
168 ++in;
169 c4[i] = v;
170 if (++i == 4)
171 {
172 c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
173 c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
174 c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
175
176 for (i = 0; i < 3; i++)
177 *out++ = c3[i];
178 i = 0;
179 }
180 }
181
182 if (i)
183 {
184 c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
185 c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
186 c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
187
188 for (j = 0; j < i - 1; j++)
189 *out++ = c3[j];
190 }
191
192 return {out - static_cast<char*>(dest), in - reinterpret_cast<unsigned char const*>(src)};
193}
194
195} // namespace base64
196
199{
200 std::string dest;
201 dest.resize(base64::encoded_size(len));
202 dest.resize(base64::encode(&dest[0], data, len));
203 return dest;
204}
205
208{
209 std::string dest;
210 dest.resize(base64::decoded_size(data.size()));
211 auto const result = base64::decode(&dest[0], data.data(), data.size());
212 dest.resize(result.first);
213 return dest;
214}
215
216} // namespace xrpl
signed char const * get_inverse()
std::size_t constexpr encoded_size(std::size_t n)
Returns max chars needed to encode a base64 string.
char const * get_alphabet()
std::pair< std::size_t, std::size_t > decode(void *dest, char const *src, std::size_t len)
Decode a padded base64 string into a series of octets.
std::size_t encode(void *dest, void const *src, std::size_t len)
Encode a series of octets as a padded, base64 string.
std::size_t constexpr decoded_size(std::size_t n)
Returns max bytes needed to decode a base64 string.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::string base64_decode(std::string_view data)
std::string base64_encode(std::uint8_t const *data, std::size_t len)
T resize(T... args)