rippled
base64.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2018 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 //
21 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
22 //
23 // Distributed under the Boost Software License, Version 1.0. (See accompanying
24 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
25 //
26 
27 /*
28  Portions from http://www.adp-gmbh.ch/cpp/common/base64.html
29  Copyright notice:
30 
31  base64.cpp and base64.h
32 
33  Copyright (C) 2004-2008 RenĂ© Nyffenegger
34 
35  This source code is provided 'as-is', without any express or implied
36  warranty. In no event will the author be held liable for any damages
37  arising from the use of this software.
38 
39  Permission is granted to anyone to use this software for any purpose,
40  including commercial applications, and to alter it and redistribute it
41  freely, subject to the following restrictions:
42 
43  1. The origin of this source code must not be misrepresented; you must not
44  claim that you wrote the original source code. If you use this source code
45  in a product, an acknowledgment in the product documentation would be
46  appreciated but is not required.
47 
48  2. Altered source versions must be plainly marked as such, and must not be
49  misrepresented as being the original source code.
50 
51  3. This notice may not be removed or altered from any source distribution.
52 
53  RenĂ© Nyffenegger rene.nyffenegger@adp-gmbh.ch
54 
55 */
56 
57 #include <ripple/basics/base64.h>
58 
59 #include <cctype>
60 #include <utility>
61 
62 namespace ripple {
63 
64 namespace base64 {
65 
66 inline char const*
68 {
69  static char constexpr tab[] = {
70  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
71  return &tab[0];
72 }
73 
74 inline signed char const*
76 {
77  static signed char constexpr tab[] = {
78  -1, -1, -1, -1, -1, -1, -1, -1,
79  -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
80  -1, -1, -1, -1, -1, -1, -1, -1,
81  -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
82  -1, -1, -1, -1, -1, -1, -1, -1,
83  -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
84  52, 53, 54, 55, 56, 57, 58, 59,
85  60, 61, -1, -1, -1, -1, -1, -1, // 48-63
86  -1, 0, 1, 2, 3, 4, 5, 6,
87  7, 8, 9, 10, 11, 12, 13, 14, // 64-79
88  15, 16, 17, 18, 19, 20, 21, 22,
89  23, 24, 25, -1, -1, -1, -1, -1, // 80-95
90  -1, 26, 27, 28, 29, 30, 31, 32,
91  33, 34, 35, 36, 37, 38, 39, 40, // 96-111
92  41, 42, 43, 44, 45, 46, 47, 48,
93  49, 50, 51, -1, -1, -1, -1, -1, // 112-127
94  -1, -1, -1, -1, -1, -1, -1, -1,
95  -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
96  -1, -1, -1, -1, -1, -1, -1, -1,
97  -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
98  -1, -1, -1, -1, -1, -1, -1, -1,
99  -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
100  -1, -1, -1, -1, -1, -1, -1, -1,
101  -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
102  -1, -1, -1, -1, -1, -1, -1, -1,
103  -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
104  -1, -1, -1, -1, -1, -1, -1, -1,
105  -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
106  -1, -1, -1, -1, -1, -1, -1, -1,
107  -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
108  -1, -1, -1, -1, -1, -1, -1, -1,
109  -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
110  };
111  return &tab[0];
112 }
113 
116 {
117  return 4 * ((n + 2) / 3);
118 }
119 
122 {
123  return ((n / 4) * 3) + 2;
124 }
125 
139 encode(void* dest, void const* src, std::size_t len)
140 {
141  char* out = static_cast<char*>(dest);
142  char const* in = static_cast<char const*>(src);
143  auto const tab = base64::get_alphabet();
144 
145  for (auto n = len / 3; n--;)
146  {
147  *out++ = tab[(in[0] & 0xfc) >> 2];
148  *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
149  *out++ = tab[((in[2] & 0xc0) >> 6) + ((in[1] & 0x0f) << 2)];
150  *out++ = tab[in[2] & 0x3f];
151  in += 3;
152  }
153 
154  switch (len % 3)
155  {
156  case 2:
157  *out++ = tab[(in[0] & 0xfc) >> 2];
158  *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
159  *out++ = tab[(in[1] & 0x0f) << 2];
160  *out++ = '=';
161  break;
162 
163  case 1:
164  *out++ = tab[(in[0] & 0xfc) >> 2];
165  *out++ = tab[((in[0] & 0x03) << 4)];
166  *out++ = '=';
167  *out++ = '=';
168  break;
169 
170  case 0:
171  break;
172  }
173 
174  return out - static_cast<char*>(dest);
175 }
176 
189 decode(void* dest, char const* src, std::size_t len)
190 {
191  char* out = static_cast<char*>(dest);
192  auto in = reinterpret_cast<unsigned char const*>(src);
193  unsigned char c3[3]{}, c4[4]{};
194  int i = 0;
195  int j = 0;
196 
197  auto const inverse = base64::get_inverse();
198 
199  while (len-- && *in != '=')
200  {
201  auto const v = inverse[*in];
202  if (v == -1)
203  break;
204  ++in;
205  c4[i] = v;
206  if (++i == 4)
207  {
208  c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
209  c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
210  c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
211 
212  for (i = 0; i < 3; i++)
213  *out++ = c3[i];
214  i = 0;
215  }
216  }
217 
218  if (i)
219  {
220  c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
221  c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
222  c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
223 
224  for (j = 0; j < i - 1; j++)
225  *out++ = c3[j];
226  }
227 
228  return {
229  out - static_cast<char*>(dest),
230  in - reinterpret_cast<unsigned char const*>(src)};
231 }
232 
233 } // namespace base64
234 
237 {
238  std::string dest;
239  dest.resize(base64::encoded_size(len));
240  dest.resize(base64::encode(&dest[0], data, len));
241  return dest;
242 }
243 
246 {
247  std::string dest;
248  dest.resize(base64::decoded_size(data.size()));
249  auto const result = base64::decode(&dest[0], data.data(), data.size());
250  dest.resize(result.first);
251  return dest;
252 }
253 
254 } // namespace ripple
std::string::resize
T resize(T... args)
ripple::base64::decode
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.
Definition: base64.cpp:189
std::string
STL class.
utility
std::pair
ripple::base64::get_alphabet
char const * get_alphabet()
Definition: base64.cpp:67
ripple::base64_encode
std::string base64_encode(std::uint8_t const *data, std::size_t len)
Definition: base64.cpp:236
ripple::QualityDirection::in
@ in
ripple::QualityDirection::out
@ out
ripple::base64::decoded_size
constexpr std::size_t decoded_size(std::size_t n)
Returns max bytes needed to decode a base64 string.
Definition: base64.cpp:121
ripple::base64_decode
std::string base64_decode(std::string const &data)
Definition: base64.cpp:245
std::uint8_t
ripple::base64::encoded_size
constexpr std::size_t encoded_size(std::size_t n)
Returns max chars needed to encode a base64 string.
Definition: base64.cpp:115
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
cctype
std::size_t
ripple::base64::get_inverse
signed char const * get_inverse()
Definition: base64.cpp:75
ripple::base64::encode
std::size_t encode(void *dest, void const *src, std::size_t len)
Encode a series of octets as a padded, base64 string.
Definition: base64.cpp:139