forked from Public/monero-gui
'--verify-update', shasum support, OpenPGP signatures verification
This commit is contained in:
171
src/openpgp/serialization.h
Normal file
171
src/openpgp/serialization.h
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
namespace openpgp
|
||||
{
|
||||
|
||||
size_t bits_to_bytes(size_t bits)
|
||||
{
|
||||
constexpr const uint16_t bits_in_byte = 8;
|
||||
return (bits + bits_in_byte - 1) / bits_in_byte;
|
||||
}
|
||||
|
||||
std::string strip_line_breaks(const std::string &string)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(string.size());
|
||||
for (const auto &character : string)
|
||||
{
|
||||
if (character != '\r' && character != '\n')
|
||||
{
|
||||
result.push_back(character);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct packet_tag
|
||||
{
|
||||
enum type : uint8_t
|
||||
{
|
||||
signature = 2,
|
||||
public_key = 6,
|
||||
user_id = 13,
|
||||
};
|
||||
|
||||
const type packet_type;
|
||||
const size_t length;
|
||||
};
|
||||
|
||||
template <
|
||||
typename byte_container,
|
||||
typename = typename std::enable_if<(sizeof(typename byte_container::value_type) == 1)>::type>
|
||||
class deserializer
|
||||
{
|
||||
public:
|
||||
deserializer(byte_container buffer)
|
||||
: buffer(std::move(buffer))
|
||||
, cursor(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return buffer.size() - cursor == 0;
|
||||
}
|
||||
|
||||
packet_tag read_packet_tag()
|
||||
{
|
||||
const auto tag = read_big_endian<uint8_t>();
|
||||
|
||||
constexpr const uint8_t format_mask = 0b11000000;
|
||||
constexpr const uint8_t format_old_tag = 0b10000000;
|
||||
if ((tag & format_mask) != format_old_tag)
|
||||
{
|
||||
throw std::runtime_error("invalid packet tag");
|
||||
}
|
||||
|
||||
const packet_tag::type packet_type = static_cast<packet_tag::type>((tag & 0b00111100) >> 2);
|
||||
const uint8_t length_type = tag & 0b00000011;
|
||||
|
||||
size_t length;
|
||||
switch (length_type)
|
||||
{
|
||||
case 0:
|
||||
length = read_big_endian<uint8_t>();
|
||||
break;
|
||||
case 1:
|
||||
length = read_big_endian<uint16_t>();
|
||||
break;
|
||||
case 2:
|
||||
length = read_big_endian<uint32_t>();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("unsupported packet length type");
|
||||
}
|
||||
|
||||
return {packet_type, length};
|
||||
}
|
||||
|
||||
mpi read_mpi()
|
||||
{
|
||||
const size_t bit_length = read_big_endian<uint16_t>();
|
||||
return mpi(read_span(bits_to_bytes(bit_length)));
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read(size_t size)
|
||||
{
|
||||
if (buffer.size() - cursor < size)
|
||||
{
|
||||
throw std::runtime_error("insufficient buffer size");
|
||||
}
|
||||
|
||||
const size_t offset = cursor;
|
||||
cursor += size;
|
||||
|
||||
return {&buffer[offset], &buffer[cursor]};
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
T read_big_endian()
|
||||
{
|
||||
if (buffer.size() - cursor < sizeof(T))
|
||||
{
|
||||
throw std::runtime_error("insufficient buffer size");
|
||||
}
|
||||
T result = 0;
|
||||
for (size_t read = 0; read < sizeof(T); ++read)
|
||||
{
|
||||
result = (result << 8) | static_cast<uint8_t>(buffer[cursor++]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
epee::span<const uint8_t> read_span(size_t size)
|
||||
{
|
||||
if (buffer.size() - cursor < size)
|
||||
{
|
||||
throw std::runtime_error("insufficient buffer size");
|
||||
}
|
||||
|
||||
const size_t offset = cursor;
|
||||
cursor += size;
|
||||
|
||||
return {reinterpret_cast<const uint8_t *>(&buffer[offset]), size};
|
||||
}
|
||||
|
||||
private:
|
||||
byte_container buffer;
|
||||
size_t cursor;
|
||||
};
|
||||
|
||||
} // namespace openpgp
|
||||
Reference in New Issue
Block a user