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