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/GenerateDeterministicKey.h>
24 #include <ripple/crypto/csprng.h>
25 #include <ripple/crypto/secure_erase.h>
26 #include <ripple/protocol/SecretKey.h>
27 #include <ripple/protocol/digest.h>
28 #include <ripple/protocol/impl/secp256k1.h>
29 #include <cstring>
30 #include <ed25519-donna/ed25519.h>
31 
32 namespace ripple {
33 
35 {
36  secure_erase(buf_, sizeof(buf_));
37 }
38 
40 {
41  std::memcpy(buf_, key.data(), key.size());
42 }
43 
45 {
46  if (slice.size() != sizeof(buf_))
47  LogicError("SecretKey::SecretKey: invalid size");
48  std::memcpy(buf_, slice.data(), sizeof(buf_));
49 }
50 
53 {
54  return strHex(*this);
55 }
56 
57 //------------------------------------------------------------------------------
59 class Generator
60 {
61 private:
62  Blob gen_; // VFALCO compile time size?
63 
64 public:
65  explicit Generator(Seed const& seed)
66  {
67  // FIXME: Avoid copying the seed into a uint128 key only to have
68  // generateRootDeterministicPublicKey copy out of it.
69  uint128 ui;
70  std::memcpy(ui.data(), seed.data(), seed.size());
72  }
73 
79  operator()(Seed const& seed, std::size_t ordinal) const
80  {
81  // FIXME: Avoid copying the seed into a uint128 key only to have
82  // generatePrivateDeterministicKey copy out of it.
83  uint128 ui;
84  std::memcpy(ui.data(), seed.data(), seed.size());
85  auto gsk = generatePrivateDeterministicKey(gen_, ui, ordinal);
86  auto gpk = generatePublicDeterministicKey(gen_, ordinal);
87  SecretKey const sk(Slice{gsk.data(), gsk.size()});
88  PublicKey const pk(Slice{gpk.data(), gpk.size()});
89  secure_erase(ui.data(), ui.size());
90  secure_erase(gsk.data(), gsk.size());
91  return {pk, sk};
92  }
93 };
94 
95 //------------------------------------------------------------------------------
96 
97 Buffer
98 signDigest(PublicKey const& pk, SecretKey const& sk, uint256 const& digest)
99 {
101  LogicError("sign: secp256k1 required for digest signing");
102 
103  BOOST_ASSERT(sk.size() == 32);
104  secp256k1_ecdsa_signature sig_imp;
105  if (secp256k1_ecdsa_sign(
107  &sig_imp,
108  reinterpret_cast<unsigned char const*>(digest.data()),
109  reinterpret_cast<unsigned char const*>(sk.data()),
110  secp256k1_nonce_function_rfc6979,
111  nullptr) != 1)
112  LogicError("sign: secp256k1_ecdsa_sign failed");
113 
114  unsigned char sig[72];
115  size_t len = sizeof(sig);
116  if (secp256k1_ecdsa_signature_serialize_der(
117  secp256k1Context(), sig, &len, &sig_imp) != 1)
118  LogicError("sign: secp256k1_ecdsa_signature_serialize_der failed");
119 
120  return Buffer{sig, len};
121 }
122 
123 Buffer
124 sign(PublicKey const& pk, SecretKey const& sk, Slice const& m)
125 {
126  auto const type = publicKeyType(pk.slice());
127  if (!type)
128  LogicError("sign: invalid type");
129  switch (*type)
130  {
131  case KeyType::ed25519: {
132  Buffer b(64);
133  ed25519_sign(
134  m.data(), m.size(), sk.data(), pk.data() + 1, b.data());
135  return b;
136  }
137  case KeyType::secp256k1: {
139  h(m.data(), m.size());
140  auto const digest = sha512_half_hasher::result_type(h);
141 
142  secp256k1_ecdsa_signature sig_imp;
143  if (secp256k1_ecdsa_sign(
145  &sig_imp,
146  reinterpret_cast<unsigned char const*>(digest.data()),
147  reinterpret_cast<unsigned char const*>(sk.data()),
148  secp256k1_nonce_function_rfc6979,
149  nullptr) != 1)
150  LogicError("sign: secp256k1_ecdsa_sign failed");
151 
152  unsigned char sig[72];
153  size_t len = sizeof(sig);
154  if (secp256k1_ecdsa_signature_serialize_der(
155  secp256k1Context(), sig, &len, &sig_imp) != 1)
156  LogicError(
157  "sign: secp256k1_ecdsa_signature_serialize_der failed");
158 
159  return Buffer{sig, len};
160  }
161  default:
162  LogicError("sign: invalid type");
163  }
164 }
165 
166 SecretKey
168 {
169  std::uint8_t buf[32];
170  beast::rngfill(buf, sizeof(buf), crypto_prng());
171  SecretKey sk(Slice{buf, sizeof(buf)});
172  secure_erase(buf, sizeof(buf));
173  return sk;
174 }
175 
176 // VFALCO TODO Rewrite all this without using OpenSSL
177 // or calling into GenerateDetermisticKey
178 SecretKey
179 generateSecretKey(KeyType type, Seed const& seed)
180 {
181  if (type == KeyType::ed25519)
182  {
183  auto key = sha512Half_s(Slice(seed.data(), seed.size()));
184  SecretKey sk = Slice{key.data(), key.size()};
185  secure_erase(key.data(), key.size());
186  return sk;
187  }
188 
189  if (type == KeyType::secp256k1)
190  {
191  // FIXME: Avoid copying the seed into a uint128 key only to have
192  // generateRootDeterministicPrivateKey copy out of it.
193  uint128 ps;
194  std::memcpy(ps.data(), seed.data(), seed.size());
195  auto const upk = generateRootDeterministicPrivateKey(ps);
196  SecretKey sk = Slice{upk.data(), upk.size()};
197  secure_erase(ps.data(), ps.size());
198  return sk;
199  }
200 
201  LogicError("generateSecretKey: unknown key type");
202 }
203 
204 PublicKey
206 {
207  switch (type)
208  {
209  case KeyType::secp256k1: {
210  secp256k1_pubkey pubkey_imp;
211  if (secp256k1_ec_pubkey_create(
213  &pubkey_imp,
214  reinterpret_cast<unsigned char const*>(sk.data())) != 1)
215  LogicError(
216  "derivePublicKey: secp256k1_ec_pubkey_create failed");
217 
218  unsigned char pubkey[33];
219  std::size_t len = sizeof(pubkey);
220  if (secp256k1_ec_pubkey_serialize(
222  pubkey,
223  &len,
224  &pubkey_imp,
225  SECP256K1_EC_COMPRESSED) != 1)
226  LogicError(
227  "derivePublicKey: secp256k1_ec_pubkey_serialize failed");
228 
229  return PublicKey{Slice{pubkey, len}};
230  }
231  case KeyType::ed25519: {
232  unsigned char buf[33];
233  buf[0] = 0xED;
234  ed25519_publickey(sk.data(), &buf[1]);
235  return PublicKey(Slice{buf, sizeof(buf)});
236  }
237  default:
238  LogicError("derivePublicKey: bad key type");
239  };
240 }
241 
243 generateKeyPair(KeyType type, Seed const& seed)
244 {
245  switch (type)
246  {
247  case KeyType::secp256k1: {
248  Generator g(seed);
249  return g(seed, 0);
250  }
251  default:
252  case KeyType::ed25519: {
253  auto const sk = generateSecretKey(type, seed);
254  return {derivePublicKey(type, sk), sk};
255  }
256  }
257 }
258 
261 {
262  auto const sk = randomSecretKey();
263  return {derivePublicKey(type, sk), sk};
264 }
265 
266 template <>
267 boost::optional<SecretKey>
268 parseBase58(TokenType type, std::string const& s)
269 {
270  auto const result = decodeBase58Token(s, type);
271  if (result.empty())
272  return boost::none;
273  if (result.size() != 32)
274  return boost::none;
275  return SecretKey(makeSlice(result));
276 }
277 
278 } // 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
ripple::Generator::gen_
Blob gen_
Definition: SecretKey.cpp:62
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::Generator::operator()
std::pair< PublicKey, SecretKey > operator()(Seed const &seed, std::size_t ordinal) const
Generate the nth key pair.
Definition: SecretKey.cpp:79
std::string
STL class.
cstring
ripple::detail::basic_sha512_half_hasher
Returns the SHA512-Half digest of a message.
Definition: digest.h:175
ripple::publicKeyType
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:203
ripple::Generator
Produces a sequence of secp256k1 key pairs.
Definition: SecretKey.cpp:59
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::pair
std::vector< unsigned char >
std::array::size
T size(T... args)
ripple::generateRootDeterministicPrivateKey
uint256 generateRootDeterministicPrivateKey(uint128 const &seed)
Definition: GenerateDeterministicKey.cpp:129
ripple::crypto_prng
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Definition: csprng.cpp:108
ripple::Slice::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Slice.h:96
ripple::PublicKey::slice
Slice slice() const noexcept
Definition: PublicKey.h:123
ripple::Buffer
Like std::vector<char> but better.
Definition: Buffer.h:35
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:243
ripple::base_uint::data
pointer data()
Definition: base_uint.h:103
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:243
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:462
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:43
ripple::KeyType::ed25519
@ ed25519
ripple::SecretKey::buf_
std::uint8_t buf_[32]
Definition: SecretKey.h:39
ripple::base_uint
Definition: base_uint.h:63
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:98
ripple::derivePublicKey
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
Definition: SecretKey.cpp:205
ripple::SecretKey::data
std::uint8_t const * data() const
Definition: SecretKey.h:55
std::array
STL class.
ripple::generateSecretKey
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
Definition: SecretKey.cpp:179
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::generateRootDeterministicPublicKey
Blob generateRootDeterministicPublicKey(uint128 const &seed)
Definition: GenerateDeterministicKey.cpp:114
ripple::KeyType::secp256k1
@ secp256k1
ripple::randomKeyPair
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Definition: SecretKey.cpp:260
ripple::SecretKey::SecretKey
SecretKey()=default
ripple::Seed::size
std::size_t size() const
Definition: Seed.h:64
ripple::generatePrivateDeterministicKey
uint256 generatePrivateDeterministicKey(Blob const &family, uint128 const &seed, int n)
Definition: GenerateDeterministicKey.cpp:196
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:183
ripple::Generator::Generator
Generator(Seed const &seed)
Definition: SecretKey.cpp:65
ripple::Seed
Seeds are used to generate deterministic secret keys.
Definition: Seed.h:32
ripple::SecretKey::~SecretKey
~SecretKey()
Definition: SecretKey.cpp:34
ripple::sign
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
Definition: SecretKey.cpp:124
beast::rngfill
void rngfill(void *buffer, std::size_t bytes, Generator &g)
Definition: rngfill.h:32
ripple::decodeBase58Token
static std::string decodeBase58Token(std::string const &s, TokenType type, InverseArray const &inv)
Definition: tokens.cpp:256
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
std::size_t
std::memcpy
T memcpy(T... args)
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:67
ripple::generatePublicDeterministicKey
Blob generatePublicDeterministicKey(Blob const &generator, int n)
Definition: GenerateDeterministicKey.cpp:175
ripple::SecretKey::size
std::size_t size() const
Definition: SecretKey.h:61
ripple::parseBase58
boost::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
Definition: AccountID.cpp:36
std::array::data
T data(T... args)
ripple::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition: SecretKey.cpp:167
ripple::SecretKey::to_string
std::string to_string() const
Convert the secret key to a hexadecimal string.
Definition: SecretKey.cpp:52
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