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 #include <type_traits>
28 
29 namespace ripple {
30 
33 {
34  os << strHex(pk);
35  return os;
36 }
37 
38 template <>
39 boost::optional<PublicKey>
41 {
42  auto const result = decodeBase58Token(s, type);
43  auto const pks = makeSlice(result);
44  if (!publicKeyType(pks))
45  return boost::none;
46  return PublicKey(pks);
47 }
48 
49 //------------------------------------------------------------------------------
50 
51 // Parse a length-prefixed number
52 // Format: 0x02 <length-byte> <number>
53 static boost::optional<Slice>
55 {
56  if (buf.size() < 3 || buf[0] != 0x02)
57  return boost::none;
58  auto const len = buf[1];
59  buf += 2;
60  if (len > buf.size() || len < 1 || len > 33)
61  return boost::none;
62  // Can't be negative
63  if ((buf[0] & 0x80) != 0)
64  return boost::none;
65  if (buf[0] == 0)
66  {
67  // Can't be zero
68  if (len == 1)
69  return boost::none;
70  // Can't be padded
71  if ((buf[1] & 0x80) == 0)
72  return boost::none;
73  }
74  boost::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 
113 boost::optional<ECDSACanonicality>
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 boost::none;
131  if ((sig[0] != 0x30) || (sig[1] != (sig.size() - 2)))
132  return boost::none;
133  Slice p = sig + 2;
134  auto r = sigPart(p);
135  auto s = sigPart(p);
136  if (!r || !s || !p.empty())
137  return boost::none;
138 
139  uint264 R(sliceToHex(*r));
140  if (R >= G)
141  return boost::none;
142 
143  uint264 S(sliceToHex(*s));
144  if (S >= G)
145  return boost::none;
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  size_ = other.size_;
195  if (size_)
196  std::memcpy(buf_, other.buf_, size_);
197  return *this;
198 }
199 
200 //------------------------------------------------------------------------------
201 
202 boost::optional<KeyType>
203 publicKeyType(Slice const& slice)
204 {
205  if (slice.size() == 33)
206  {
207  if (slice[0] == 0xED)
208  return KeyType::ed25519;
209 
210  if (slice[0] == 0x02 || slice[0] == 0x03)
211  return KeyType::secp256k1;
212  }
213 
214  return boost::none;
215 }
216 
217 bool
219  PublicKey const& publicKey,
220  uint256 const& digest,
221  Slice const& sig,
222  bool mustBeFullyCanonical)
223 {
224  if (publicKeyType(publicKey) != KeyType::secp256k1)
225  LogicError("sign: secp256k1 required for digest signing");
226  auto const canonicality = ecdsaCanonicality(sig);
227  if (!canonicality)
228  return false;
229  if (mustBeFullyCanonical &&
230  (*canonicality != ECDSACanonicality::fullyCanonical))
231  return false;
232 
233  secp256k1_pubkey pubkey_imp;
234  if (secp256k1_ec_pubkey_parse(
236  &pubkey_imp,
237  reinterpret_cast<unsigned char const*>(publicKey.data()),
238  publicKey.size()) != 1)
239  return false;
240 
241  secp256k1_ecdsa_signature sig_imp;
242  if (secp256k1_ecdsa_signature_parse_der(
244  &sig_imp,
245  reinterpret_cast<unsigned char const*>(sig.data()),
246  sig.size()) != 1)
247  return false;
248  if (*canonicality != ECDSACanonicality::fullyCanonical)
249  {
250  secp256k1_ecdsa_signature sig_norm;
251  if (secp256k1_ecdsa_signature_normalize(
252  secp256k1Context(), &sig_norm, &sig_imp) != 1)
253  return false;
254  return secp256k1_ecdsa_verify(
256  &sig_norm,
257  reinterpret_cast<unsigned char const*>(digest.data()),
258  &pubkey_imp) == 1;
259  }
260  return secp256k1_ecdsa_verify(
262  &sig_imp,
263  reinterpret_cast<unsigned char const*>(digest.data()),
264  &pubkey_imp) == 1;
265 }
266 
267 bool
269  PublicKey const& publicKey,
270  Slice const& m,
271  Slice const& sig,
272  bool mustBeFullyCanonical)
273 {
274  if (auto const type = publicKeyType(publicKey))
275  {
276  if (*type == KeyType::secp256k1)
277  {
278  return verifyDigest(
279  publicKey, sha512Half(m), sig, mustBeFullyCanonical);
280  }
281  else if (*type == KeyType::ed25519)
282  {
283  if (!ed25519Canonical(sig))
284  return false;
285 
286  // We internally prefix Ed25519 keys with a 0xED
287  // byte to distinguish them from secp256k1 keys
288  // so when verifying the signature, we need to
289  // first strip that prefix.
290  return ed25519_sign_open(
291  m.data(), m.size(), publicKey.data() + 1, sig.data()) ==
292  0;
293  }
294  }
295  return false;
296 }
297 
298 NodeID
300 {
301  static_assert(NodeID::bytes == sizeof(ripesha_hasher::result_type));
302 
303  ripesha_hasher h;
304  h(pk.data(), pk.size());
305  return NodeID{static_cast<ripesha_hasher::result_type>(h)};
306 }
307 
308 } // 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:79
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:240
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:299
ripple::NodeID
base_uint< 160, detail::NodeIDTag > NodeID
NodeID is a 160-bit hash representing one node.
Definition: UintTypes.h:59
ripple::publicKeyType
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:203
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::Slice::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Slice.h:96
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::sigPart
static boost::optional< Slice > sigPart(Slice &buf)
Definition: PublicKey.cpp:54
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:68
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::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
Definition: PublicKey.cpp:268
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:73
ripple::base_uint< 160, detail::NodeIDTag >::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:96
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)
std::array
STL class.
ripple::ecdsaCanonicality
boost::optional< ECDSACanonicality > ecdsaCanonicality(Slice const &sig)
Determine whether a signature is canonical.
Definition: PublicKey.cpp:114
std::uint8_t
ripple::PublicKey::operator=
PublicKey & operator=(PublicKey const &other)
Definition: PublicKey.cpp:192
ripple::verifyDigest
bool verifyDigest(PublicKey const &publicKey, uint256 const &digest, Slice const &sig, bool mustBeFullyCanonical)
Verify a secp256k1 signature on the digest of a message.
Definition: PublicKey.cpp:218
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::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
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:45
ripple::ed25519Canonical
static bool ed25519Canonical(Slice const &sig)
Definition: PublicKey.cpp:156
ripple::parseBase58
boost::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
Definition: AccountID.cpp:36
type_traits