diff options
| author | xiphon <xiphon@protonmail.com> | 2020-04-06 16:57:32 +0000 |
|---|---|---|
| committer | xiphon <xiphon@protonmail.com> | 2020-04-12 21:34:22 +0000 |
| commit | 5f27a45910fcba954e652f3214bc489f03262346 (patch) | |
| tree | 151d35b69a466881628096f7130eefdd02758596 /src/openpgp/serialization.h | |
| parent | 042400b83fdea6c18ea8a7970cb0a8af2070c03a (diff) | |
| download | monzero-gui-5f27a45910fcba954e652f3214bc489f03262346.tar.gz monzero-gui-5f27a45910fcba954e652f3214bc489f03262346.tar.xz monzero-gui-5f27a45910fcba954e652f3214bc489f03262346.zip | |
'--verify-update', shasum support, OpenPGP signatures verification
Diffstat (limited to 'src/openpgp/serialization.h')
| -rw-r--r-- | src/openpgp/serialization.h | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/openpgp/serialization.h b/src/openpgp/serialization.h new file mode 100644 index 00000000..33de9216 --- /dev/null +++ b/src/openpgp/serialization.h @@ -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 |
