Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
key_store.hpp
Go to the documentation of this file.
1#pragma once
2
3// Signing-key material + a file-backed store for the swap-pack signing flow. The
4// key is an Ed25519 keypair; it is serialized as a small text blob (base64 public +
5// private) so it can live in a file OR a keychain/GitHub secret (same bytes, same
6// parse). load_or_generate_file() reuses an existing key and NEVER silently makes a
7// second one — a plugin's key is its identity. The caller prints the loud
8// provenance banner when `generated` comes back true.
9
12
13#include <filesystem>
14#include <fstream>
15#include <optional>
16#include <string>
17#include <string_view>
18#include <vector>
19
20namespace pulp::format::reload {
21
23 std::vector<std::uint8_t> public_key;
24 std::vector<std::uint8_t> private_key;
25 bool valid() const { return !public_key.empty() && !private_key.empty(); }
26};
27
28inline constexpr std::string_view kKeyBlobMagic = "PULP-RELOAD-KEY-v1";
29
31inline std::string serialize_key_blob(const KeyMaterial& k) {
32 return std::string(kKeyBlobMagic) + "\n" +
33 runtime::base64_encode(k.public_key.data(), k.public_key.size()) + "\n" +
34 runtime::base64_encode(k.private_key.data(), k.private_key.size()) + "\n";
35}
36
39inline std::optional<KeyMaterial> parse_key_blob(std::string_view blob) {
40 auto next_line = [&](std::size_t& pos) -> std::string_view {
41 const std::size_t nl = blob.find('\n', pos);
42 const std::size_t end = nl == std::string_view::npos ? blob.size() : nl;
43 std::string_view line = blob.substr(pos, end - pos);
44 pos = nl == std::string_view::npos ? blob.size() : nl + 1;
45 // trim a trailing CR (tolerate CRLF).
46 if (!line.empty() && line.back() == '\r') line.remove_suffix(1);
47 return line;
48 };
49 std::size_t pos = 0;
50 if (next_line(pos) != kKeyBlobMagic) return std::nullopt;
51 const std::string_view pub_b64 = next_line(pos);
52 const std::string_view priv_b64 = next_line(pos);
53 auto pub = runtime::base64_decode(pub_b64);
54 auto priv = runtime::base64_decode(priv_b64);
55 if (!pub || !priv || pub->empty() || priv->empty()) return std::nullopt;
56 return KeyMaterial{std::move(*pub), std::move(*priv)};
57}
58
63inline std::optional<KeyMaterial> load_or_generate_key_file(const std::filesystem::path& path,
64 bool& generated) {
65 generated = false;
66 std::error_code ec;
67 if (std::filesystem::exists(path, ec)) {
68 std::ifstream in(path, std::ios::binary);
69 std::string blob((std::istreambuf_iterator<char>(in)),
70 std::istreambuf_iterator<char>());
71 return parse_key_blob(blob); // nullopt on corruption → caller errors, no regen
72 }
74 if (!kp) return std::nullopt;
75 KeyMaterial km{kp->public_key, kp->private_key};
76 std::filesystem::create_directories(path.parent_path(), ec);
77 {
78 std::ofstream out(path, std::ios::binary | std::ios::trunc);
79 if (!out) return std::nullopt;
80 out << serialize_key_blob(km);
81 }
82 std::filesystem::permissions(path, std::filesystem::perms::owner_read |
83 std::filesystem::perms::owner_write,
84 std::filesystem::perm_options::replace, ec);
85 generated = true;
86 return km;
87}
88
89} // namespace pulp::format::reload
Definition build_fingerprint.hpp:23
std::string serialize_key_blob(const KeyMaterial &k)
Serialize a keypair to a text blob: magic line, base64 public, base64 private.
Definition key_store.hpp:31
constexpr std::string_view kKeyBlobMagic
Definition key_store.hpp:28
std::optional< KeyMaterial > parse_key_blob(std::string_view blob)
Parse a key blob.
Definition key_store.hpp:39
std::optional< KeyMaterial > load_or_generate_key_file(const std::filesystem::path &path, bool &generated)
Load the key at path, or generate a fresh keypair, write it there (0600), and return it with generate...
Definition key_store.hpp:63
@ end
Definition editor_host.hpp:354
std::optional< Ed25519KeyPair > ed25519_keypair_generate()
Generate a fresh Ed25519 keypair using mbedTLS CTR-DRBG for entropy.
std::optional< std::vector< uint8_t > > base64_decode(std::string_view input)
Decode base64 string to binary data. Returns nullopt on invalid input.
std::string base64_encode(const uint8_t *data, size_t length)
Encode binary data to base64 string.
Definition key_store.hpp:22
std::vector< std::uint8_t > public_key
Definition key_store.hpp:23
std::vector< std::uint8_t > private_key
Definition key_store.hpp:24
bool valid() const
Definition key_store.hpp:25