mirror of
https://github.com/monero-project/monero-gui.git
synced 2025-01-10 11:52:05 +02:00
openpgp: implement public subkeys support
This commit is contained in:
parent
c8f4355e15
commit
ef5d855950
@ -93,15 +93,9 @@ std::string get_armored_block_contents(const std::string &text, const std::strin
|
||||
|
||||
} // namespace
|
||||
|
||||
public_key_rsa::public_key_rsa(const std::string &armored)
|
||||
: public_key_rsa(decode(armored))
|
||||
{
|
||||
}
|
||||
|
||||
public_key_rsa::public_key_rsa(std::tuple<std::string, s_expression, size_t> params)
|
||||
: m_expression(std::move(std::get<1>(params)))
|
||||
, m_bits(std::get<2>(params))
|
||||
, m_user_id(std::move(std::get<0>(params)))
|
||||
public_key_rsa::public_key_rsa(s_expression expression, size_t bits)
|
||||
: m_expression(std::move(expression))
|
||||
, m_bits(bits)
|
||||
{
|
||||
}
|
||||
|
||||
@ -115,19 +109,14 @@ size_t public_key_rsa::bits() const
|
||||
return m_bits;
|
||||
}
|
||||
|
||||
std::string public_key_rsa::user_id() const
|
||||
public_key_block::public_key_block(const std::string &armored)
|
||||
: public_key_block(epee::to_byte_span(epee::to_span(epee::string_encoding::base64_decode(
|
||||
strip_line_breaks(get_armored_block_contents(armored, "BEGIN PGP PUBLIC KEY BLOCK"))))))
|
||||
{
|
||||
return m_user_id;
|
||||
}
|
||||
|
||||
std::tuple<std::string, s_expression, size_t> public_key_rsa::decode(const std::string &armored)
|
||||
{
|
||||
const std::string buffer = epee::string_encoding::base64_decode(
|
||||
strip_line_breaks(get_armored_block_contents(armored, "BEGIN PGP PUBLIC KEY BLOCK")));
|
||||
return decode(epee::to_byte_span(epee::to_span(buffer)));
|
||||
}
|
||||
|
||||
std::tuple<std::string, s_expression, size_t> public_key_rsa::decode(const epee::span<const uint8_t> buffer)
|
||||
// TODO: Public-Key expiration, User ID and Public-Key certification, Subkey binding checks
|
||||
public_key_block::public_key_block(const epee::span<const uint8_t> buffer)
|
||||
{
|
||||
packet_stream packets(buffer);
|
||||
|
||||
@ -136,15 +125,10 @@ std::tuple<std::string, s_expression, size_t> public_key_rsa::decode(const epee:
|
||||
{
|
||||
throw std::runtime_error("user id is missing");
|
||||
}
|
||||
std::string user_id(data->begin(), data->end());
|
||||
m_user_id.assign(data->begin(), data->end());
|
||||
|
||||
data = packets.find_first(packet_tag::type::public_key);
|
||||
if (data == nullptr)
|
||||
{
|
||||
throw std::runtime_error("public key is missing");
|
||||
}
|
||||
|
||||
deserializer<std::vector<uint8_t>> serialized(*data);
|
||||
const auto append_public_key = [this](const std::vector<uint8_t> &data) {
|
||||
deserializer<std::vector<uint8_t>> serialized(data);
|
||||
|
||||
const auto version = serialized.read_big_endian<uint8_t>();
|
||||
if (version != 4)
|
||||
@ -160,14 +144,32 @@ std::tuple<std::string, s_expression, size_t> public_key_rsa::decode(const epee:
|
||||
throw std::runtime_error("unsupported public key algorithm");
|
||||
}
|
||||
|
||||
{
|
||||
const mpi public_key_n = serialized.read_mpi();
|
||||
const mpi public_key_e = serialized.read_mpi();
|
||||
|
||||
s_expression expression("(public-key (rsa (n %m) (e %m)))", public_key_n.get(), public_key_e.get());
|
||||
emplace_back(
|
||||
s_expression("(public-key (rsa (n %m) (e %m)))", public_key_n.get(), public_key_e.get()),
|
||||
gcry_mpi_get_nbits(public_key_n.get()));
|
||||
}
|
||||
};
|
||||
|
||||
return {std::move(user_id), std::move(expression), gcry_mpi_get_nbits(public_key_n.get())};
|
||||
data = packets.find_first(packet_tag::type::public_key);
|
||||
if (data == nullptr)
|
||||
{
|
||||
throw std::runtime_error("public key is missing");
|
||||
}
|
||||
append_public_key(*data);
|
||||
|
||||
packets.for_each(packet_tag::type::public_subkey, append_public_key);
|
||||
}
|
||||
|
||||
std::string public_key_block::user_id() const
|
||||
{
|
||||
return m_user_id;
|
||||
}
|
||||
|
||||
// TODO: Signature expiration check
|
||||
signature_rsa::signature_rsa(
|
||||
uint8_t algorithm,
|
||||
std::pair<uint8_t, uint8_t> hash_leftmost_bytes,
|
||||
|
@ -47,20 +47,25 @@ enum algorithm : uint8_t
|
||||
class public_key_rsa
|
||||
{
|
||||
public:
|
||||
public_key_rsa(const std::string &armored);
|
||||
public_key_rsa(std::tuple<std::string, s_expression, size_t> params);
|
||||
public_key_rsa(s_expression expression, size_t bits);
|
||||
|
||||
size_t bits() const;
|
||||
const gcry_sexp_t &get() const;
|
||||
std::string user_id() const;
|
||||
|
||||
private:
|
||||
static std::tuple<std::string, s_expression, size_t> decode(const std::string &armored);
|
||||
static std::tuple<std::string, s_expression, size_t> decode(const epee::span<const uint8_t> buffer);
|
||||
|
||||
private:
|
||||
s_expression m_expression;
|
||||
size_t m_bits;
|
||||
};
|
||||
|
||||
class public_key_block : public std::vector<public_key_rsa>
|
||||
{
|
||||
public:
|
||||
public_key_block(const std::string &armored);
|
||||
public_key_block(const epee::span<const uint8_t> buffer);
|
||||
|
||||
std::string user_id() const;
|
||||
|
||||
private:
|
||||
std::string m_user_id;
|
||||
};
|
||||
|
||||
|
@ -69,6 +69,18 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void for_each(packet_tag::type type, Callback &callback) const
|
||||
{
|
||||
for (const auto &packet : packets)
|
||||
{
|
||||
if (packet.first.packet_type == type)
|
||||
{
|
||||
callback(packet.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<packet_tag, std::vector<uint8_t>>> packets;
|
||||
};
|
||||
|
@ -60,6 +60,7 @@ struct packet_tag
|
||||
signature = 2,
|
||||
public_key = 6,
|
||||
user_id = 13,
|
||||
public_subkey = 14,
|
||||
};
|
||||
|
||||
const type packet_type;
|
||||
|
@ -157,11 +157,14 @@ QString Updater::verifySignature(const epee::span<const uint8_t> data, const ope
|
||||
{
|
||||
for (const auto &maintainer : m_maintainers)
|
||||
{
|
||||
if (signature.verify(data, maintainer))
|
||||
for (const auto &public_key : maintainer)
|
||||
{
|
||||
if (signature.verify(data, public_key))
|
||||
{
|
||||
return QString::fromStdString(maintainer.user_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("not signed by a maintainer");
|
||||
}
|
||||
|
@ -60,5 +60,5 @@ private:
|
||||
QByteArray parseShasumOutput(const QString &message, const QString &filename) const;
|
||||
|
||||
private:
|
||||
std::vector<openpgp::public_key_rsa> m_maintainers;
|
||||
std::vector<openpgp::public_key_block> m_maintainers;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user