xrpld
Loading...
Searching...
No Matches
libxrpl/protocol/Sign.cpp
1#include <xrpl/protocol/Sign.h>
2
3#include <xrpl/beast/utility/instrumentation.h>
4#include <xrpl/protocol/AccountID.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/HashPrefix.h>
7#include <xrpl/protocol/KeyType.h>
8#include <xrpl/protocol/PublicKey.h>
9#include <xrpl/protocol/Rules.h>
10#include <xrpl/protocol/SField.h>
11#include <xrpl/protocol/STExchange.h>
12#include <xrpl/protocol/STObject.h>
13#include <xrpl/protocol/SecretKey.h>
14#include <xrpl/protocol/Serializer.h>
15
16#include <optional>
17
18namespace xrpl {
19
20SField const*
22{
23 switch (role)
24 {
26 return nullptr;
28 return &sfCounterpartySignature;
30 return &sfSponsorSignature;
31 }
32 UNREACHABLE("xrpl::signatureField : unknown SignatureRole");
33 return nullptr;
34}
35
37signatureRole(SField const& sigField)
38{
39 if (sigField == sfCounterpartySignature)
41 if (sigField == sfSponsorSignature)
43 return std::nullopt;
44}
45
46// Signature validity depends on fixCleanup3_4_0: a role signature covers
47// different bytes before and after the amendment activates. checkValidity
48// caches its verdict per transaction ID, so it keeps two separate cache slots
49// for role-signature transactions (kSfSiggoodOldPrefix / kSfSigbadOldPrefix in
50// tx/apply.cpp) to keep a pre-fix verdict from being reused in the post-fix
51// era, and vice versa. See the block comment in tx/apply.cpp for the details
52// and the reason both directions matter.
54signingPrefix(SignatureRole role, bool multiSigning, Rules const& rules)
55{
56 // Before fixCleanup3_4_0 every signature on a transaction covered the same
57 // bytes, so a signature could be moved from one role to another.
58 if (!rules.enabled(fixCleanup3_4_0))
59 return multiSigning ? HashPrefix::TxMultiSign : HashPrefix::TxSign;
60
61 switch (role)
62 {
64 return multiSigning ? HashPrefix::TxMultiSign : HashPrefix::TxSign;
66 return multiSigning ? HashPrefix::CounterpartyTxMultiSign
70 }
71 UNREACHABLE("xrpl::signingPrefix : unknown SignatureRole");
72 return multiSigning ? HashPrefix::TxMultiSign : HashPrefix::TxSign;
73}
74
75void
77 STObject& st,
78 HashPrefix const& prefix,
79 KeyType type,
80 SecretKey const& sk,
81 SF_VL const& sigField)
82{
83 Serializer ss;
84 ss.add32(prefix);
86 set(st, sigField, sign(type, sk, ss.slice()));
87}
88
89bool
90verify(STObject const& st, HashPrefix const& prefix, PublicKey const& pk, SF_VL const& sigField)
91{
92 auto const sig = get(st, sigField);
93 if (!sig)
94 return false;
95 Serializer ss;
96 ss.add32(prefix);
98 return verify(pk, Slice(ss.data(), ss.size()), Slice(sig->data(), sig->size()));
99}
100
101// Questions regarding buildMultiSigningData:
102//
103// Why do we include the Signer.Account in the blob to be signed?
104//
105// Unless you include the Account which is signing in the signing blob,
106// you could swap out any Signer.Account for any other, which may also
107// be on the SignerList and have a RegularKey matching the
108// Signer.SigningPubKey.
109//
110// That RegularKey may be set to allow some 3rd party to sign transactions
111// on the account's behalf, and that RegularKey could be common amongst all
112// users of the 3rd party. That's just one example of sharing the same
113// RegularKey amongst various accounts and just one vulnerability.
114//
115// "When you have something that's easy to do that makes entire classes of
116// attacks clearly and obviously impossible, you need a damn good reason
117// not to do it." -- David Schwartz
118//
119// Why would we include the signingFor account in the blob to be signed?
120//
121// In the current signing scheme, the account that a signer is `signing
122// for/on behalf of` is the tx_json.Account.
123//
124// Later we might support more levels of signing. Suppose Bob is a signer
125// for Alice, and Carol is a signer for Bob, so Carol can sign for Bob who
126// signs for Alice. But suppose Alice has two signers: Bob and Dave. If
127// Carol is a signer for both Bob and Dave, then the signature needs to
128// distinguish between Carol signing for Bob and Carol signing for Dave.
129//
130// So, if we support multiple levels of signing, then we'll need to
131// incorporate the "signing for" accounts into the signing data as well.
132Serializer
133buildMultiSigningData(STObject const& obj, AccountID const& signingID, HashPrefix prefix)
134{
135 Serializer s{startMultiSigningData(obj, prefix)};
136 finishMultiSigningData(signingID, s);
137 return s;
138}
139
140Serializer
142{
143 Serializer s;
144 s.add32(prefix);
146 return s;
147}
148
149} // namespace xrpl
A public key.
Definition PublicKey.h:53
Rules controlling protocol behavior.
Definition Rules.h:40
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:182
Identifies fields.
Definition SField.h:132
void addWithoutSigningFields(Serializer &s) const
Definition STObject.h:994
A secret key.
Definition SecretKey.h:24
Slice slice() const noexcept
Definition Serializer.h:141
std::size_t size() const noexcept
Definition Serializer.h:147
void const * data() const noexcept
Definition Serializer.h:153
An immutable linear range of bytes.
Definition Slice.h:28
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
KeyType
Definition KeyType.h:8
Serializer startMultiSigningData(STObject const &obj, HashPrefix prefix)
Break the multi-signing hash computation into 2 parts for optimization.
std::optional< SignatureRole > signatureRole(SField const &sigField)
The role that signs into the given field.
HashPrefix signingPrefix(SignatureRole role, bool multiSigning, Rules const &rules)
The hash prefix that binds a transaction signature to the role that made it.
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
SField const * signatureField(SignatureRole role)
The field that holds this role's signature.
void finishMultiSigningData(AccountID const &signingID, Serializer &s)
Definition Sign.h:128
SignatureRole
The signature slots on a transaction.
Definition Sign.h:23
@ Transaction
The transaction's own signature, in sfTxnSignature or sfSigners.
Definition Sign.h:27
@ Sponsor
The sponsor's signature, in sfSponsorSignature.
Definition Sign.h:35
@ Counterparty
The counterparty's signature, in sfCounterpartySignature.
Definition Sign.h:31
TypedField< STBlob > SF_VL
Definition SField.h:362
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
HashPrefix
Prefix for hashing functions.
Definition HashPrefix.h:35
@ CounterpartyTxMultiSign
inner transaction to multi-sign as the counterparty
Definition HashPrefix.h:104
@ TxSign
inner transaction to sign
Definition HashPrefix.h:64
@ SponsorTxSign
inner transaction to sign as the sponsor
Definition HashPrefix.h:109
@ TxMultiSign
inner transaction to multi-sign
Definition HashPrefix.h:69
@ CounterpartyTxSign
inner transaction to sign as the counterparty
Definition HashPrefix.h:99
@ SponsorTxMultiSign
inner transaction to multi-sign as the sponsor
Definition HashPrefix.h:114
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
Serializer buildMultiSigningData(STObject const &obj, AccountID const &signingID, HashPrefix prefix)
Return a Serializer suitable for computing a multisigning TxnSignature.