Commit 60272e9f authored by Ivan Vilata-i-Balaguer's avatar Ivan Vilata-i-Balaguer
Browse files

Allow Base32-encoding for injector pubkey config option.

Padded or unpadded, upper or lower case.
parent e2d4d9dc
......@@ -6,6 +6,7 @@
#include "namespaces.h"
#include "util.h"
#include "util/bytes.h"
#include "parse/endpoint.h"
#include "util/crypto.h"
#include "increase_open_file_limit.h"
......@@ -135,7 +136,8 @@ public:
, "Type of d-cache {none, bep5-http}")
("cache-http-public-key"
, po::value<string>()
, "Public key for HTTP signatures in the BEP5/HTTP cache (hex-encoded)")
, "Public key for HTTP signatures in the BEP5/HTTP cache "
"(hex-encoded or Base32-encoded)")
("max-cached-age"
, po::value<int>()->default_value(_max_cached_age.total_seconds())
, "Discard cached content older than this many seconds "
......@@ -331,7 +333,16 @@ ClientConfig::ClientConfig(int argc, char* argv[])
if (vm.count(opt)) {
string value = vm[opt].as<string>();
pk = util::Ed25519PublicKey::from_hex(value);
using PubKey = util::Ed25519PublicKey;
pk = PubKey::from_hex(value);
if (!pk) { // attempt decoding from Base32
auto pk_s = util::base32_decode(value);
if (pk_s.size() == PubKey::key_size) {
auto pk_a = util::bytes::to_array<uint8_t, PubKey::key_size>(pk_s);
pk = PubKey(std::move(pk_a));
}
}
if (!pk) {
throw std::runtime_error(
......
......@@ -10,6 +10,7 @@
#include <boost/archive/iterators/transform_width.hpp>
#include "util/iterators/base32_from_binary.hpp"
#include "util/iterators/binary_from_base32.hpp"
using namespace std;
......@@ -53,6 +54,19 @@ string ouinet::util::detail::base32up_encode(const char* data, size_t size) {
return out; // do not add padding
}
string ouinet::util::base32_decode(const boost::string_view in) {
using namespace boost::archive::iterators;
using It = transform_width<binary_from_base32<const char*>, 8, 5>;
It begin = in.data();
It end = in.data() + in.size();
string out(begin, end); // decode from base32
size_t npad = count(in.begin(), in.end(), '=');
if (npad > 6) npad = 6;
static const size_t padding_bytes[7] = {0, 1, 1, 2, 3, 3, 4};
npad = padding_bytes[npad];
return out.erase((npad > out.size()) ? 0 : out.size() - npad); // remove padding
}
// Based on <https://stackoverflow.com/a/28471421> by user "ltc"
// and <https://stackoverflow.com/a/10973348> by user "PiQuer".
string ouinet::util::detail::base64_encode(const char* data, size_t size) {
......
......@@ -174,6 +174,7 @@ template<class In>
std::string base32up_encode(const In& in) { // unpadded!
return detail::base32up_encode(reinterpret_cast<const char*>(in.data()), in.size());
}
std::string base32_decode(const boost::string_view);
template<class In>
std::string base64_encode(const In& in) {
......
#ifndef BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE32_HPP
#define BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE32_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// binary_from_base32.hpp
// Adapted from Robert Ramsey's "binary_from_base64.hpp".
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/assert.hpp>
#include <boost/serialization/throw_exception.hpp>
#include <boost/static_assert.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/archive/iterators/dataflow_exception.hpp>
namespace boost {
namespace archive {
namespace iterators {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// convert base32 characters to binary data
namespace detail {
template<class CharType>
struct to_5_bit {
typedef CharType result_type;
CharType operator()(CharType t) const{
static const signed char lookup_table[] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,26,27,28,29,30,31,-1,-1,-1,-1,-1, 0,-1,-1, // render '=' as 0
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1
};
// metrowerks trips this assertion - how come?
#if ! defined(__MWERKS__)
BOOST_STATIC_ASSERT(128 == sizeof(lookup_table));
#endif
signed char value = -1;
if((unsigned)t <= 127)
value = lookup_table[(unsigned)t];
if(-1 == value)
boost::serialization::throw_exception(
// TODO: A specific exception should be added here for Base32.
//dataflow_exception(dataflow_exception::invalid_base32_character)
dataflow_exception(dataflow_exception::invalid_conversion)
);
return value;
}
};
} // namespace detail
// note: what we would like to do is
// template<class Base, class CharType = typename Base::value_type>
// typedef transform_iterator<
// from_5_bit<CharType>,
// transform_width<Base, 5, sizeof(Base::value_type) * 8, CharType>
// > base32_from_binary;
// but C++ won't accept this. Rather than using a "type generator" and
// using a different syntax, make a derivation which should be equivalent.
//
// Another issue addressed here is that the transform_iterator doesn't have
// a templated constructor. This makes it incompatible with the dataflow
// ideal. This is also addressed here.
template<
class Base,
class CharType = typename boost::iterator_value<Base>::type
>
class binary_from_base32 : public
transform_iterator<
detail::to_5_bit<CharType>,
Base
>
{
friend class boost::iterator_core_access;
typedef transform_iterator<
detail::to_5_bit<CharType>,
Base
> super_t;
public:
// make composible buy using templated constructor
template<class T>
binary_from_base32(T start) :
super_t(
Base(static_cast< T >(start)),
detail::to_5_bit<CharType>()
)
{}
// intel 7.1 doesn't like default copy constructor
binary_from_base32(const binary_from_base32 & rhs) :
super_t(
Base(rhs.base_reference()),
detail::to_5_bit<CharType>()
)
{}
// binary_from_base32(){};
};
} // namespace iterators
} // namespace archive
} // namespace boost
#endif // BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE32_HPP
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment