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 
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 (slice.size() < size_)
179  LogicError(
180  "PublicKey::PublicKey - Input slice cannot be an undersized "
181  "buffer");
182 
183  if (!publicKeyType(slice))
184  LogicError("PublicKey::PublicKey invalid type");
186 }
187 
189 {
190  std::memcpy(buf_, other.buf_, size_);
191 }
192 
193 PublicKey&
195 {
196  if (this != &other)
197  {
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:87
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
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: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:272
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)
Definition: tokens.cpp:205
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:303
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:152
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:61
ripple::TokenType
TokenType
Definition: tokens.h:38
ripple::PublicKey::size
std::size_t size() const noexcept
Definition: PublicKey.h:93
std::ostream
STL class.
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::buf_
std::uint8_t buf_[size_]
Definition: PublicKey.h:67
ripple::PublicKey::operator=
PublicKey & operator=(PublicKey const &other)
Definition: PublicKey.cpp:194
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::PublicKey::PublicKey
PublicKey()=delete
ripple::PublicKey::size_
static constexpr std::size_t size_
Definition: PublicKey.h:66
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:47
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
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