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