rippled
GenerateDeterministicKey.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/crypto/GenerateDeterministicKey.h>
22 #include <ripple/crypto/impl/ec_key.h>
23 #include <ripple/crypto/impl/openssl.h>
24 #include <ripple/crypto/secure_erase.h>
25 #include <ripple/protocol/digest.h>
26 #include <array>
27 #include <openssl/pem.h>
28 #include <string>
29 
30 namespace ripple {
31 
32 namespace openssl {
33 
35 {
36  EC_GROUP const* group;
38 
40  {
41  group = EC_GROUP_new_by_curve_name(NID_secp256k1);
42 
43  if (!group)
44  LogicError(
45  "The OpenSSL library on this system lacks elliptic curve "
46  "support.");
47 
48  bn_ctx ctx;
49  order = get_order(group, ctx);
50  }
51 };
52 
53 static secp256k1_data const&
55 {
56  static secp256k1_data const curve{};
57  return curve;
58 }
59 
60 } // namespace openssl
61 
62 using namespace openssl;
63 
64 static Blob
66 {
67  Blob result(33);
68 
69  serialize_ec_point(point, &result[0]);
70 
71  return result;
72 }
73 
74 template <class FwdIt>
75 void
77 {
78  *out++ = v >> 24;
79  *out++ = (v >> 16) & 0xff;
80  *out++ = (v >> 8) & 0xff;
81  *out = v & 0xff;
82 }
83 
84 // Functions to add support for deterministic EC keys
85 
86 // --> seed
87 // <-- private root generator + public root generator
88 static bignum
90 {
91  // find non-zero private key less than the curve's order
92  bignum privKey;
93  std::uint32_t seq = 0;
94 
95  do
96  {
97  // buf: 0 seed 16 seq 20
98  // |<--------------------------------->|<------>|
100  std::copy(seed.begin(), seed.end(), buf.begin());
101  copy_uint32(buf.begin() + 16, seq++);
102  auto root = sha512Half(buf);
103  secure_erase(buf.data(), buf.size());
104  privKey.assign(root.data(), root.size());
105  secure_erase(root.data(), root.size());
106  } while (privKey.is_zero() || privKey >= secp256k1curve().order);
107  secure_erase(&seq, sizeof(seq));
108  return privKey;
109 }
110 
111 // --> seed
112 // <-- private root generator + public root generator
113 Blob
115 {
116  bn_ctx ctx;
117 
118  bignum privKey = generateRootDeterministicKey(seed);
119 
120  // compute the corresponding public key point
121  ec_point pubKey = multiply(secp256k1curve().group, privKey, ctx);
122 
123  privKey.clear(); // security erase
124 
125  return serialize_ec_point(pubKey);
126 }
127 
128 uint256
130 {
132 
133  return uint256_from_bignum_clear(key);
134 }
135 
136 // Take ripple address.
137 // --> root public generator (consumes)
138 // <-- root public generator in EC format
139 static ec_point
140 generateRootPubKey(bignum&& pubGenerator)
141 {
142  ec_point pubPoint = bn2point(secp256k1curve().group, pubGenerator.get());
143 
144  return pubPoint;
145 }
146 
147 // --> public generator
148 static bignum
149 makeHash(Blob const& pubGen, int seq, bignum const& order)
150 {
151  int subSeq = 0;
152 
153  bignum result;
154 
155  assert(pubGen.size() == 33);
156  do
157  {
158  // buf: 0 pubGen 33 seq 37 subSeq 41
159  // |<--------------------------->|<------>|<-------->|
161  std::copy(pubGen.begin(), pubGen.end(), buf.begin());
162  copy_uint32(buf.begin() + 33, seq);
163  copy_uint32(buf.begin() + 37, subSeq++);
164  auto root = sha512Half_s(buf);
165  secure_erase(buf.data(), buf.size());
166  result.assign(root.data(), root.size());
167  secure_erase(root.data(), root.size());
168  } while (result.is_zero() || result >= order);
169 
170  return result;
171 }
172 
173 // --> public generator
174 Blob
175 generatePublicDeterministicKey(Blob const& pubGen, int seq)
176 {
177  // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
178  ec_point rootPubKey = generateRootPubKey(bignum(pubGen));
179 
180  bn_ctx ctx;
181 
182  // Calculate the private additional key.
183  bignum hash = makeHash(pubGen, seq, secp256k1curve().order);
184 
185  // Calculate the corresponding public key.
186  ec_point newPoint = multiply(secp256k1curve().group, hash, ctx);
187 
188  // Add the master public key and set.
189  add_to(secp256k1curve().group, rootPubKey, newPoint, ctx);
190 
191  return serialize_ec_point(newPoint);
192 }
193 
194 // --> root private key
195 uint256
197  Blob const& pubGen,
198  uint128 const& seed,
199  int seq)
200 {
201  // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
202  bignum rootPrivKey = generateRootDeterministicKey(seed);
203 
204  bn_ctx ctx;
205 
206  // calculate the private additional key
207  bignum privKey = makeHash(pubGen, seq, secp256k1curve().order);
208 
209  // calculate the final private key
210  add_to(rootPrivKey, privKey, secp256k1curve().order, ctx);
211 
212  rootPrivKey.clear(); // security erase
213 
214  return uint256_from_bignum_clear(privKey);
215 }
216 
217 } // namespace ripple
ripple::openssl::ec_point
Definition: openssl.h:172
ripple::openssl::secp256k1_data::order
bignum order
Definition: GenerateDeterministicKey.cpp:37
ripple::Blob
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition: Blob.h:30
ripple::openssl::secp256k1_data::secp256k1_data
secp256k1_data()
Definition: GenerateDeterministicKey.cpp:39
ripple::openssl::bn_ctx
Definition: openssl.h:133
ripple::openssl::secp256k1_data::group
EC_GROUP const * group
Definition: GenerateDeterministicKey.cpp:36
std::vector< unsigned char >
std::array::size
T size(T... args)
ripple::base_uint::end
iterator end()
Definition: base_uint.h:119
ripple::openssl::uint256_from_bignum_clear
uint256 uint256_from_bignum_clear(bignum &number)
Definition: openssl.h:121
ripple::generateRootDeterministicPrivateKey
uint256 generateRootDeterministicPrivateKey(uint128 const &seed)
Definition: GenerateDeterministicKey.cpp:129
ripple::openssl::bignum::is_zero
bool is_zero() const
Definition: openssl.h:93
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::makeHash
static bignum makeHash(Blob const &pubGen, int seq, bignum const &order)
Definition: GenerateDeterministicKey.cpp:149
ripple::openssl::secp256k1_data
Definition: GenerateDeterministicKey.cpp:34
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:493
ripple::base_uint
Definition: base_uint.h:63
ripple::openssl::serialize_ec_point
void serialize_ec_point(ec_point const &point, std::uint8_t *ptr)
Definition: openssl.cpp:119
ripple::openssl::add_to
void add_to(EC_GROUP const *group, ec_point const &a, ec_point &b, bn_ctx &ctx)
Definition: openssl.cpp:78
ripple::QualityDirection::out
@ out
ripple::generateRootDeterministicKey
static bignum generateRootDeterministicKey(uint128 const &seed)
Definition: GenerateDeterministicKey.cpp:89
array
std::copy
T copy(T... args)
std::uint32_t
ripple::generateRootPubKey
static ec_point generateRootPubKey(bignum &&pubGenerator)
Definition: GenerateDeterministicKey.cpp:140
ripple::openssl::bignum::clear
void clear()
Definition: openssl.h:99
ripple::generateRootDeterministicPublicKey
Blob generateRootDeterministicPublicKey(uint128 const &seed)
Definition: GenerateDeterministicKey.cpp:114
ripple::openssl::bignum
Definition: openssl.h:31
ripple::openssl::secp256k1curve
static secp256k1_data const & secp256k1curve()
Definition: GenerateDeterministicKey.cpp:54
ripple::generatePrivateDeterministicKey
uint256 generatePrivateDeterministicKey(Blob const &family, uint128 const &seed, int n)
Definition: GenerateDeterministicKey.cpp:196
ripple::openssl::get_order
bignum get_order(EC_GROUP const *group, bn_ctx &ctx)
Definition: openssl.cpp:61
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:114
std::array::begin
T begin(T... args)
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:227
ripple::openssl::bignum::assign
void assign(uint8_t const *data, size_t size)
Definition: openssl.cpp:35
std::vector::end
T end(T... args)
ripple::generatePublicDeterministicKey
Blob generatePublicDeterministicKey(Blob const &generator, int n)
Definition: GenerateDeterministicKey.cpp:175
ripple::openssl::bn2point
ec_point bn2point(EC_GROUP const *group, BIGNUM const *number)
Definition: openssl.cpp:96
ripple::openssl::multiply
ec_point multiply(EC_GROUP const *group, bignum const &n, bn_ctx &ctx)
Definition: openssl.cpp:85
std::array::data
T data(T... args)
ripple::copy_uint32
void copy_uint32(FwdIt out, std::uint32_t v)
Definition: GenerateDeterministicKey.cpp:76
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
string