aboutsummaryrefslogtreecommitdiff
path: root/src/openpgp/serialization.h
diff options
context:
space:
mode:
authorxiphon <xiphon@protonmail.com>2020-04-06 16:57:32 +0000
committerxiphon <xiphon@protonmail.com>2020-04-12 21:34:22 +0000
commit5f27a45910fcba954e652f3214bc489f03262346 (patch)
tree151d35b69a466881628096f7130eefdd02758596 /src/openpgp/serialization.h
parent042400b83fdea6c18ea8a7970cb0a8af2070c03a (diff)
downloadmonzero-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.h171
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