rippled
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
12namespace xrpl {
13
14/*
15 Validator key manifests
16 -----------------------
17
18 Suppose the secret keys installed on a Ripple validator are compromised. Not
19 only do you have to generate and install new key pairs on each validator,
20 EVERY rippled needs to have its config updated with the new public keys, and
21 is vulnerable to forged validation signatures until this is done. The
22 solution is a new layer of indirection: A master secret key under
23 restrictive access control is used to sign a "manifest": essentially, a
24 certificate including the master public key, an ephemeral public key for
25 verifying validations (which will be signed by its secret counterpart), a
26 sequence number, and a digital signature.
27
28 The manifest has two serialized forms: one which includes the digital
29 signature and one which doesn't. There is an obvious causal dependency
30 relationship between the (latter) form with no signature, the signature
31 of that form, and the (former) form which includes that signature. In
32 other words, a message can't contain a signature of itself. The code
33 below stores a serialized manifest which includes the signature, and
34 dynamically generates the signatureless form when it needs to verify
35 the signature.
36
37 An instance of ManifestCache stores, for each trusted validator, (a) its
38 master public key, and (b) the most senior of all valid manifests it has
39 seen for that validator, if any. On startup, the [validator_token] config
40 entry (which contains the manifest for this validator) is decoded and
41 added to the manifest cache. Other manifests are added as "gossip"
42 received from rippled peers.
43
44 When an ephemeral key is compromised, a new signing key pair is created,
45 along with a new manifest vouching for it (with a higher sequence number),
46 signed by the master key. When a rippled peer receives the new manifest,
47 it verifies it with the master key and (assuming it's valid) discards the
48 old ephemeral key and stores the new one. If the master key itself gets
49 compromised, a manifest with sequence number 0xFFFFFFFF will supersede a
50 prior manifest and discard any existing ephemeral key without storing a
51 new one. These revocation manifests are loaded from the
52 [validator_key_revocation] config entry as well as received as gossip from
53 peers. Since no further manifests for this master key will be accepted
54 (since no higher sequence number is possible), and no signing key is on
55 record, no validations will be accepted from the compromised validator.
56*/
57
58//------------------------------------------------------------------------------
59
61{
64
67
69 // A revoked manifest does not have a signingKey
70 // This field is specified as "optional" in manifestFormat's
71 // SOTemplate
73
76
79
80 Manifest() = delete;
81
83 std::string const& serialized_,
84 PublicKey const& masterKey_,
85 std::optional<PublicKey> const& signingKey_,
86 std::uint32_t seq,
87 std::string const& domain_)
88 : serialized(serialized_), masterKey(masterKey_), signingKey(signingKey_), sequence(seq), domain(domain_)
89 {
90 }
91
92 Manifest(Manifest const& other) = delete;
94 operator=(Manifest const& other) = delete;
95 Manifest(Manifest&& other) = default;
97 operator=(Manifest&& other) = default;
98
100 bool
101 verify() const;
102
104 uint256
105 hash() const;
106
108 // The maximum possible sequence number means that the master key has
109 // been revoked
110 static bool
112
114 bool
115 revoked() const;
116
119 getSignature() const;
120
122 Blob
123 getMasterSignature() const;
124};
125
128to_string(Manifest const& m);
129
142
148
149template <class T, class = std::enable_if_t<std::is_same<T, char>::value || std::is_same<T, unsigned char>::value>>
157inline bool
158operator==(Manifest const& lhs, Manifest const& rhs)
159{
160 // In theory, comparing the two serialized strings should be
161 // sufficient.
162 return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey && lhs.signingKey == rhs.signingKey &&
163 lhs.domain == rhs.domain && lhs.serialized == rhs.serialized;
164}
165
166inline bool
167operator!=(Manifest const& lhs, Manifest const& rhs)
168{
169 return !(lhs == rhs);
170}
171
177
180 std::vector<std::string> const& blob,
182
185 accepted = 0,
186
188 stale,
189
192
195
197 invalid
198};
199
200inline std::string
202{
203 switch (m)
204 {
206 return "accepted";
208 return "stale";
210 return "badMasterKey";
212 return "badEphemeralKey";
214 return "invalid";
215 default:
216 return "unknown";
217 }
218}
219
220class DatabaseCon;
221
224{
225private:
228
231
234
236
237public:
241
244 sequence() const
245 {
246 return seq_.load();
247 }
248
260 getSigningKey(PublicKey const& pk) const;
261
273 getMasterKey(PublicKey const& pk) const;
274
281 getSequence(PublicKey const& pk) const;
282
289 getDomain(PublicKey const& pk) const;
290
297 getManifest(PublicKey const& pk) const;
298
307 bool
308 revoked(PublicKey const& pk) const;
309
323
340 bool
341 load(
342 DatabaseCon& dbCon,
343 std::string const& dbTable,
344 std::string const& configManifest,
345 std::vector<std::string> const& configRevocation);
346
357 void
358 load(DatabaseCon& dbCon, std::string const& dbTable);
359
370 void
371 save(DatabaseCon& dbCon, std::string const& dbTable, std::function<bool(PublicKey const&)> const& isTrusted);
372
386 template <class Function>
387 void
388 for_each_manifest(Function&& f) const
389 {
391 for (auto const& [_, manifest] : map_)
392 {
393 (void)_;
394 f(manifest);
395 }
396 }
397
414 template <class PreFun, class EachFun>
415 void
416 for_each_manifest(PreFun&& pf, EachFun&& f) const
417 {
419 pf(map_.size());
420 for (auto const& [_, manifest] : map_)
421 {
422 (void)_;
423 f(manifest);
424 }
425 }
426};
427
428} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
static Sink & getNullSink()
Returns a Sink which does nothing.
Remembers manifests with the highest sequence number.
Definition Manifest.h:224
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:388
std::atomic< std::uint32_t > seq_
Definition Manifest.h:235
std::shared_mutex mutex_
Definition Manifest.h:227
void for_each_manifest(PreFun &&pf, EachFun &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:416
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:494
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition Manifest.cpp:272
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition Manifest.cpp:343
ManifestCache(beast::Journal j=beast::Journal(beast::Journal::getNullSink()))
Definition Manifest.h:238
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Definition Manifest.cpp:307
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition Manifest.cpp:284
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition Manifest.h:244
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition Manifest.h:233
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns manifest corresponding to a given public key.
Definition Manifest.cpp:319
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition Manifest.h:230
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
Definition Manifest.cpp:295
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
Definition Manifest.cpp:548
beast::Journal j_
Definition Manifest.h:226
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 load(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:597
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:552
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
Definition Manifest.cpp:34
bool operator!=(Buffer const &lhs, Buffer const &rhs) noexcept
Definition Buffer.h:209
@ manifest
Manifest.
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:213
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal=beast::Journal(beast::Journal::getNullSink()))
Definition Manifest.cpp:229
ManifestDisposition
Definition Manifest.h:183
@ 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.
Manifest(Manifest const &other)=delete
Manifest & operator=(Manifest const &other)=delete
PublicKey masterKey
The master key associated with this manifest.
Definition Manifest.h:66
Manifest(Manifest &&other)=default
std::string serialized
The manifest in serialized form.
Definition Manifest.h:63
Blob getMasterSignature() const
Returns manifest master key signature.
Definition Manifest.cpp:220
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition Manifest.h:78
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition Manifest.cpp:209
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Definition Manifest.h:72
std::uint32_t sequence
The sequence number of this manifest.
Definition Manifest.h:75
bool revoked() const
Returns true if manifest revokes master key.
Definition Manifest.cpp:191
uint256 hash() const
Returns hash of serialized manifest data.
Definition Manifest.cpp:182
bool verify() const
Returns true if manifest signature is valid.
Definition Manifest.cpp:162
Manifest & operator=(Manifest &&other)=default
Manifest()=delete
Manifest(std::string const &serialized_, PublicKey const &masterKey_, std::optional< PublicKey > const &signingKey_, std::uint32_t seq, std::string const &domain_)
Definition Manifest.h:82
std::string manifest
Definition Manifest.h:174
SecretKey validationSecret
Definition Manifest.h:175