19 #include <boost/archive/iterators/base64_from_binary.hpp>
20 #include <boost/archive/iterators/binary_from_base64.hpp>
21 #include <boost/archive/iterators/transform_width.hpp>
22 #ifdef HAVE_BOOST_INTEGER_COMMON_FACTOR_HPP
23 #include <boost/integer/common_factor.hpp>
25 #include <boost/math/common_factor.hpp>
43 namespace clang_unnamed_namespace_workaround {
98 const char BASE_PADDING_CHAR =
'=';
99 const uint8_t BINARY_ZERO_CODE = 0;
115 class EncodeNormalizer :
public iterator<input_iterator_tag, uint8_t> {
117 EncodeNormalizer(
const vector<uint8_t>::const_iterator& base,
118 const vector<uint8_t>::const_iterator& base_end) :
121 EncodeNormalizer& operator++() {
125 EncodeNormalizer operator++(
int) {
126 const EncodeNormalizer
copy = *
this;
130 const uint8_t& operator*()
const {
132 return (BINARY_ZERO_CODE);
137 bool operator==(
const EncodeNormalizer& other)
const {
138 return (
base_ == other.base_);
149 vector<uint8_t>::const_iterator
base_;
170 class DecodeNormalizer :
public iterator<input_iterator_tag, char> {
172 DecodeNormalizer(
const char base_zero_code,
173 const string::const_iterator& base,
174 const string::const_iterator& base_beginpad,
175 const string::const_iterator& base_end,
176 size_t* char_count) :
185 DecodeNormalizer& operator++() {
209 const char& operator*()
const {
224 throw clang_unnamed_namespace_workaround::IncompleteBaseInput();
226 if (*
base_ == BASE_PADDING_CHAR) {
234 isc_throw(BadValue,
"Intermediate padding found");
240 bool operator==(
const DecodeNormalizer& other)
const {
241 return (
base_ == other.base_);
245 string::const_iterator
base_;
262 template <
int BitsPerChunk,
char BaseZeroCode,
263 typename Encoder,
typename Decoder>
264 struct BaseNTransformer {
265 static string encode(
const vector<uint8_t>& binary);
266 static void decode(
const char* algorithm,
267 const string& base64, vector<uint8_t>& result);
273 static const int BITS_PER_GROUP =
274 #ifdef HAVE_BOOST_INTEGER_COMMON_FACTOR_HPP
275 boost::integer::static_lcm<BitsPerChunk, 8>::value;
277 boost::math::static_lcm<BitsPerChunk, 8>::value;
289 static const int MAX_PADDING_CHARS =
290 BITS_PER_GROUP / BitsPerChunk -
291 (8 / BitsPerChunk + ((8 % BitsPerChunk) == 0 ? 0 : 1));
294 template <
int BitsPerChunk,
char BaseZeroCode,
295 typename Encoder,
typename Decoder>
297 BaseNTransformer<BitsPerChunk, BaseZeroCode, Encoder, Decoder>::encode(
298 const vector<uint8_t>& binary)
301 size_t bits = binary.size() * 8;
302 if (bits % BITS_PER_GROUP > 0) {
303 bits += (BITS_PER_GROUP - (bits % BITS_PER_GROUP));
305 const size_t len = bits / BitsPerChunk;
309 result.assign(Encoder(EncodeNormalizer(binary.begin(), binary.end())),
310 Encoder(EncodeNormalizer(binary.end(), binary.end())));
312 result.append(len - result.length(), BASE_PADDING_CHAR);
316 template <
int BitsPerChunk,
char BaseZeroCode,
317 typename Encoder,
typename Decoder>
319 BaseNTransformer<BitsPerChunk, BaseZeroCode, Encoder, Decoder>::decode(
320 const char*
const algorithm,
322 vector<uint8_t>& result)
328 string::const_reverse_iterator srit = input.rbegin();
329 string::const_reverse_iterator srit_end = input.rend();
330 while (srit != srit_end) {
332 if (ch == BASE_PADDING_CHAR) {
333 if (++padchars > MAX_PADDING_CHARS) {
334 isc_throw(BadValue,
"Too many " << algorithm
335 <<
" padding characters: " << input);
337 }
else if (!(ch > 0 && isspace(ch))) {
357 const size_t padbits = (padchars * BitsPerChunk + 7) & ~7;
369 if (padbits > BitsPerChunk * (padchars + 1)) {
370 isc_throw(BadValue,
"Invalid " << algorithm <<
" padding: " << input);
374 const size_t padbytes = padbits / 8;
377 size_t char_count = 0;
378 result.assign(Decoder(DecodeNormalizer(BaseZeroCode, input.begin(),
379 srit.base(), input.end(),
381 Decoder(DecodeNormalizer(BaseZeroCode, input.end(),
382 input.end(), input.end(),
388 if (((char_count * BitsPerChunk) % 8) != 0) {
390 throw clang_unnamed_namespace_workaround::IncompleteBaseInput();
392 }
catch (
const clang_unnamed_namespace_workaround::IncompleteBaseInput&) {
394 isc_throw(BadValue,
"Incomplete input for " << algorithm
396 }
catch (
const dataflow_exception& ex) {
406 if (padbytes > 0 && *(result.end() - padbytes) != 0) {
407 isc_throw(BadValue,
"Non 0 bits included in " << algorithm
408 <<
" padding: " << input);
412 result.resize(result.size() - padbytes);
419 base64_from_binary<transform_width<EncodeNormalizer, 6, 8> > base64_encoder;
421 transform_width<binary_from_base64<DecodeNormalizer>, 8, 6> base64_decoder;
422 typedef BaseNTransformer<6, 'A', base64_encoder, base64_decoder>
432 transform_width<binary_from_base32hex<DecodeNormalizer>, 8, 5>
434 typedef BaseNTransformer<5, '0', base32hex_encoder, base32hex_decoder>
435 Base32HexTransformer;
443 transform_width<binary_from_base16<DecodeNormalizer>, 8, 4> base16_decoder;
444 typedef BaseNTransformer<4, '0', base16_encoder, base16_decoder>
450 return (Base64Transformer::encode(binary));
455 Base64Transformer::decode(
"base64", input, result);
460 return (Base32HexTransformer::encode(binary));
465 Base32HexTransformer::decode(
"base32hex", input, result);
470 return (Base16Transformer::encode(binary));
474 decodeHex(
const string& input, vector<uint8_t>& result) {
475 Base16Transformer::decode(
"base16", input, result);
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
bool operator==(const Element &a, const Element &b)
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
const vector< uint8_t >::const_iterator base_end_
void decodeBase64(const std::string &input, std::vector< uint8_t > &result)
Decode a text encoded in the base64 format into the original data.
Defines the logger used by the top-level component of kea-dhcp-ddns.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
std::string encodeBase64(const std::vector< uint8_t > &binary)
Encode binary data in the base64 format.
const char base_zero_code_
std::string encodeBase32Hex(const std::vector< uint8_t > &binary)
Encode binary data in the base32hex format.
vector< uint8_t >::const_iterator base_
void decodeBase32Hex(const std::string &input, std::vector< uint8_t > &result)
Decode a text encoded in the base32hex format into the original data.
const string::const_iterator base_beginpad_