xrpld
Loading...
Searching...
No Matches
Manifest.h
1#pragma once
2
3#include <xrpl/basics/UnorderedContainers.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/protocol/PublicKey.h>
6#include <xrpl/protocol/SecretKey.h>
7
8#include <optional>
9#include <shared_mutex>
10#include <string>
11#include <utility>
12
13namespace xrpl {
14
15/*
16 Validator key manifests
17 -----------------------
18
19 Suppose the secret keys installed on an XRPL validator are compromised. Not
20 only do you have to generate and install new key pairs on each validator,
21 EVERY xrpld needs to have its config updated with the new public keys, and
22 is vulnerable to forged validation signatures until this is done. The
23 solution is a new layer of indirection: A master secret key under
24 restrictive access control is used to sign a "manifest": essentially, a
25 certificate including the master public key, an ephemeral public key for
26 verifying validations (which will be signed by its secret counterpart), a
27 sequence number, and a digital signature.
28
29 The manifest has two serialized forms: one which includes the digital
30 signature and one which doesn't. There is an obvious causal dependency
31 relationship between the (latter) form with no signature, the signature
32 of that form, and the (former) form which includes that signature. In
33 other words, a message can't contain a signature of itself. The code
34 below stores a serialized manifest which includes the signature, and
35 dynamically generates the signatureless form when it needs to verify
36 the signature.
37
38 An instance of ManifestCache stores, for each trusted validator, (a) its
39 master public key, and (b) the most senior of all valid manifests it has
40 seen for that validator, if any. On startup, the [validator_token] config
41 entry (which contains the manifest for this validator) is decoded and
42 added to the manifest cache. Other manifests are added as "gossip"
43 received from xrpld peers.
44
45 When an ephemeral key is compromised, a new signing key pair is created,
46 along with a new manifest vouching for it (with a higher sequence number),
47 signed by the master key. When an xrpld peer receives the new manifest,
48 it verifies it with the master key and (assuming it's valid) discards the
49 old ephemeral key and stores the new one. If the master key itself gets
50 compromised, a manifest with sequence number 0xFFFFFFFF will supersede a
51 prior manifest and discard any existing ephemeral key without storing a
52 new one. These revocation manifests are loaded from the
53 [validator_key_revocation] config entry as well as received as gossip from
54 peers. Since no further manifests for this master key will be accepted
55 (since no higher sequence number is possible), and no signing key is on
56 record, no validations will be accepted from the compromised validator.
57*/
58
59//------------------------------------------------------------------------------
60
62{
65
68
70 // A revoked manifest does not have a signingKey
71 // This field is specified as "optional" in manifestFormat's
72 // SOTemplate
74
77
80
81 Manifest() = delete;
82
96
97 Manifest(Manifest const& other) = delete;
99 operator=(Manifest const& other) = delete;
100 Manifest(Manifest&& other) = default;
101 Manifest&
102 operator=(Manifest&& other) = default;
103
105 [[nodiscard]] bool
106 verify() const;
107
109 [[nodiscard]] uint256
110 hash() const;
111
113 // The maximum possible sequence number means that the master key has
114 // been revoked
115 static bool
117
119 [[nodiscard]] bool
120 revoked() const;
121
123 [[nodiscard]] std::optional<Blob>
124 getSignature() const;
125
127 [[nodiscard]] Blob
128 getMasterSignature() const;
129};
130
133to_string(Manifest const& m);
134
147
155
156template <
157 class T,
166
167
168inline bool
169operator==(Manifest const& lhs, Manifest const& rhs)
170{
171 // In theory, comparing the two serialized strings should be
172 // sufficient.
173 return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
174 lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
175 lhs.serialized == rhs.serialized;
176}
177
178inline bool
179operator!=(Manifest const& lhs, Manifest const& rhs)
180{
181 return !(lhs == rhs);
182}
183
189
192 std::vector<std::string> const& blob,
194
211
212inline std::string
214{
215 switch (m)
216 {
218 return "accepted";
220 return "stale";
222 return "badMasterKey";
224 return "badEphemeralKey";
226 return "invalid";
227 default:
228 return "unknown";
229 }
230}
231
232class DatabaseCon;
233
236{
237private:
240
243
246
248
249public:
253
256 sequence() const
257 {
258 return seq_.load();
259 }
260
272 getSigningKey(PublicKey const& pk) const;
273
285 getMasterKey(PublicKey const& pk) const;
286
293 getSequence(PublicKey const& pk) const;
294
301 getDomain(PublicKey const& pk) const;
302
309 getManifest(PublicKey const& pk) const;
310
319 bool
320 revoked(PublicKey const& pk) const;
321
335
352 bool
353 load(
354 DatabaseCon& dbCon,
355 std::string const& dbTable,
356 std::string const& configManifest,
357 std::vector<std::string> const& configRevocation);
358
369 void
370 load(DatabaseCon& dbCon, std::string const& dbTable);
371
382 void
383 save(
384 DatabaseCon& dbCon,
385 std::string const& dbTable,
386 std::function<bool(PublicKey const&)> const& isTrusted);
387
401 template <class Function>
402 void
403 forEachManifest(Function&& f) const
404 {
405 std::shared_lock const lock{mutex_};
406 for (auto const& [_, manifest] : map_)
407 {
408 (void)_;
409 f(manifest);
410 }
411 }
412
429 template <class PreFun, class EachFun>
430 void
431 forEachManifest(PreFun&& pf, EachFun&& f) const
432 {
433 std::shared_lock const lock{mutex_};
434 pf(map_.size());
435 for (auto const& [_, manifest] : map_)
436 {
437 (void)_;
438 f(manifest);
439 }
440 }
441};
442
443} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
static Sink & getNullSink()
Returns a Sink which does nothing.
void forEachManifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:403
std::atomic< std::uint32_t > seq_
Definition Manifest.h:247
std::shared_mutex mutex_
Definition Manifest.h:239
bool load(DatabaseCon &dbCon, std::string const &dbTable, std::string const &configManifest, std::vector< std::string > const &configRevocation)
Populate manifest cache with manifests in database and config.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
ManifestCache(beast::Journal j=beast::Journal(beast::Journal::getNullSink()))
Definition Manifest.h:250
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition Manifest.h:256
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition Manifest.h:245
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns manifest corresponding to a given public key.
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition Manifest.h:242
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
void forEachManifest(PreFun &&pf, EachFun &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:431
beast::Journal j_
Definition Manifest.h:238
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
A public key.
Definition PublicKey.h:42
A secret key.
Definition SecretKey.h:18
An immutable linear range of bytes.
Definition Slice.h:26
T is_same_v
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr bool operator==(BaseUInt< Bits, Tag > const &lhs, BaseUInt< Bits, Tag > const &rhs)
Definition base_uint.h:588
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
bool operator!=(Buffer const &lhs, Buffer const &rhs) noexcept
Definition Buffer.h:210
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:10
BaseUInt< 256 > uint256
Definition base_uint.h:562
std::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:215
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal=beast::Journal(beast::Journal::getNullSink()))
ManifestDisposition
Definition Manifest.h:195
@ BadMasterKey
The master key is not acceptable to us.
Definition Manifest.h:203
@ Accepted
Manifest is valid.
Definition Manifest.h:197
@ Invalid
Timely, but invalid signature.
Definition Manifest.h:209
@ BadEphemeralKey
The ephemeral key is not acceptable to us.
Definition Manifest.h:206
@ Stale
Sequence is too old.
Definition Manifest.h:200
Manifest(Manifest const &other)=delete
Manifest(std::string serialized, PublicKey const &masterKey, std::optional< PublicKey > const &signingKey, std::uint32_t seq, std::string domain)
Definition Manifest.h:83
Manifest & operator=(Manifest const &other)=delete
PublicKey masterKey
The master key associated with this manifest.
Definition Manifest.h:67
Manifest(Manifest &&other)=default
std::string serialized
The manifest in serialized form.
Definition Manifest.h:64
Blob getMasterSignature() const
Returns manifest master key signature.
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition Manifest.h:79
std::optional< Blob > getSignature() const
Returns manifest signature.
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Definition Manifest.h:73
std::uint32_t sequence
The sequence number of this manifest.
Definition Manifest.h:76
bool revoked() const
Returns true if manifest revokes master key.
uint256 hash() const
Returns hash of serialized manifest data.
bool verify() const
Returns true if manifest signature is valid.
Manifest & operator=(Manifest &&other)=default
Manifest()=delete
std::string manifest
Definition Manifest.h:186
SecretKey validationSecret
Definition Manifest.h:187