rippled
SecretKey.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/beast/utility/rngfill.h>
23 #include <ripple/crypto/csprng.h>
24 #include <ripple/crypto/secure_erase.h>
25 #include <ripple/protocol/SecretKey.h>
26 #include <ripple/protocol/digest.h>
27 #include <ripple/protocol/impl/secp256k1.h>
28 #include <cstring>
29 #include <ed25519.h>
30 
31 namespace ripple {
32 
34 {
35  secure_erase(buf_, sizeof(buf_));
36 }
37 
39 {
40  std::memcpy(buf_, key.data(), key.size());
41 }
42 
44 {
45  if (slice.size() != sizeof(buf_))
46  LogicError("SecretKey::SecretKey: invalid size");
47  std::memcpy(buf_, slice.data(), sizeof(buf_));
48 }
49 
52 {
53  return strHex(*this);
54 }
55 
56 namespace detail {
57 
58 void
60 {
61  *out++ = v >> 24;
62  *out++ = (v >> 16) & 0xff;
63  *out++ = (v >> 8) & 0xff;
64  *out = v & 0xff;
65 }
66 
67 uint256
69 {
70  // We fill this buffer with the seed and append a 32-bit "counter"
71  // that counts how many attempts we've had to make to generate a
72  // non-zero key that's less than the curve's order:
73  //
74  // 1 2
75  // 0 6 0
76  // buf |----------------|----|
77  // | seed | seq|
78 
80  std::copy(seed.begin(), seed.end(), buf.begin());
81 
82  // The odds that this loop executes more than once are neglible
83  // but *just* in case someone managed to generate a key that required
84  // more iterations loop a few times.
85  for (std::uint32_t seq = 0; seq != 128; ++seq)
86  {
87  copy_uint32(buf.data() + 16, seq);
88 
89  auto const ret = sha512Half(buf);
90 
91  if (secp256k1_ec_seckey_verify(secp256k1Context(), ret.data()) == 1)
92  {
93  secure_erase(buf.data(), buf.size());
94  return ret;
95  }
96  }
97 
98  Throw<std::runtime_error>("Unable to derive generator from seed");
99 }
100 
101 //------------------------------------------------------------------------------
121 {
122 private:
125 
126  uint256
128  {
129  // We fill the buffer with the generator, the provided sequence
130  // and a 32-bit counter tracking the number of attempts we have
131  // already made looking for a non-zero key that's less than the
132  // curve's order:
133  // 3 3 4
134  // 0 pubGen 3 7 1
135  // buf |---------------------------------|----|----|
136  // | generator | seq| cnt|
137 
140  copy_uint32(buf.data() + 33, seq);
141 
142  // The odds that this loop executes more than once are neglible
143  // but we impose a maximum limit just in case.
144  for (std::uint32_t subseq = 0; subseq != 128; ++subseq)
145  {
146  copy_uint32(buf.data() + 37, subseq);
147 
148  auto const ret = sha512Half_s(buf);
149 
150  if (secp256k1_ec_seckey_verify(secp256k1Context(), ret.data()) == 1)
151  {
152  secure_erase(buf.data(), buf.size());
153  return ret;
154  }
155  }
156 
157  Throw<std::runtime_error>("Unable to derive generator from seed");
158  }
159 
160 public:
161  explicit Generator(Seed const& seed)
163  {
164  secp256k1_pubkey pubkey;
165  if (secp256k1_ec_pubkey_create(
166  secp256k1Context(), &pubkey, root_.data()) != 1)
167  LogicError("derivePublicKey: secp256k1_ec_pubkey_create failed");
168 
169  auto len = generator_.size();
170 
171  if (secp256k1_ec_pubkey_serialize(
173  generator_.data(),
174  &len,
175  &pubkey,
176  SECP256K1_EC_COMPRESSED) != 1)
177  LogicError("derivePublicKey: secp256k1_ec_pubkey_serialize failed");
178  }
179 
181  {
184  }
185 
188  operator()(std::size_t ordinal) const
189  {
190  // Generates Nth secret key:
191  auto gsk = [this, tweak = calculateTweak(ordinal)]() {
192  auto rpk = root_;
193 
194  if (secp256k1_ec_privkey_tweak_add(
195  secp256k1Context(), rpk.data(), tweak.data()) == 1)
196  {
197  SecretKey sk{Slice{rpk.data(), rpk.size()}};
198  secure_erase(rpk.data(), rpk.size());
199  return sk;
200  }
201 
202  LogicError("Unable to add a tweak!");
203  }();
204 
205  return {derivePublicKey(KeyType::secp256k1, gsk), gsk};
206  }
207 };
208 
209 } // namespace detail
210 
211 Buffer
212 signDigest(PublicKey const& pk, SecretKey const& sk, uint256 const& digest)
213 {
215  LogicError("sign: secp256k1 required for digest signing");
216 
217  BOOST_ASSERT(sk.size() == 32);
218  secp256k1_ecdsa_signature sig_imp;
219  if (secp256k1_ecdsa_sign(
221  &sig_imp,
222  reinterpret_cast<unsigned char const*>(digest.data()),
223  reinterpret_cast<unsigned char const*>(sk.data()),
224  secp256k1_nonce_function_rfc6979,
225  nullptr) != 1)
226  LogicError("sign: secp256k1_ecdsa_sign failed");
227 
228  unsigned char sig[72];
229  size_t len = sizeof(sig);
230  if (secp256k1_ecdsa_signature_serialize_der(
231  secp256k1Context(), sig, &len, &sig_imp) != 1)
232  LogicError("sign: secp256k1_ecdsa_signature_serialize_der failed");
233 
234  return Buffer{sig, len};
235 }
236 
237 Buffer
238 sign(PublicKey const& pk, SecretKey const& sk, Slice const& m)
239 {
240  auto const type = publicKeyType(pk.slice());
241  if (!type)
242  LogicError("sign: invalid type");
243  switch (*type)
244  {
245  case KeyType::ed25519: {
246  Buffer b(64);
247  ed25519_sign(
248  m.data(), m.size(), sk.data(), pk.data() + 1, b.data());
249  return b;
250  }
251  case KeyType::secp256k1: {
253  h(m.data(), m.size());
254  auto const digest = sha512_half_hasher::result_type(h);
255 
256  secp256k1_ecdsa_signature sig_imp;
257  if (secp256k1_ecdsa_sign(
259  &sig_imp,
260  reinterpret_cast<unsigned char const*>(digest.data()),
261  reinterpret_cast<unsigned char const*>(sk.data()),
262  secp256k1_nonce_function_rfc6979,
263  nullptr) != 1)
264  LogicError("sign: secp256k1_ecdsa_sign failed");
265 
266  unsigned char sig[72];
267  size_t len = sizeof(sig);
268  if (secp256k1_ecdsa_signature_serialize_der(
269  secp256k1Context(), sig, &len, &sig_imp) != 1)
270  LogicError(
271  "sign: secp256k1_ecdsa_signature_serialize_der failed");
272 
273  return Buffer{sig, len};
274  }
275  default:
276  LogicError("sign: invalid type");
277  }
278 }
279 
280 SecretKey
282 {
283  std::uint8_t buf[32];
284  beast::rngfill(buf, sizeof(buf), crypto_prng());
285  SecretKey sk(Slice{buf, sizeof(buf)});
286  secure_erase(buf, sizeof(buf));
287  return sk;
288 }
289 
290 SecretKey
291 generateSecretKey(KeyType type, Seed const& seed)
292 {
293  if (type == KeyType::ed25519)
294  {
295  auto key = sha512Half_s(Slice(seed.data(), seed.size()));
296  SecretKey sk{Slice{key.data(), key.size()}};
297  secure_erase(key.data(), key.size());
298  return sk;
299  }
300 
301  if (type == KeyType::secp256k1)
302  {
303  auto key = detail::deriveDeterministicRootKey(seed);
304  SecretKey sk{Slice{key.data(), key.size()}};
305  secure_erase(key.data(), key.size());
306  return sk;
307  }
308 
309  LogicError("generateSecretKey: unknown key type");
310 }
311 
312 PublicKey
314 {
315  switch (type)
316  {
317  case KeyType::secp256k1: {
318  secp256k1_pubkey pubkey_imp;
319  if (secp256k1_ec_pubkey_create(
321  &pubkey_imp,
322  reinterpret_cast<unsigned char const*>(sk.data())) != 1)
323  LogicError(
324  "derivePublicKey: secp256k1_ec_pubkey_create failed");
325 
326  unsigned char pubkey[33];
327  std::size_t len = sizeof(pubkey);
328  if (secp256k1_ec_pubkey_serialize(
330  pubkey,
331  &len,
332  &pubkey_imp,
333  SECP256K1_EC_COMPRESSED) != 1)
334  LogicError(
335  "derivePublicKey: secp256k1_ec_pubkey_serialize failed");
336 
337  return PublicKey{Slice{pubkey, len}};
338  }
339  case KeyType::ed25519: {
340  unsigned char buf[33];
341  buf[0] = 0xED;
342  ed25519_publickey(sk.data(), &buf[1]);
343  return PublicKey(Slice{buf, sizeof(buf)});
344  }
345  default:
346  LogicError("derivePublicKey: bad key type");
347  };
348 }
349 
351 generateKeyPair(KeyType type, Seed const& seed)
352 {
353  switch (type)
354  {
355  case KeyType::secp256k1: {
356  detail::Generator g(seed);
357  return g(0);
358  }
359  default:
360  case KeyType::ed25519: {
361  auto const sk = generateSecretKey(type, seed);
362  return {derivePublicKey(type, sk), sk};
363  }
364  }
365 }
366 
369 {
370  auto const sk = randomSecretKey();
371  return {derivePublicKey(type, sk), sk};
372 }
373 
374 template <>
376 parseBase58(TokenType type, std::string const& s)
377 {
378  auto const result = decodeBase58Token(s, type);
379  if (result.empty())
380  return std::nullopt;
381  if (result.size() != 32)
382  return std::nullopt;
383  return SecretKey(makeSlice(result));
384 }
385 
386 } // 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
ripple::detail::Generator::root_
uint256 root_
Definition: SecretKey.cpp:123
ripple::detail::Generator::calculateTweak
uint256 calculateTweak(std::uint32_t seq) const
Definition: SecretKey.cpp:127
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.
cstring
ripple::detail::basic_sha512_half_hasher
Returns the SHA512-Half digest of a message.
Definition: digest.h:166
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::pair
std::array::size
T size(T... args)
ripple::crypto_prng
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Definition: csprng.cpp:99
ripple::detail::Generator::generator_
std::array< std::uint8_t, 33 > generator_
Definition: SecretKey.cpp:124
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::Buffer
Like std::vector<char> but better.
Definition: Buffer.h:35
ripple::detail::Generator::operator()
std::pair< PublicKey, SecretKey > operator()(std::size_t ordinal) const
Generate the nth key pair.
Definition: SecretKey.cpp:188
ripple::sha512Half_s
sha512_half_hasher_s::result_type sha512Half_s(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:232
ripple::base_uint::data
pointer data()
Definition: base_uint.h:122
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:351
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:519
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::SecretKey::buf_
std::uint8_t buf_[32]
Definition: SecretKey.h:39
ripple::base_uint< 256 >
ripple::QualityDirection::out
@ out
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::TokenType
TokenType
Definition: tokens.h:29
ripple::signDigest
Buffer signDigest(PublicKey const &pk, SecretKey const &sk, uint256 const &digest)
Generate a signature for a message digest.
Definition: SecretKey.cpp:212
ripple::derivePublicKey
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
Definition: SecretKey.cpp:313
ripple::detail::Generator::Generator
Generator(Seed const &seed)
Definition: SecretKey.cpp:161
ripple::detail::copy_uint32
void copy_uint32(std::uint8_t *out, std::uint32_t v)
Definition: SecretKey.cpp:59
ripple::detail::Generator
Produces a sequence of secp256k1 key pairs.
Definition: SecretKey.cpp:120
ripple::SecretKey::data
std::uint8_t const * data() const
Definition: SecretKey.h:55
std::array< std::uint8_t, 32 >
std::copy
T copy(T... args)
ripple::generateSecretKey
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
Definition: SecretKey.cpp:291
ripple::Buffer::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Buffer.h:150
std::uint8_t
ripple::SecretKey
A secret key.
Definition: SecretKey.h:36
ripple::KeyType
KeyType
Definition: KeyType.h:28
ripple::KeyType::secp256k1
@ secp256k1
ripple::randomKeyPair
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Definition: SecretKey.cpp:368
ripple::SecretKey::SecretKey
SecretKey()=default
ripple::Seed::size
std::size_t size() const
Definition: Seed.h:64
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::detail::basic_sha512_half_hasher::result_type
uint256 result_type
Definition: digest.h:174
ripple::Seed::begin
const_iterator begin() const noexcept
Definition: Seed.h:70
ripple::Seed
Seeds are used to generate deterministic secret keys.
Definition: Seed.h:32
ripple::SecretKey::~SecretKey
~SecretKey()
Definition: SecretKey.cpp:33
ripple::sign
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
Definition: SecretKey.cpp:238
std::array::begin
T begin(T... args)
beast::rngfill
void rngfill(void *buffer, std::size_t bytes, Generator &g)
Definition: rngfill.h:33
ripple::detail::deriveDeterministicRootKey
uint256 deriveDeterministicRootKey(Seed const &seed)
Definition: SecretKey.cpp:68
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
std::optional
ripple::detail::Generator::~Generator
~Generator()
Definition: SecretKey.cpp:180
std::size_t
std::memcpy
T memcpy(T... args)
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
std::array::end
T end(T... args)
ripple::parseBase58
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
Definition: AccountID.cpp:114
ripple::SecretKey::size
std::size_t size() const
Definition: SecretKey.h:61
ripple::Seed::end
const_iterator end() const noexcept
Definition: Seed.h:82
std::array::data
T data(T... args)
ripple::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition: SecretKey.cpp:281
ripple::SecretKey::to_string
std::string to_string() const
Convert the secret key to a hexadecimal string.
Definition: SecretKey.cpp:51
ripple::secure_erase
void secure_erase(void *dest, std::size_t bytes)
Attempts to clear the given blob of memory.
Definition: secure_erase.cpp:26
ripple::Seed::data
std::uint8_t const * data() const
Definition: Seed.h:58