rippled
PublicKey.cpp
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 #include <ripple/basics/contract.h>
21 #include <ripple/basics/strHex.h>
22 #include <ripple/protocol/PublicKey.h>
23 #include <ripple/protocol/digest.h>
24 #include <ripple/protocol/impl/secp256k1.h>
25 #include <boost/multiprecision/cpp_int.hpp>
26 #include <ed25519-donna/ed25519.h>
27 
28 namespace ripple {
29 
32 {
33  os << strHex(pk);
34  return os;
35 }
36 
37 template <>
40 {
41  auto const result = decodeBase58Token(s, type);
42  auto const pks = makeSlice(result);
43  if (!publicKeyType(pks))
44  return std::nullopt;
45  return PublicKey(pks);
46 }
47 
48 //------------------------------------------------------------------------------
49 
50 // Parse a length-prefixed number
51 // Format: 0x02 <length-byte> <number>
54 {
55  if (buf.size() < 3 || buf[0] != 0x02)
56  return std::nullopt;
57  auto const len = buf[1];
58  buf += 2;
59  if (len > buf.size() || len < 1 || len > 33)
60  return std::nullopt;
61  // Can't be negative
62  if ((buf[0] & 0x80) != 0)
63  return std::nullopt;
64  if (buf[0] == 0)
65  {
66  // Can't be zero
67  if (len == 1)
68  return std::nullopt;
69  // Can't be padded
70  if ((buf[1] & 0x80) == 0)
71  return std::nullopt;
72  }
73  std::optional<Slice> number = Slice(buf.data(), len);
74  buf += len;
75  return number;
76 }
77 
78 static std::string
79 sliceToHex(Slice const& slice)
80 {
81  std::string s;
82  if (slice[0] & 0x80)
83  {
84  s.reserve(2 * (slice.size() + 2));
85  s = "0x00";
86  }
87  else
88  {
89  s.reserve(2 * (slice.size() + 1));
90  s = "0x";
91  }
92  for (int i = 0; i < slice.size(); ++i)
93  {
94  s += "0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
95  s += "0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
96  }
97  return s;
98 }
99 
114 {
115  using uint264 =
116  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<
117  264,
118  264,
119  boost::multiprecision::signed_magnitude,
120  boost::multiprecision::unchecked,
121  void>>;
122 
123  static uint264 const G(
124  "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
125 
126  // The format of a signature should be:
127  // <30> <len> [ <02> <lenR> <R> ] [ <02> <lenS> <S> ]
128  if ((sig.size() < 8) || (sig.size() > 72))
129  return std::nullopt;
130  if ((sig[0] != 0x30) || (sig[1] != (sig.size() - 2)))
131  return std::nullopt;
132  Slice p = sig + 2;
133  auto r = sigPart(p);
134  auto s = sigPart(p);
135  if (!r || !s || !p.empty())
136  return std::nullopt;
137 
138  uint264 R(sliceToHex(*r));
139  if (R >= G)
140  return std::nullopt;
141 
142  uint264 S(sliceToHex(*s));
143  if (S >= G)
144  return std::nullopt;
145 
146  // (R,S) and (R,G-S) are canonical,
147  // but is fully canonical when S <= G-S
148  auto const Sp = G - S;
149  if (S > Sp)
152 }
153 
154 static bool
156 {
157  if (sig.size() != 64)
158  return false;
159  // Big-endian Order, the Ed25519 subgroup order
160  std::uint8_t const Order[] = {
161  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162  0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7,
163  0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED,
164  };
165  // Take the second half of signature
166  // and byte-reverse it to big-endian.
167  auto const le = sig.data() + 32;
168  std::uint8_t S[32];
169  std::reverse_copy(le, le + 32, S);
170  // Must be less than Order
171  return std::lexicographical_compare(S, S + 32, Order, Order + 32);
172 }
173 
174 //------------------------------------------------------------------------------
175 
177 {
178  if (!publicKeyType(slice))
179  LogicError("PublicKey::PublicKey invalid type");
180  size_ = slice.size();
182 }
183 
184 PublicKey::PublicKey(PublicKey const& other) : size_(other.size_)
185 {
186  if (size_)
187  std::memcpy(buf_, other.buf_, size_);
188 }
189 
190 PublicKey&
192 {
193  if (this != &other)
194  {
195  size_ = other.size_;
196  if (size_)
197  std::memcpy(buf_, other.buf_, size_);
198  }
199 
200  return *this;
201 }
202 
203 //------------------------------------------------------------------------------
204 
206 publicKeyType(Slice const& slice)
207 {
208  if (slice.size() == 33)
209  {
210  if (slice[0] == 0xED)
211  return KeyType::ed25519;
212 
213  if (slice[0] == 0x02 || slice[0] == 0x03)
214  return KeyType::secp256k1;
215  }
216 
217  return std::nullopt;
218 }
219 
220 bool
222  PublicKey const& publicKey,
223  uint256 const& digest,
224  Slice const& sig,
225  bool mustBeFullyCanonical) noexcept
226 {
227  if (publicKeyType(publicKey) != KeyType::secp256k1)
228  LogicError("sign: secp256k1 required for digest signing");
229  auto const canonicality = ecdsaCanonicality(sig);
230  if (!canonicality)
231  return false;
232  if (mustBeFullyCanonical &&
233  (*canonicality != ECDSACanonicality::fullyCanonical))
234  return false;
235 
236  secp256k1_pubkey pubkey_imp;
237  if (secp256k1_ec_pubkey_parse(
239  &pubkey_imp,
240  reinterpret_cast<unsigned char const*>(publicKey.data()),
241  publicKey.size()) != 1)
242  return false;
243 
244  secp256k1_ecdsa_signature sig_imp;
245  if (secp256k1_ecdsa_signature_parse_der(
247  &sig_imp,
248  reinterpret_cast<unsigned char const*>(sig.data()),
249  sig.size()) != 1)
250  return false;
251  if (*canonicality != ECDSACanonicality::fullyCanonical)
252  {
253  secp256k1_ecdsa_signature sig_norm;
254  if (secp256k1_ecdsa_signature_normalize(
255  secp256k1Context(), &sig_norm, &sig_imp) != 1)
256  return false;
257  return secp256k1_ecdsa_verify(
259  &sig_norm,
260  reinterpret_cast<unsigned char const*>(digest.data()),
261  &pubkey_imp) == 1;
262  }
263  return secp256k1_ecdsa_verify(
265  &sig_imp,
266  reinterpret_cast<unsigned char const*>(digest.data()),
267  &pubkey_imp) == 1;
268 }
269 
270 bool
272  PublicKey const& publicKey,
273  Slice const& m,
274  Slice const& sig,
275  bool mustBeFullyCanonical) noexcept
276 {
277  if (auto const type = publicKeyType(publicKey))
278  {
279  if (*type == KeyType::secp256k1)
280  {
281  return verifyDigest(
282  publicKey, sha512Half(m), sig, mustBeFullyCanonical);
283  }
284  else if (*type == KeyType::ed25519)
285  {
286  if (!ed25519Canonical(sig))
287  return false;
288 
289  // We internally prefix Ed25519 keys with a 0xED
290  // byte to distinguish them from secp256k1 keys
291  // so when verifying the signature, we need to
292  // first strip that prefix.
293  return ed25519_sign_open(
294  m.data(), m.size(), publicKey.data() + 1, sig.data()) ==
295  0;
296  }
297  }
298  return false;
299 }
300 
301 NodeID
303 {
304  static_assert(NodeID::bytes == sizeof(ripesha_hasher::result_type));
305 
306  ripesha_hasher h;
307  h(pk.data(), pk.size());
308  return NodeID{static_cast<ripesha_hasher::result_type>(h)};
309 }
310 
311 } // namespace ripple
ripple::PublicKey::data
std::uint8_t const * data() const noexcept
Definition: PublicKey.h:81
ripple::Slice::size
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:80
std::reverse_copy
T reverse_copy(T... args)
ripple::makeSlice
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:241
ripple::PublicKey::PublicKey
PublicKey()=default
std::string
STL class.
ripple::calcNodeID
NodeID calcNodeID(PublicKey const &pk)
Calculate the 160-bit node ID from a node public key.
Definition: PublicKey.cpp:302
ripple::NodeID
base_uint< 160, detail::NodeIDTag > NodeID
NodeID is a 160-bit hash representing one node.
Definition: UintTypes.h:59
ripple::sliceToHex
static std::string sliceToHex(Slice const &slice)
Definition: PublicKey.cpp:79
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::string::reserve
T reserve(T... args)
ripple::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical) noexcept
Verify a signature on a message.
Definition: PublicKey.cpp:271
ripple::sigPart
static std::optional< Slice > sigPart(Slice &buf)
Definition: PublicKey.cpp:53
ripple::Slice::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Slice.h:97
ripple::decodeBase58Token
std::string decodeBase58Token(std::string const &s, TokenType type)
Decode a token of given type encoded using Base58Check and the XRPL alphabet.
Definition: tokens.cpp:223
ripple::PublicKey::slice
Slice slice() const noexcept
Definition: PublicKey.h:123
ripple::Slice::empty
bool empty() const noexcept
Return true if the byte range is empty.
Definition: Slice.h:69
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
ripple::ECDSACanonicality::fullyCanonical
@ fullyCanonical
ripple::secp256k1Context
secp256k1_context const * secp256k1Context()
Definition: secp256k1.h:29
ripple::digest
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition: tokens.cpp:47
ripple::KeyType::ed25519
@ ed25519
ripple::publicKeyType
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:206
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:81
ripple::base_uint< 160, detail::NodeIDTag >::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:104
ripple::ripesha_hasher
Returns the RIPEMD-160 digest of the SHA256 hash of the message.
Definition: digest.h:131
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::TokenType
TokenType
Definition: tokens.h:29
ripple::PublicKey::size
std::size_t size() const noexcept
Definition: PublicKey.h:87
std::ostream
STL class.
ripple::PublicKey::size_
std::size_t size_
Definition: PublicKey.h:62
std::lexicographical_compare
T lexicographical_compare(T... args)
ripple::ecdsaCanonicality
std::optional< ECDSACanonicality > ecdsaCanonicality(Slice const &sig)
Determine whether a signature is canonical.
Definition: PublicKey.cpp:113
std::array
STL class.
std::uint8_t
ripple::PublicKey::operator=
PublicKey & operator=(PublicKey const &other)
Definition: PublicKey.cpp:191
ripple::ECDSACanonicality::canonical
@ canonical
ripple::KeyType::secp256k1
@ secp256k1
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
ripple::verifyDigest
bool verifyDigest(PublicKey const &publicKey, uint256 const &digest, Slice const &sig, bool mustBeFullyCanonical) noexcept
Verify a secp256k1 signature on the digest of a message.
Definition: PublicKey.cpp:221
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
std::optional
ripple::PublicKey::buf_
std::uint8_t buf_[33]
Definition: PublicKey.h:63
std::memcpy
T memcpy(T... args)
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
ripple::ed25519Canonical
static bool ed25519Canonical(Slice const &sig)
Definition: PublicKey.cpp:155
ripple::parseBase58
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
Definition: AccountID.cpp:114