rippled
Loading...
Searching...
No Matches
Manifest.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_APP_MISC_MANIFEST_H_INCLUDED
21#define RIPPLE_APP_MISC_MANIFEST_H_INCLUDED
22
23#include <xrpl/basics/UnorderedContainers.h>
24#include <xrpl/beast/utility/Journal.h>
25#include <xrpl/protocol/PublicKey.h>
26#include <xrpl/protocol/SecretKey.h>
27
28#include <optional>
29#include <shared_mutex>
30#include <string>
31
32namespace ripple {
33
34/*
35 Validator key manifests
36 -----------------------
37
38 Suppose the secret keys installed on a Ripple validator are compromised. Not
39 only do you have to generate and install new key pairs on each validator,
40 EVERY rippled needs to have its config updated with the new public keys, and
41 is vulnerable to forged validation signatures until this is done. The
42 solution is a new layer of indirection: A master secret key under
43 restrictive access control is used to sign a "manifest": essentially, a
44 certificate including the master public key, an ephemeral public key for
45 verifying validations (which will be signed by its secret counterpart), a
46 sequence number, and a digital signature.
47
48 The manifest has two serialized forms: one which includes the digital
49 signature and one which doesn't. There is an obvious causal dependency
50 relationship between the (latter) form with no signature, the signature
51 of that form, and the (former) form which includes that signature. In
52 other words, a message can't contain a signature of itself. The code
53 below stores a serialized manifest which includes the signature, and
54 dynamically generates the signatureless form when it needs to verify
55 the signature.
56
57 An instance of ManifestCache stores, for each trusted validator, (a) its
58 master public key, and (b) the most senior of all valid manifests it has
59 seen for that validator, if any. On startup, the [validator_token] config
60 entry (which contains the manifest for this validator) is decoded and
61 added to the manifest cache. Other manifests are added as "gossip"
62 received from rippled peers.
63
64 When an ephemeral key is compromised, a new signing key pair is created,
65 along with a new manifest vouching for it (with a higher sequence number),
66 signed by the master key. When a rippled peer receives the new manifest,
67 it verifies it with the master key and (assuming it's valid) discards the
68 old ephemeral key and stores the new one. If the master key itself gets
69 compromised, a manifest with sequence number 0xFFFFFFFF will supersede a
70 prior manifest and discard any existing ephemeral key without storing a
71 new one. These revocation manifests are loaded from the
72 [validator_key_revocation] config entry as well as received as gossip from
73 peers. Since no further manifests for this master key will be accepted
74 (since no higher sequence number is possible), and no signing key is on
75 record, no validations will be accepted from the compromised validator.
76*/
77
78//------------------------------------------------------------------------------
79
81{
84
87
89 // A revoked manifest does not have a signingKey
90 // This field is specified as "optional" in manifestFormat's
91 // SOTemplate
93
96
99
100 Manifest() = delete;
101
103 std::string const& serialized_,
104 PublicKey const& masterKey_,
105 std::optional<PublicKey> const& signingKey_,
106 std::uint32_t seq,
107 std::string const& domain_)
108 : serialized(serialized_)
109 , masterKey(masterKey_)
110 , signingKey(signingKey_)
111 , sequence(seq)
112 , domain(domain_)
113 {
114 }
115
116 Manifest(Manifest const& other) = delete;
117 Manifest&
118 operator=(Manifest const& other) = delete;
119 Manifest(Manifest&& other) = default;
120 Manifest&
121 operator=(Manifest&& other) = default;
122
124 bool
125 verify() const;
126
128 uint256
129 hash() const;
130
132 // The maximum possible sequence number means that the master key has
133 // been revoked
134 static bool
136
138 bool
139 revoked() const;
140
143 getSignature() const;
144
146 Blob
147 getMasterSignature() const;
148};
149
152to_string(Manifest const& m);
153
166
174
175template <
176 class T,
177 class = std::enable_if_t<
188inline bool
189operator==(Manifest const& lhs, Manifest const& rhs)
190{
191 // In theory, comparing the two serialized strings should be
192 // sufficient.
193 return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
194 lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
195 lhs.serialized == rhs.serialized;
196}
197
198inline bool
199operator!=(Manifest const& lhs, Manifest const& rhs)
200{
201 return !(lhs == rhs);
202}
203
209
212 std::vector<std::string> const& blob,
214
217 accepted = 0,
218
220 stale,
221
224
227
229 invalid
230};
231
232inline std::string
234{
235 switch (m)
236 {
238 return "accepted";
240 return "stale";
242 return "badMasterKey";
244 return "badEphemeralKey";
246 return "invalid";
247 default:
248 return "unknown";
249 }
250}
251
252class DatabaseCon;
253
256{
257private:
260
263
266
268
269public:
275
278 sequence() const
279 {
280 return seq_.load();
281 }
282
294 getSigningKey(PublicKey const& pk) const;
295
307 getMasterKey(PublicKey const& pk) const;
308
315 getSequence(PublicKey const& pk) const;
316
323 getDomain(PublicKey const& pk) const;
324
331 getManifest(PublicKey const& pk) const;
332
341 bool
342 revoked(PublicKey const& pk) const;
343
357
374 bool
375 load(
376 DatabaseCon& dbCon,
377 std::string const& dbTable,
378 std::string const& configManifest,
379 std::vector<std::string> const& configRevocation);
380
391 void
392 load(DatabaseCon& dbCon, std::string const& dbTable);
393
404 void
405 save(
406 DatabaseCon& dbCon,
407 std::string const& dbTable,
408 std::function<bool(PublicKey const&)> const& isTrusted);
409
423 template <class Function>
424 void
425 for_each_manifest(Function&& f) const
426 {
428 for (auto const& [_, manifest] : map_)
429 {
430 (void)_;
431 f(manifest);
432 }
433 }
434
451 template <class PreFun, class EachFun>
452 void
453 for_each_manifest(PreFun&& pf, EachFun&& f) const
454 {
456 pf(map_.size());
457 for (auto const& [_, manifest] : map_)
458 {
459 (void)_;
460 f(manifest);
461 }
462 }
463};
464
465} // namespace ripple
466
467#endif
A generic endpoint for log messages.
Definition Journal.h:60
static Sink & getNullSink()
Returns a Sink which does nothing.
Remembers manifests with the highest sequence number.
Definition Manifest.h:256
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
Definition Manifest.cpp:335
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition Manifest.h:265
ManifestCache(beast::Journal j=beast::Journal(beast::Journal::getNullSink()))
Definition Manifest.h:270
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
Definition Manifest.cpp:359
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition Manifest.cpp:311
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition Manifest.h:278
std::shared_mutex mutex_
Definition Manifest.h:259
beast::Journal j_
Definition Manifest.h:258
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:425
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition Manifest.cpp:383
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition Manifest.h:262
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:551
std::atomic< std::uint32_t > seq_
Definition Manifest.h:267
void for_each_manifest(PreFun &&pf, EachFun &&f) const
Invokes the callback once for every populated manifest.
Definition Manifest.h:453
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
Definition Manifest.cpp:608
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition Manifest.cpp:323
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Definition Manifest.cpp:347
A public key.
Definition PublicKey.h:62
A secret key.
Definition SecretKey.h:38
An immutable linear range of bytes.
Definition Slice.h:46
T load(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
Definition Manifest.cpp:54
bool operator!=(Buffer const &lhs, Buffer const &rhs) noexcept
Definition Buffer.h:232
ManifestDisposition
Definition Manifest.h:215
@ 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:244
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
Definition Manifest.cpp:264
@ manifest
Manifest.
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:585
std::string serialized
The manifest in serialized form.
Definition Manifest.h:83
Manifest(std::string const &serialized_, PublicKey const &masterKey_, std::optional< PublicKey > const &signingKey_, std::uint32_t seq, std::string const &domain_)
Definition Manifest.h:102
std::uint32_t sequence
The sequence number of this manifest.
Definition Manifest.h:95
Manifest(Manifest &&other)=default
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition Manifest.h:98
bool revoked() const
Returns true if manifest revokes master key.
Definition Manifest.cpp:226
Manifest(Manifest const &other)=delete
bool verify() const
Returns true if manifest signature is valid.
Definition Manifest.cpp:196
Manifest & operator=(Manifest const &other)=delete
uint256 hash() const
Returns hash of serialized manifest data.
Definition Manifest.cpp:217
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition Manifest.cpp:244
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Definition Manifest.h:92
Blob getMasterSignature() const
Returns manifest master key signature.
Definition Manifest.cpp:255
PublicKey masterKey
The master key associated with this manifest.
Definition Manifest.h:86
Manifest & operator=(Manifest &&other)=default
std::string manifest
Definition Manifest.h:206
SecretKey validationSecret
Definition Manifest.h:207