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/crypto/csprng.h>
21 #include <ripple/protocol/PublicKey.h>
22 #include <ripple/protocol/SecretKey.h>
23 #include <ripple/protocol/Seed.h>
24 #include <ripple/beast/unit_test.h>
25 #include <ripple/beast/utility/rngfill.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
41  void
42  hex_to_binary (FwdIter first, FwdIter last, Container& out)
43  {
44  struct Table
45  {
46  int val[256];
47  Table ()
48  {
49  std::fill (val, val+256, 0);
50  for (int i = 0; i < 10; ++i)
51  val ['0'+i] = i;
52  for (int i = 0; i < 6; ++i)
53  {
54  val ['A'+i] = 10 + i;
55  val ['a'+i] = 10 + i;
56  }
57  }
58  int 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
75  uint256
77  {
78  blob b;
79  hex_to_binary (s.begin (), s.end (), b);
80  return uint256{b};
81  }
82 
83  static
84  PublicKey
86  {
87  blob b;
88  hex_to_binary (s.begin (), s.end (), b);
89  return PublicKey{Slice{b.data(), b.size()}};
90  }
91 
92  static
93  SecretKey
95  {
96  blob b;
97  hex_to_binary (s.begin (), s.end (), b);
98  return SecretKey{Slice{b.data(), b.size()}};
99  }
100 
101  static
102  Buffer
104  {
105  blob b;
106  hex_to_binary (s.begin (), s.end (), b);
107  return Buffer{Slice{b.data(), b.size()}};
108  }
109 
110  // VFALCO We can remove this commented out code
111  // later, when we have confidence in the vectors.
112 
113  /*
114  Buffer
115  makeNonCanonical(Buffer const& sig)
116  {
117  secp256k1_ecdsa_signature sigin;
118  BEAST_EXPECT(secp256k1_ecdsa_signature_parse_der(
119  secp256k1Context(),
120  &sigin,
121  reinterpret_cast<unsigned char const*>(
122  sig.data()),
123  sig.size()) == 1);
124  secp256k1_ecdsa_signature sigout;
125  BEAST_EXPECT(secp256k1_ecdsa_signature_denormalize(
126  secp256k1Context(),
127  &sigout,
128  &sigin) == 1);
129  unsigned char buf[72];
130  size_t len = sizeof(buf);
131  BEAST_EXPECT(secp256k1_ecdsa_signature_serialize_der(
132  secp256k1Context(),
133  buf,
134  &len,
135  &sigout) == 1);
136  return Buffer{buf, len};
137  }
138 
139  void
140  makeCanonicalityTestVectors()
141  {
142  uint256 digest;
143  beast::rngfill (
144  digest.data(),
145  digest.size(),
146  crypto_prng());
147  log << "digest " << strHex(digest.data(), digest.size()) << std::endl;
148 
149  auto const sk = randomSecretKey();
150  auto const pk = derivePublicKey(KeyType::secp256k1, sk);
151  log << "public " << pk << std::endl;
152  log << "secret " << sk.to_string() << std::endl;
153 
154  auto sig = signDigest(pk, sk, digest);
155  log << "canonical sig " << strHex(sig) << std::endl;
156 
157  auto const non = makeNonCanonical(sig);
158  log << "non-canon sig " << strHex(non) << std::endl;
159 
160  {
161  auto const canonicality = ecdsaCanonicality(sig);
162  BEAST_EXPECT(canonicality);
163  BEAST_EXPECT(*canonicality == ECDSACanonicality::fullyCanonical);
164  }
165 
166  {
167  auto const canonicality = ecdsaCanonicality(non);
168  BEAST_EXPECT(canonicality);
169  BEAST_EXPECT(*canonicality != ECDSACanonicality::fullyCanonical);
170  }
171 
172  BEAST_EXPECT(verifyDigest(pk, digest, sig, false));
173  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
174  BEAST_EXPECT(verifyDigest(pk, digest, non, false));
175  BEAST_EXPECT(! verifyDigest(pk, digest, non, true));
176  }
177  */
178 
179  // Ensure that verification does the right thing with
180  // respect to the matrix of canonicality variables.
181  void
183  {
184  testcase ("secp256k1 canonicality");
185 
186 #if 0
187  makeCanonicalityTestVectors();
188 #else
189  auto const digest = hex_to_digest("34C19028C80D21F3F48C9354895F8D5BF0D5EE7FF457647CF655F5530A3022A7");
190  auto const pk = hex_to_pk("025096EB12D3E924234E7162369C11D8BF877EDA238778E7A31FF0AAC5D0DBCF37");
191  auto const sk = hex_to_sk("AA921417E7E5C299DA4EEC16D1CAA92F19B19F2A68511F68EC73BBB2F5236F3D");
192  auto const sig = hex_to_sig("3045022100B49D07F0E934BA468C0EFC78117791408D1FB8B63A6492AD395AC2F360F246600220508739DB0A2EF81676E39F459C8BBB07A09C3E9F9BEB696294D524D479D62740");
193  auto const non = hex_to_sig("3046022100B49D07F0E934BA468C0EFC78117791408D1FB8B63A6492AD395AC2F360F24660022100AF78C624F5D107E9891C60BA637444F71A129E47135D36D92AFD39B856601A01");
194 
195  {
196  auto const canonicality = ecdsaCanonicality(sig);
197  BEAST_EXPECT(canonicality);
198  BEAST_EXPECT(*canonicality == ECDSACanonicality::fullyCanonical);
199  }
200 
201  {
202  auto const canonicality = ecdsaCanonicality(non);
203  BEAST_EXPECT(canonicality);
204  BEAST_EXPECT(*canonicality != ECDSACanonicality::fullyCanonical);
205  }
206 
207  BEAST_EXPECT(verifyDigest(pk, digest, sig, false));
208  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
209  BEAST_EXPECT(verifyDigest(pk, digest, non, false));
210  BEAST_EXPECT(! verifyDigest(pk, digest, non, true));
211 #endif
212  }
213 
215  {
216  testcase ("secp256k1 digest");
217 
218  for (std::size_t i = 0; i < 32; i++)
219  {
220  auto const [pk, sk] = randomKeyPair (KeyType::secp256k1);
221 
222  BEAST_EXPECT(pk == derivePublicKey (KeyType::secp256k1, sk));
223  BEAST_EXPECT(*publicKeyType (pk) == KeyType::secp256k1);
224 
225  for (std::size_t j = 0; j < 32; j++)
226  {
227  uint256 digest;
229  digest.data(),
230  digest.size(),
231  crypto_prng());
232 
233  auto sig = signDigest (
234  pk, sk, digest);
235 
236  BEAST_EXPECT(sig.size() != 0);
237  BEAST_EXPECT(verifyDigest (pk,
238  digest, sig, true));
239 
240  // Wrong digest:
241  BEAST_EXPECT(!verifyDigest (pk,
242  ~digest, sig, true));
243 
244  // Slightly change the signature:
245  if (auto ptr = sig.data())
246  ptr[j % sig.size()]++;
247 
248  // Wrong signature:
249  BEAST_EXPECT(!verifyDigest (pk,
250  digest, sig, true));
251 
252  // Wrong digest and signature:
253  BEAST_EXPECT(!verifyDigest (pk,
254  ~digest, sig, true));
255  }
256  }
257  }
258 
259  void testSigning (KeyType type)
260  {
261  for (std::size_t i = 0; i < 32; i++)
262  {
263  auto const [pk, sk] = randomKeyPair (type);
264 
265  BEAST_EXPECT(pk == derivePublicKey (type, sk));
266  BEAST_EXPECT(*publicKeyType (pk) == type);
267 
268  for (std::size_t j = 0; j < 32; j++)
269  {
270  std::vector<std::uint8_t> data (64 + (8 * i) + j);
272  data.data(),
273  data.size(),
274  crypto_prng());
275 
276  auto sig = sign (
277  pk, sk,
278  makeSlice (data));
279 
280  BEAST_EXPECT(sig.size() != 0);
281  BEAST_EXPECT(verify(pk,
282  makeSlice(data), sig, true));
283 
284  // Construct wrong data:
285  auto badData = data;
286 
287  // swaps the smallest and largest elements in buffer
289  std::min_element (badData.begin(), badData.end()),
290  std::max_element (badData.begin(), badData.end()));
291 
292  // Wrong data: should fail
293  BEAST_EXPECT(!verify (pk,
294  makeSlice(badData), sig, true));
295 
296  // Slightly change the signature:
297  if (auto ptr = sig.data())
298  ptr[j % sig.size()]++;
299 
300  // Wrong signature: should fail
301  BEAST_EXPECT(!verify (pk,
302  makeSlice(data), sig, true));
303 
304  // Wrong data and signature: should fail
305  BEAST_EXPECT(!verify (pk,
306  makeSlice(badData), sig, true));
307  }
308  }
309  }
310 
311  void testBase58 ()
312  {
313  testcase ("Base58");
314 
315  // Ensure that parsing some well-known secret keys works
316  {
317  auto const sk1 = generateSecretKey (
319  generateSeed ("masterpassphrase"));
320 
321  auto const sk2 = parseBase58<SecretKey> (
323  "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe");
324  BEAST_EXPECT(sk2);
325 
326  BEAST_EXPECT(sk1 == *sk2);
327  }
328 
329  {
330  auto const sk1 = generateSecretKey (
332  generateSeed ("masterpassphrase"));
333 
334  auto const sk2 = parseBase58<SecretKey> (
336  "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36");
337  BEAST_EXPECT(sk2);
338 
339  BEAST_EXPECT(sk1 == *sk2);
340  }
341 
342  // Try converting short, long and malformed data
343  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, ""));
344  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, " "));
345  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, "!35gty9mhju8nfjl"));
346 
347  auto const good = toBase58 (
349  randomSecretKey());
350 
351  // Short (non-empty) strings
352  {
353  auto s = good;
354 
355  // Remove all characters from the string in random order:
357 
358  while (!s.empty())
359  {
360  s.erase (r(s) % s.size(), 1);
361  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, s));
362  }
363  }
364 
365  // Long strings
366  for (std::size_t i = 1; i != 16; i++)
367  {
368  auto s = good;
369  s.resize (s.size() + i, s[i % s.size()]);
370  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, s));
371  }
372 
373  // Strings with invalid Base58 characters
374  for (auto c : std::string ("0IOl"))
375  {
376  for (std::size_t i = 0; i != good.size(); ++i)
377  {
378  auto s = good;
379  s[i % s.size()] = c;
380  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, s));
381  }
382  }
383 
384  // Strings with incorrect prefix
385  {
386  auto s = good;
387 
388  for (auto c : std::string("ansrJqtv7"))
389  {
390  s[0] = c;
391  BEAST_EXPECT(!parseBase58<SecretKey> (TokenType::NodePrivate, s));
392  }
393  }
394 
395  // Try some random secret keys
397 
398  for (std::size_t i = 0; i != keys.size(); ++i)
399  keys[i] = randomSecretKey();
400 
401  for (std::size_t i = 0; i != keys.size(); ++i)
402  {
403  auto const si = toBase58 (
405  keys[i]);
406  BEAST_EXPECT(!si.empty());
407 
408  auto const ski = parseBase58<SecretKey> (
410  BEAST_EXPECT(ski && keys[i] == *ski);
411 
412  for (std::size_t j = i; j != keys.size(); ++j)
413  {
414  BEAST_EXPECT((keys[i] == keys[j]) == (i == j));
415 
416  auto const sj = toBase58 (
418  keys[j]);
419 
420  BEAST_EXPECT((si == sj) == (i == j));
421 
422  auto const skj = parseBase58<SecretKey> (
424  BEAST_EXPECT(skj && keys[j] == *skj);
425 
426  BEAST_EXPECT((*ski == *skj) == (i == j));
427  }
428  }
429  }
430 
432  {
433  testcase ("Miscellaneous operations");
434 
435  auto const sk1 = generateSecretKey (
437  generateSeed ("masterpassphrase"));
438 
439  SecretKey sk2 (sk1);
440  BEAST_EXPECT(sk1 == sk2);
441 
442  SecretKey sk3;
443  BEAST_EXPECT(sk3 != sk2);
444  sk3 = sk2;
445  BEAST_EXPECT(sk3 == sk2);
446  }
447 
448  void run() override
449  {
450  testBase58();
454 
455  testcase ("secp256k1");
457 
458  testcase ("ed25519");
460  }
461 };
462 
463 BEAST_DEFINE_TESTSUITE(SecretKey,protocol,ripple);
464 
465 } // 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:42
ripple::SecretKey_test::hex_to_sk
static SecretKey hex_to_sk(std::string const &s)
Definition: SecretKey_test.cpp:94
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:199
ripple::SecretKey_test::testMiscOperations
void testMiscOperations()
Definition: SecretKey_test.cpp:431
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:207
ripple::SecretKey_test::run
void run() override
Definition: SecretKey_test.cpp:448
ripple::SecretKey_test::testSigning
void testSigning(KeyType type)
Definition: SecretKey_test.cpp:259
ripple::SecretKey_test::testBase58
void testBase58()
Definition: SecretKey_test.cpp:311
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:43
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:85
ripple::crypto_prng
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Definition: csprng.cpp:111
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:44
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:277
ripple::base_uint< 256 >
ripple::SecretKey_test::testDigestSigning
void testDigestSigning()
Definition: SecretKey_test.cpp:214
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:100
ripple::derivePublicKey
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
Definition: SecretKey.cpp:228
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:103
std::array
STL class.
ripple::ecdsaCanonicality
boost::optional< ECDSACanonicality > ecdsaCanonicality(Slice const &sig)
Determine whether a signature is canonical.
Definition: PublicKey.cpp:116
ripple::generateSecretKey
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
Definition: SecretKey.cpp:199
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:222
ripple::SecretKey_test::hex_to_digest
static uint256 hex_to_digest(std::string const &s)
Definition: SecretKey_test.cpp:76
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:286
ripple::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:74
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:132
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:182
ripple::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition: SecretKey.cpp:184
std::hash
string