rippled
SecretKey_test.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/beast/unit_test.h>
21 #include <ripple/beast/utility/rngfill.h>
22 #include <ripple/crypto/csprng.h>
23 #include <ripple/protocol/PublicKey.h>
24 #include <ripple/protocol/SecretKey.h>
25 #include <ripple/protocol/Seed.h>
26 #include <algorithm>
27 #include <string>
28 #include <vector>
29 
30 #include <ripple/protocol/impl/secp256k1.h>
31 
32 namespace ripple {
33 
34 class SecretKey_test : public beast::unit_test::suite
35 {
36 public:
38 
39  template <class FwdIter, class Container>
40  static void
41  hex_to_binary(FwdIter first, FwdIter last, Container& out)
42  {
43  struct Table
44  {
45  int val[256];
46  Table()
47  {
48  std::fill(val, val + 256, 0);
49  for (int i = 0; i < 10; ++i)
50  val['0' + i] = i;
51  for (int i = 0; i < 6; ++i)
52  {
53  val['A' + i] = 10 + i;
54  val['a' + i] = 10 + i;
55  }
56  }
57  int
58  operator[](int i)
59  {
60  return val[i];
61  }
62  };
63 
64  static Table lut;
65  out.reserve(std::distance(first, last) / 2);
66  while (first != last)
67  {
68  auto const hi(lut[(*first++)]);
69  auto const lo(lut[(*first++)]);
70  out.push_back((hi * 16) + lo);
71  }
72  }
73 
74  static uint256
76  {
77  blob b;
78  hex_to_binary(s.begin(), s.end(), b);
79  return uint256{b};
80  }
81 
82  static PublicKey
84  {
85  blob b;
86  hex_to_binary(s.begin(), s.end(), b);
87  return PublicKey{Slice{b.data(), b.size()}};
88  }
89 
90  static SecretKey
92  {
93  blob b;
94  hex_to_binary(s.begin(), s.end(), b);
95  return SecretKey{Slice{b.data(), b.size()}};
96  }
97 
98  static Buffer
100  {
101  blob b;
102  hex_to_binary(s.begin(), s.end(), b);
103  return Buffer{Slice{b.data(), b.size()}};
104  }
105 
106  // Ensure that verification does the right thing with
107  // respect to the matrix of canonicality variables.
108  void
110  {
111  testcase("secp256k1 canonicality");
112 
113 #if 0
114  makeCanonicalityTestVectors();
115 #else
116  auto const digest = hex_to_digest(
117  "34C19028C80D21F3F48C9354895F8D5BF0D5EE7FF457647CF655F5530A3022A7");
118  auto const pk = hex_to_pk(
119  "025096EB12D3E924234E7162369C11D8BF877EDA238778E7A31FF0AAC5D0DBCF3"
120  "7");
121  auto const sk = hex_to_sk(
122  "AA921417E7E5C299DA4EEC16D1CAA92F19B19F2A68511F68EC73BBB2F5236F3D");
123  auto const sig = hex_to_sig(
124  "3045022100B49D07F0E934BA468C0EFC78117791408D1FB8B63A6492AD395AC2F3"
125  "60F246600220508739DB0A2EF81676E39F459C8BBB07A09C3E9F9BEB696294D524"
126  "D479D62740");
127  auto const non = hex_to_sig(
128  "3046022100B49D07F0E934BA468C0EFC78117791408D1FB8B63A6492AD395AC2F3"
129  "60F24660022100AF78C624F5D107E9891C60BA637444F71A129E47135D36D92AFD"
130  "39B856601A01");
131 
132  {
133  auto const canonicality = ecdsaCanonicality(sig);
134  BEAST_EXPECT(canonicality);
135  BEAST_EXPECT(*canonicality == ECDSACanonicality::fullyCanonical);
136  }
137 
138  {
139  auto const canonicality = ecdsaCanonicality(non);
140  BEAST_EXPECT(canonicality);
141  BEAST_EXPECT(*canonicality != ECDSACanonicality::fullyCanonical);
142  }
143 
144  BEAST_EXPECT(verifyDigest(pk, digest, sig, false));
145  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
146  BEAST_EXPECT(verifyDigest(pk, digest, non, false));
147  BEAST_EXPECT(!verifyDigest(pk, digest, non, true));
148 #endif
149  }
150 
151  void
153  {
154  testcase("secp256k1 digest");
155 
156  for (std::size_t i = 0; i < 32; i++)
157  {
158  auto const [pk, sk] = randomKeyPair(KeyType::secp256k1);
159 
160  BEAST_EXPECT(pk == derivePublicKey(KeyType::secp256k1, sk));
161  BEAST_EXPECT(*publicKeyType(pk) == KeyType::secp256k1);
162 
163  for (std::size_t j = 0; j < 32; j++)
164  {
165  uint256 digest;
166  beast::rngfill(digest.data(), digest.size(), crypto_prng());
167 
168  auto sig = signDigest(pk, sk, digest);
169 
170  BEAST_EXPECT(sig.size() != 0);
171  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
172 
173  // Wrong digest:
174  BEAST_EXPECT(!verifyDigest(pk, ~digest, sig, true));
175 
176  // Slightly change the signature:
177  if (auto ptr = sig.data())
178  ptr[j % sig.size()]++;
179 
180  // Wrong signature:
181  BEAST_EXPECT(!verifyDigest(pk, digest, sig, true));
182 
183  // Wrong digest and signature:
184  BEAST_EXPECT(!verifyDigest(pk, ~digest, sig, true));
185  }
186  }
187  }
188 
189  void
191  {
192  for (std::size_t i = 0; i < 32; i++)
193  {
194  auto const [pk, sk] = randomKeyPair(type);
195 
196  BEAST_EXPECT(pk == derivePublicKey(type, sk));
197  BEAST_EXPECT(*publicKeyType(pk) == type);
198 
199  for (std::size_t j = 0; j < 32; j++)
200  {
201  std::vector<std::uint8_t> data(64 + (8 * i) + j);
202  beast::rngfill(data.data(), data.size(), crypto_prng());
203 
204  auto sig = sign(pk, sk, makeSlice(data));
205 
206  BEAST_EXPECT(sig.size() != 0);
207  BEAST_EXPECT(verify(pk, makeSlice(data), sig, true));
208 
209  // Construct wrong data:
210  auto badData = data;
211 
212  // swaps the smallest and largest elements in buffer
214  std::min_element(badData.begin(), badData.end()),
215  std::max_element(badData.begin(), badData.end()));
216 
217  // Wrong data: should fail
218  BEAST_EXPECT(!verify(pk, makeSlice(badData), sig, true));
219 
220  // Slightly change the signature:
221  if (auto ptr = sig.data())
222  ptr[j % sig.size()]++;
223 
224  // Wrong signature: should fail
225  BEAST_EXPECT(!verify(pk, makeSlice(data), sig, true));
226 
227  // Wrong data and signature: should fail
228  BEAST_EXPECT(!verify(pk, makeSlice(badData), sig, true));
229  }
230  }
231  }
232 
233  void
235  {
236  testcase("Base58");
237 
238  // Ensure that parsing some well-known secret keys works
239  {
240  auto const sk1 = generateSecretKey(
241  KeyType::secp256k1, generateSeed("masterpassphrase"));
242 
243  auto const sk2 = parseBase58<SecretKey>(
245  "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe");
246  BEAST_EXPECT(sk2);
247 
248  BEAST_EXPECT(sk1 == *sk2);
249  }
250 
251  {
252  auto const sk1 = generateSecretKey(
253  KeyType::ed25519, generateSeed("masterpassphrase"));
254 
255  auto const sk2 = parseBase58<SecretKey>(
257  "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36");
258  BEAST_EXPECT(sk2);
259 
260  BEAST_EXPECT(sk1 == *sk2);
261  }
262 
263  // Try converting short, long and malformed data
264  BEAST_EXPECT(!parseBase58<SecretKey>(TokenType::NodePrivate, ""));
265  BEAST_EXPECT(!parseBase58<SecretKey>(TokenType::NodePrivate, " "));
266  BEAST_EXPECT(!parseBase58<SecretKey>(
267  TokenType::NodePrivate, "!35gty9mhju8nfjl"));
268 
269  auto const good = toBase58(TokenType::NodePrivate, randomSecretKey());
270 
271  // Short (non-empty) strings
272  {
273  auto s = good;
274 
275  // Remove all characters from the string in random order:
277 
278  while (!s.empty())
279  {
280  s.erase(r(s) % s.size(), 1);
281  BEAST_EXPECT(
282  !parseBase58<SecretKey>(TokenType::NodePrivate, s));
283  }
284  }
285 
286  // Long strings
287  for (std::size_t i = 1; i != 16; i++)
288  {
289  auto s = good;
290  s.resize(s.size() + i, s[i % s.size()]);
291  BEAST_EXPECT(!parseBase58<SecretKey>(TokenType::NodePrivate, s));
292  }
293 
294  // Strings with invalid Base58 characters
295  for (auto c : std::string("0IOl"))
296  {
297  for (std::size_t i = 0; i != good.size(); ++i)
298  {
299  auto s = good;
300  s[i % s.size()] = c;
301  BEAST_EXPECT(
302  !parseBase58<SecretKey>(TokenType::NodePrivate, s));
303  }
304  }
305 
306  // Strings with incorrect prefix
307  {
308  auto s = good;
309 
310  for (auto c : std::string("ansrJqtv7"))
311  {
312  s[0] = c;
313  BEAST_EXPECT(
314  !parseBase58<SecretKey>(TokenType::NodePrivate, s));
315  }
316  }
317 
318  // Try some random secret keys
320 
321  for (std::size_t i = 0; i != keys.size(); ++i)
322  keys[i] = randomSecretKey();
323 
324  for (std::size_t i = 0; i != keys.size(); ++i)
325  {
326  auto const si = toBase58(TokenType::NodePrivate, keys[i]);
327  BEAST_EXPECT(!si.empty());
328 
329  auto const ski = parseBase58<SecretKey>(TokenType::NodePrivate, si);
330  BEAST_EXPECT(ski && keys[i] == *ski);
331 
332  for (std::size_t j = i; j != keys.size(); ++j)
333  {
334  BEAST_EXPECT((keys[i] == keys[j]) == (i == j));
335 
336  auto const sj = toBase58(TokenType::NodePrivate, keys[j]);
337 
338  BEAST_EXPECT((si == sj) == (i == j));
339 
340  auto const skj =
341  parseBase58<SecretKey>(TokenType::NodePrivate, sj);
342  BEAST_EXPECT(skj && keys[j] == *skj);
343 
344  BEAST_EXPECT((*ski == *skj) == (i == j));
345  }
346  }
347  }
348 
349  void
351  {
352  testcase("Miscellaneous operations");
353 
354  auto const sk1 = generateSecretKey(
355  KeyType::secp256k1, generateSeed("masterpassphrase"));
356 
357  SecretKey sk2(sk1);
358  BEAST_EXPECT(sk1 == sk2);
359 
360  SecretKey sk3;
361  BEAST_EXPECT(sk3 != sk2);
362  sk3 = sk2;
363  BEAST_EXPECT(sk3 == sk2);
364  }
365 
366  void
367  run() override
368  {
369  testBase58();
373 
374  testcase("secp256k1");
376 
377  testcase("ed25519");
379  }
380 };
381 
382 BEAST_DEFINE_TESTSUITE(SecretKey, protocol, ripple);
383 
384 } // namespace ripple
std::max_element
T max_element(T... args)
ripple::SecretKey_test::hex_to_binary
static void hex_to_binary(FwdIter first, FwdIter last, Container &out)
Definition: SecretKey_test.cpp:41
ripple::SecretKey_test::hex_to_sk
static SecretKey hex_to_sk(std::string const &s)
Definition: SecretKey_test.cpp:91
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::SecretKey_test::testMiscOperations
void testMiscOperations()
Definition: SecretKey_test.cpp:350
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::publicKeyType
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:203
ripple::SecretKey_test::run
void run() override
Definition: SecretKey_test.cpp:367
ripple::SecretKey_test::testSigning
void testSigning(KeyType type)
Definition: SecretKey_test.cpp:190
ripple::SecretKey_test::testBase58
void testBase58()
Definition: SecretKey_test.cpp:234
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
vector
std::vector::size
T size(T... args)
ripple::SecretKey_test::hex_to_pk
static PublicKey hex_to_pk(std::string const &s)
Definition: SecretKey_test.cpp:83
ripple::crypto_prng
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Definition: csprng.cpp:108
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:29
std::distance
T distance(T... args)
ripple::Buffer
Like std::vector<char> but better.
Definition: Buffer.h:35
ripple::SecretKey_test
Definition: SecretKey_test.cpp:34
ripple::ECDSACanonicality::fullyCanonical
@ fullyCanonical
algorithm
std::fill
T fill(T... args)
ripple::digest
static Hasher::result_type digest(void const *data, std::size_t size) noexcept
Definition: tokens.cpp:47
ripple::KeyType::ed25519
@ ed25519
ripple::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
Definition: PublicKey.cpp:268
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:73
ripple::SecretKey_test::testDigestSigning
void testDigestSigning()
Definition: SecretKey_test.cpp:152
ripple::QualityDirection::out
@ out
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
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
std::iter_swap
T iter_swap(T... args)
std::min_element
T min_element(T... args)
ripple::SecretKey_test::hex_to_sig
static Buffer hex_to_sig(std::string const &s)
Definition: SecretKey_test.cpp:99
std::array
STL class.
ripple::ecdsaCanonicality
boost::optional< ECDSACanonicality > ecdsaCanonicality(Slice const &sig)
Determine whether a signature is canonical.
Definition: PublicKey.cpp:114
ripple::generateSecretKey
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
Definition: SecretKey.cpp:179
ripple::SecretKey
A secret key.
Definition: SecretKey.h:36
ripple::verifyDigest
bool verifyDigest(PublicKey const &publicKey, uint256 const &digest, Slice const &sig, bool mustBeFullyCanonical)
Verify a secp256k1 signature on the digest of a message.
Definition: PublicKey.cpp:218
ripple::SecretKey_test::hex_to_digest
static uint256 hex_to_digest(std::string const &s)
Definition: SecretKey_test.cpp:75
ripple::KeyType
KeyType
Definition: KeyType.h:28
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::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:69
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::sign
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
Definition: SecretKey.cpp:124
std::string::begin
T begin(T... args)
beast::rngfill
void rngfill(void *buffer, std::size_t bytes, Generator &g)
Definition: rngfill.h:32
std::size_t
std::string::end
T end(T... args)
std::vector::data
T data(T... args)
ripple::TokenType::NodePrivate
@ NodePrivate
ripple::SecretKey_test::testCanonicality
void testCanonicality()
Definition: SecretKey_test.cpp:109
ripple::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition: SecretKey.cpp:167
std::hash
string