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
67 char const*
69 {
70  static char constexpr tab[] = {
71  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
72  };
73  return &tab[0];
74 }
75 
76 inline
77 signed char const*
79 {
80  static signed char constexpr tab[] = {
81  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
82  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
83  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
84  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
85  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
86  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
87  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
88  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
89  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
90  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
91  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
92  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
93  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
94  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
95  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
96  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
97  };
98  return &tab[0];
99 }
100 
101 
103 inline
104 std::size_t constexpr
106 {
107  return 4 * ((n + 2) / 3);
108 }
109 
111 inline
112 std::size_t constexpr
114 {
115  return ((n / 4) * 3) + 2;
116 }
117 
131 encode(void* dest, void const* src, std::size_t len)
132 {
133  char* out = static_cast<char*>(dest);
134  char const* in = static_cast<char const*>(src);
135  auto const tab = base64::get_alphabet();
136 
137  for(auto n = len / 3; n--;)
138  {
139  *out++ = tab[ (in[0] & 0xfc) >> 2];
140  *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
141  *out++ = tab[((in[2] & 0xc0) >> 6) + ((in[1] & 0x0f) << 2)];
142  *out++ = tab[ in[2] & 0x3f];
143  in += 3;
144  }
145 
146  switch(len % 3)
147  {
148  case 2:
149  *out++ = tab[ (in[0] & 0xfc) >> 2];
150  *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
151  *out++ = tab[ (in[1] & 0x0f) << 2];
152  *out++ = '=';
153  break;
154 
155  case 1:
156  *out++ = tab[ (in[0] & 0xfc) >> 2];
157  *out++ = tab[((in[0] & 0x03) << 4)];
158  *out++ = '=';
159  *out++ = '=';
160  break;
161 
162  case 0:
163  break;
164  }
165 
166  return out - static_cast<char*>(dest);
167 }
168 
181 decode(void* dest, char const* src, std::size_t len)
182 {
183  char* out = static_cast<char*>(dest);
184  auto in = reinterpret_cast<unsigned char const*>(src);
185  unsigned char c3[3], c4[4];
186  int i = 0;
187  int j = 0;
188 
189  auto const inverse = base64::get_inverse();
190 
191  while(len-- && *in != '=')
192  {
193  auto const v = inverse[*in];
194  if(v == -1)
195  break;
196  ++in;
197  c4[i] = v;
198  if(++i == 4)
199  {
200  c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
201  c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
202  c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
203 
204  for(i = 0; i < 3; i++)
205  *out++ = c3[i];
206  i = 0;
207  }
208  }
209 
210  if(i)
211  {
212  c3[0] = ( c4[0] << 2) + ((c4[1] & 0x30) >> 4);
213  c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
214  c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
215 
216  for(j = 0; j < i - 1; j++)
217  *out++ = c3[j];
218  }
219 
220  return {out - static_cast<char*>(dest),
221  in - reinterpret_cast<unsigned char const*>(src)};
222 }
223 
224 } // base64
225 
228  std::size_t len)
229 {
230  std::string dest;
231  dest.resize(base64::encoded_size(len));
232  dest.resize(base64::encode(&dest[0], data, len));
233  return dest;
234 }
235 
238 {
239  std::string dest;
240  dest.resize(base64::decoded_size(data.size()));
241  auto const result = base64::decode(
242  &dest[0], data.data(), data.size());
243  dest.resize(result.first);
244  return dest;
245 }
246 
247 } // 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:181
std::string
STL class.
utility
std::pair
ripple::base64::get_alphabet
char const * get_alphabet()
Definition: base64.cpp:68
ripple::base64_encode
std::string base64_encode(std::uint8_t const *data, std::size_t len)
Definition: base64.cpp:227
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:113
ripple::base64_decode
std::string base64_decode(std::string const &data)
Definition: base64.cpp:237
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:105
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:78
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:131