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