-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add PublicKeyPacket and PublicSubkeyPacket.
- Loading branch information
Showing
40 changed files
with
1,893 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// OpenPGP public key packet data v3 (implementation) | ||
// Copyright 2018 The NeoPG developers | ||
// | ||
// NeoPG is released under the Simplified BSD License (see license.txt) | ||
|
||
#include <neopg/v3_public_key_data.h> | ||
|
||
#include <neopg/rsa_public_key_material.h> | ||
|
||
#include <neopg/intern/cplusplus.h> | ||
#include <neopg/intern/pegtl.h> | ||
|
||
#include <botan/md5.h> | ||
|
||
using namespace NeoPG; | ||
|
||
namespace NeoPG { | ||
namespace v3_public_key_data { | ||
|
||
using namespace pegtl; | ||
|
||
// Grammar | ||
struct created : uint32_be::any {}; | ||
struct days_valid : uint16_be::any {}; | ||
struct algorithm | ||
: uint8::one<static_cast<uint8_t>(PublicKeyAlgorithm::Rsa), | ||
static_cast<uint8_t>(PublicKeyAlgorithm::RsaEncrypt), | ||
static_cast<uint8_t>(PublicKeyAlgorithm::RsaSign)> {}; | ||
struct grammar : must<created, days_valid, algorithm> {}; | ||
|
||
// Action | ||
template <typename Rule> | ||
struct action : nothing<Rule> {}; | ||
|
||
template <> | ||
struct action<created> | ||
: bind<V3PublicKeyData, uint32_t, &V3PublicKeyData::m_created> {}; | ||
|
||
template <> | ||
struct action<days_valid> | ||
: bind<V3PublicKeyData, uint16_t, &V3PublicKeyData::m_days_valid> {}; | ||
|
||
template <> | ||
struct action<algorithm> | ||
: bind<V3PublicKeyData, PublicKeyAlgorithm, &V3PublicKeyData::m_algorithm> { | ||
}; | ||
|
||
// Control | ||
template <typename Rule> | ||
struct control : pegtl::normal<Rule> { | ||
static const std::string error_message; | ||
|
||
template <typename Input, typename... States> | ||
static void raise(const Input& in, States&&...) { | ||
throw parser_error(error_message, in); | ||
} | ||
}; | ||
|
||
template <> | ||
const std::string control<created>::error_message = | ||
"v3 public key data is missing created time"; | ||
|
||
template <> | ||
const std::string control<days_valid>::error_message = | ||
"v3 public key data is missing days invalid"; | ||
|
||
template <> | ||
const std::string control<algorithm>::error_message = | ||
"v3 public key data has invalid algorithm specifier"; | ||
} // namespace v3_public_key_data | ||
|
||
std::unique_ptr<V3PublicKeyData> V3PublicKeyData::create_or_throw( | ||
ParserInput& in) { | ||
auto packet = make_unique<V3PublicKeyData>(); | ||
|
||
pegtl::parse<v3_public_key_data::grammar, v3_public_key_data::action, | ||
v3_public_key_data::control>(in.m_impl->m_input, *packet.get()); | ||
packet->m_key = PublicKeyMaterial::create_or_throw(packet->m_algorithm, in); | ||
|
||
return packet; | ||
} | ||
|
||
void V3PublicKeyData::write(std::ostream& out) const { | ||
out << static_cast<uint8_t>(m_created >> 24) | ||
<< static_cast<uint8_t>(m_created >> 16) | ||
<< static_cast<uint8_t>(m_created >> 8) | ||
<< static_cast<uint8_t>(m_created); | ||
out << static_cast<uint8_t>(m_days_valid >> 8) | ||
<< static_cast<uint8_t>(m_days_valid); | ||
out << static_cast<uint8_t>(m_algorithm); | ||
if (m_key) m_key->write(out); | ||
} | ||
|
||
std::vector<uint8_t> V3PublicKeyData::fingerprint() const { | ||
Botan::MD5 md5; | ||
auto rsa = dynamic_cast<RsaPublicKeyMaterial*>(m_key.get()); | ||
if (rsa) { | ||
md5.update(rsa->m_n.bits()); | ||
md5.update(rsa->m_e.bits()); | ||
} | ||
return md5.final_stdvec(); | ||
} | ||
|
||
std::vector<uint8_t> V3PublicKeyData::keyid() const { | ||
std::vector<uint8_t> keyid(KEYID_LENGTH, static_cast<uint8_t>(0x00)); | ||
auto rsa = dynamic_cast<RsaPublicKeyMaterial*>(m_key.get()); | ||
if (rsa) { | ||
const std::vector<uint8_t>& n = rsa->m_n.bits(); | ||
size_t len = std::min(keyid.size(), n.size()); | ||
std::copy_backward(n.end() - len, n.end(), keyid.end()); | ||
} | ||
return keyid; | ||
} | ||
|
||
} // namespace NeoPG |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// OpenPGP public key packet data v3 | ||
// Copyright 2018 The NeoPG developers | ||
// | ||
// NeoPG is released under the Simplified BSD License (see license.txt) | ||
|
||
/// \file | ||
/// This file contains the version 3 specific part of public key packets. | ||
|
||
#pragma once | ||
|
||
#include <neopg/public_key_data.h> | ||
|
||
namespace NeoPG { | ||
|
||
class NEOPG_UNSTABLE_API V3PublicKeyData : public PublicKeyData { | ||
public: | ||
/// Create new public key data from \p input. Throw an exception on error. | ||
/// | ||
/// \param input the parser input to read from | ||
/// | ||
/// \return pointer to packet | ||
/// | ||
/// \throws ParserError | ||
static std::unique_ptr<V3PublicKeyData> create_or_throw(ParserInput& input); | ||
|
||
/// The created timestamp. | ||
uint32_t m_created{0}; | ||
|
||
/// The number of days until expiration. | ||
uint16_t m_days_valid{0}; | ||
|
||
/// The algorithm identifier. | ||
PublicKeyAlgorithm m_algorithm{PublicKeyAlgorithm::Rsa}; | ||
|
||
/// The key material. | ||
std::unique_ptr<PublicKeyMaterial> m_key; | ||
|
||
/// Write the packet body to the output stream. | ||
/// | ||
/// \param out the output stream to write to | ||
void write(std::ostream& out) const override; | ||
|
||
/// Return the public key version. | ||
/// | ||
/// \return the value PublicKeyVersion::V3. | ||
PublicKeyVersion version() const noexcept override { | ||
return PublicKeyVersion::V3; | ||
} | ||
|
||
/// Return the public key fingerprint. | ||
std::vector<uint8_t> fingerprint() const override; | ||
|
||
/// The length of the keyid (8). | ||
static constexpr size_t KEYID_LENGTH{8}; | ||
|
||
/// Return the public key id. Can return a truncated string if the RSA | ||
/// parameter n is too short for a complete key id. | ||
std::vector<uint8_t> keyid() const override; | ||
|
||
/// Construct new v3 public key packet data. | ||
V3PublicKeyData() = default; | ||
}; | ||
|
||
} // namespace NeoPG |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// OpenPGP v3 public key packet data (tests) | ||
// Copyright 2018 The NeoPG developers | ||
// | ||
// NeoPG is released under the Simplified BSD License (see license.txt) | ||
|
||
#include <neopg/v3_public_key_data.h> | ||
|
||
#include <neopg/rsa_public_key_material.h> | ||
|
||
#include <neopg/intern/cplusplus.h> | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include <memory> | ||
#include <sstream> | ||
|
||
using namespace NeoPG; | ||
|
||
TEST(OpenpgpV3PublicKeyData, Create) { | ||
// Test V3 packets. | ||
const std::string raw{ | ||
"\x12\x34\x56\x78" | ||
"\xab\xcd" | ||
"\x01" | ||
"\x00\x11\x01\x42\x23" | ||
"\x00\x02\x03", | ||
15}; | ||
auto fpr = | ||
std::vector<uint8_t>{0xb5, 0xb5, 0xbe, 0xc2, 0x3d, 0x70, 0xea, 0x0e, | ||
0x05, 0x68, 0x45, 0x64, 0xac, 0xa7, 0x3d, 0xc7}; | ||
auto keyid = | ||
std::vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x23}; | ||
ParserInput in(raw.data(), raw.length()); | ||
auto key = PublicKeyData::create_or_throw(PublicKeyVersion::V3, in); | ||
ASSERT_EQ(key->version(), PublicKeyVersion::V3); | ||
auto v3key = dynamic_cast<V3PublicKeyData*>(key.get()); | ||
ASSERT_NE(v3key, nullptr); | ||
ASSERT_EQ(v3key->m_created, 0x12345678); | ||
ASSERT_EQ(v3key->m_days_valid, 0xabcd); | ||
ASSERT_EQ(v3key->m_algorithm, PublicKeyAlgorithm::Rsa); | ||
ASSERT_NE(v3key->m_key, nullptr); | ||
ASSERT_EQ(v3key->m_key->algorithm(), PublicKeyAlgorithm::Rsa); | ||
ASSERT_EQ(v3key->fingerprint(), fpr); | ||
ASSERT_EQ(v3key->keyid(), keyid); | ||
auto rsa = dynamic_cast<RsaPublicKeyMaterial*>(v3key->m_key.get()); | ||
ASSERT_EQ(rsa->m_n, MultiprecisionInteger(0x14223)); | ||
ASSERT_EQ(rsa->m_e, MultiprecisionInteger(0x3)); | ||
|
||
std::stringstream out; | ||
v3key->write(out); | ||
ASSERT_EQ(out.str(), raw); | ||
} | ||
|
||
TEST(OpenpgpV3PublicKeyData, KeyId) { | ||
V3PublicKeyData v3key; | ||
v3key.m_key = make_unique<RsaPublicKeyMaterial>(); | ||
auto rsa = dynamic_cast<RsaPublicKeyMaterial*>(v3key.m_key.get()); | ||
rsa->m_n.m_bits = std::vector<uint8_t>{0xff, 0x08, 0x07, 0x06, 0x05, | ||
0x04, 0x03, 0x02, 0x01, 0x00}; | ||
rsa->m_n.m_length = rsa->m_n.m_bits.size() * 8; | ||
auto keyid = | ||
std::vector<uint8_t>{0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; | ||
ASSERT_EQ(v3key.keyid(), keyid); | ||
} | ||
|
||
TEST(OpenpgpV3PublicKeyData, ShortKeyId) { | ||
V3PublicKeyData v3key; | ||
v3key.m_key = make_unique<RsaPublicKeyMaterial>(); | ||
auto rsa = dynamic_cast<RsaPublicKeyMaterial*>(v3key.m_key.get()); | ||
rsa->m_n.m_bits = std::vector<uint8_t>{0xff, 0x01, 0x00}; | ||
rsa->m_n.m_length = rsa->m_n.m_bits.size() * 8; | ||
auto keyid = | ||
std::vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00}; | ||
ASSERT_EQ(v3key.keyid(), keyid); | ||
} |
Oops, something went wrong.