rippled
Loading...
Searching...
No Matches
Manifest.h
1#ifndef XRPL_APP_MISC_MANIFEST_H_INCLUDED
2#define XRPL_APP_MISC_MANIFEST_H_INCLUDED
3
4#include <xrpl/basics/UnorderedContainers.h>
5#include <xrpl/beast/utility/Journal.h>
6#include <xrpl/protocol/PublicKey.h>
7#include <xrpl/protocol/SecretKey.h>
8
9#include <optional>
10#include <shared_mutex>
11#include <string>
12
13namespace ripple {
14
15/*
16 Validator key manifests
17 -----------------------
18
19 Suppose the secret keys installed on a Ripple validator are compromised. Not
20 only do you have to generate and install new key pairs on each validator,
21 EVERY rippled 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 rippled 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 a rippled 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
84 std::string const& serialized_,
85 PublicKey const& masterKey_,
86 std::optional<PublicKey> const& signingKey_,
87 std::uint32_t seq,
88 std::string const& domain_)
89 : serialized(serialized_)
90 , masterKey(masterKey_)
91 , signingKey(signingKey_)
92 , sequence(seq)
93 , domain(domain_)
94 {
95 }
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 bool
106 verify() const;
107
109 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 bool
120 revoked() const;
121
124 getSignature() const;
125
127 Blob
128 getMasterSignature() const;
129};
130
133to_string(Manifest const& m);
134
147
155
156template <
157 class T,
158 class = std::enable_if_t<
169inline bool
170operator==(Manifest const& lhs, Manifest const& rhs)
171{
172 // In theory, comparing the two serialized strings should be
173 // sufficient.
174 return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
175 lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
176 lhs.serialized == rhs.serialized;
177}
178
179inline bool
180operator!=(Manifest const& lhs, Manifest const& rhs)
181{
182 return !(lhs == rhs);
183}
184
190
193 std::vector<std::string> const& blob,
195
198 accepted = 0,
199
201 stale,
202
205
208
210 invalid
211};
212
213inline std::string
215{
216 switch (m)
217 {
219 return "accepted";
221 return "stale";
223 return "badMasterKey";
225 return "badEphemeralKey";
227 return "invalid";
228 default:
229 return "unknown";
230 }
231}
232
233class DatabaseCon;
234
237{
238private:
241
244
247
249
250public:
256
259 sequence() const
260 {
261 return seq_.load();
262 }
263
275 getSigningKey(PublicKey const& pk) const;
276
288 getMasterKey(PublicKey const& pk) const;
289
296 getSequence(PublicKey const& pk) const;
297
304 getDomain(PublicKey const& pk) const;
305
312 getManifest(PublicKey const& pk) const;
313
322 bool
323 revoked(PublicKey const& pk) const;
324
338
355 bool
356 load(
357 DatabaseCon& dbCon,
358 std::string const& dbTable,
359 std::string const& configManifest,
360 std::vector<std::string> const& configRevocation);
361
372 void
373 load(DatabaseCon& dbCon, std::string const& dbTable);
374
385 void
386 save(
387 DatabaseCon& dbCon,
388 std::string const& dbTable,
389 std::function<bool(PublicKey const&)> const& isTrusted);
390
404 template <class Function>
405 void
406 for_each_manifest(Function&& f) const
407 {
409 for (auto const& [_, manifest] : map_)
410 {
411 (void)_;
412 f(manifest);
413 }
414 }
415
432 template <class PreFun, class EachFun>
433 void
434 for_each_manifest(PreFun&& pf, EachFun&& f) const
435 {
437 pf(map_.size());
438 for (auto const& [_, manifest] : map_)
439 {
440 (void)_;
441 f(manifest);
442 }
443 }
444};
445
446} // namespace ripple
447
448#endif
A generic endpoint for log messages.
Definition Journal.h:41
static Sink & getNullSink()
Returns a Sink which does nothing.
Remembers manifests with the highest sequence number.
Definition Manifest.h:237
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
Definition Manifest.cpp:316
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition Manifest.h:246
ManifestCache(beast::Journal j=beast::Journal(beast::Journal::getNullSink()))
Definition Manifest.h:251
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
Definition Manifest.cpp:340
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition Manifest.cpp:292
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition Manifest.h:259
std::shared_mutex mutex_
Definition Manifest.h:240
beast::Journal j_
Definition Manifest.h:239
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:406
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition Manifest.cpp:364
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition Manifest.h:243
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.
Definition Manifest.cpp:532
std::atomic< std::uint32_t > seq_
Definition Manifest.h:248
void for_each_manifest(PreFun &&pf, EachFun &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:434
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
Definition Manifest.cpp:589
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition Manifest.cpp:304
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Definition Manifest.cpp:328
A public key.
Definition PublicKey.h:43
A secret key.
Definition SecretKey.h:19
An immutable linear range of bytes.
Definition Slice.h:27
T load(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
Definition Manifest.cpp:35
bool operator!=(Buffer const &lhs, Buffer const &rhs) noexcept
Definition Buffer.h:213
ManifestDisposition
Definition Manifest.h:196
@ badMasterKey
The master key is not acceptable to us.
@ stale
Sequence is too old.
@ accepted
Manifest is valid.
@ badEphemeralKey
The ephemeral key is not acceptable to us.
@ invalid
Timely, but invalid signature.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:225
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
Definition Manifest.cpp:245
@ manifest
Manifest.
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:566
std::string serialized
The manifest in serialized form.
Definition Manifest.h:64
Manifest(std::string const &serialized_, PublicKey const &masterKey_, std::optional< PublicKey > const &signingKey_, std::uint32_t seq, std::string const &domain_)
Definition Manifest.h:83
std::uint32_t sequence
The sequence number of this manifest.
Definition Manifest.h:76
Manifest(Manifest &&other)=default
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition Manifest.h:79
bool revoked() const
Returns true if manifest revokes master key.
Definition Manifest.cpp:207
Manifest(Manifest const &other)=delete
bool verify() const
Returns true if manifest signature is valid.
Definition Manifest.cpp:177
Manifest & operator=(Manifest const &other)=delete
uint256 hash() const
Returns hash of serialized manifest data.
Definition Manifest.cpp:198
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition Manifest.cpp:225
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Definition Manifest.h:73
Blob getMasterSignature() const
Returns manifest master key signature.
Definition Manifest.cpp:236
PublicKey masterKey
The master key associated with this manifest.
Definition Manifest.h:67
Manifest & operator=(Manifest &&other)=default
std::string manifest
Definition Manifest.h:187
SecretKey validationSecret
Definition Manifest.h:188