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