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  // VFALCO We can remove this commented out code
107  // later, when we have confidence in the vectors.
108 
109  /*
110  Buffer
111  makeNonCanonical(Buffer const& sig)
112  {
113  secp256k1_ecdsa_signature sigin;
114  BEAST_EXPECT(secp256k1_ecdsa_signature_parse_der(
115  secp256k1Context(),
116  &sigin,
117  reinterpret_cast<unsigned char const*>(
118  sig.data()),
119  sig.size()) == 1);
120  secp256k1_ecdsa_signature sigout;
121  BEAST_EXPECT(secp256k1_ecdsa_signature_denormalize(
122  secp256k1Context(),
123  &sigout,
124  &sigin) == 1);
125  unsigned char buf[72];
126  size_t len = sizeof(buf);
127  BEAST_EXPECT(secp256k1_ecdsa_signature_serialize_der(
128  secp256k1Context(),
129  buf,
130  &len,
131  &sigout) == 1);
132  return Buffer{buf, len};
133  }
134 
135  void
136  makeCanonicalityTestVectors()
137  {
138  uint256 digest;
139  beast::rngfill (
140  digest.data(),
141  digest.size(),
142  crypto_prng());
143  log << "digest " << strHex(digest.data(), digest.size()) << std::endl;
144 
145  auto const sk = randomSecretKey();
146  auto const pk = derivePublicKey(KeyType::secp256k1, sk);
147  log << "public " << pk << std::endl;
148  log << "secret " << sk.to_string() << std::endl;
149 
150  auto sig = signDigest(pk, sk, digest);
151  log << "canonical sig " << strHex(sig) << std::endl;
152 
153  auto const non = makeNonCanonical(sig);
154  log << "non-canon sig " << strHex(non) << std::endl;
155 
156  {
157  auto const canonicality = ecdsaCanonicality(sig);
158  BEAST_EXPECT(canonicality);
159  BEAST_EXPECT(*canonicality == ECDSACanonicality::fullyCanonical);
160  }
161 
162  {
163  auto const canonicality = ecdsaCanonicality(non);
164  BEAST_EXPECT(canonicality);
165  BEAST_EXPECT(*canonicality != ECDSACanonicality::fullyCanonical);
166  }
167 
168  BEAST_EXPECT(verifyDigest(pk, digest, sig, false));
169  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
170  BEAST_EXPECT(verifyDigest(pk, digest, non, false));
171  BEAST_EXPECT(! verifyDigest(pk, digest, non, true));
172  }
173  */
174 
175  // Ensure that verification does the right thing with
176  // respect to the matrix of canonicality variables.
177  void
179  {
180  testcase("secp256k1 canonicality");
181 
182 #if 0
183  makeCanonicalityTestVectors();
184 #else
185  auto const digest = hex_to_digest(
186  "34C19028C80D21F3F48C9354895F8D5BF0D5EE7FF457647CF655F5530A3022A7");
187  auto const pk = hex_to_pk(
188  "025096EB12D3E924234E7162369C11D8BF877EDA238778E7A31FF0AAC5D0DBCF3"
189  "7");
190  auto const sk = hex_to_sk(
191  "AA921417E7E5C299DA4EEC16D1CAA92F19B19F2A68511F68EC73BBB2F5236F3D");
192  auto const sig = hex_to_sig(
193  "3045022100B49D07F0E934BA468C0EFC78117791408D1FB8B63A6492AD395AC2F3"
194  "60F246600220508739DB0A2EF81676E39F459C8BBB07A09C3E9F9BEB696294D524"
195  "D479D62740");
196  auto const non = hex_to_sig(
197  "3046022100B49D07F0E934BA468C0EFC78117791408D1FB8B63A6492AD395AC2F3"
198  "60F24660022100AF78C624F5D107E9891C60BA637444F71A129E47135D36D92AFD"
199  "39B856601A01");
200 
201  {
202  auto const canonicality = ecdsaCanonicality(sig);
203  BEAST_EXPECT(canonicality);
204  BEAST_EXPECT(*canonicality == ECDSACanonicality::fullyCanonical);
205  }
206 
207  {
208  auto const canonicality = ecdsaCanonicality(non);
209  BEAST_EXPECT(canonicality);
210  BEAST_EXPECT(*canonicality != ECDSACanonicality::fullyCanonical);
211  }
212 
213  BEAST_EXPECT(verifyDigest(pk, digest, sig, false));
214  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
215  BEAST_EXPECT(verifyDigest(pk, digest, non, false));
216  BEAST_EXPECT(!verifyDigest(pk, digest, non, true));
217 #endif
218  }
219 
220  void
222  {
223  testcase("secp256k1 digest");
224 
225  for (std::size_t i = 0; i < 32; i++)
226  {
227  auto const [pk, sk] = randomKeyPair(KeyType::secp256k1);
228 
229  BEAST_EXPECT(pk == derivePublicKey(KeyType::secp256k1, sk));
230  BEAST_EXPECT(*publicKeyType(pk) == KeyType::secp256k1);
231 
232  for (std::size_t j = 0; j < 32; j++)
233  {
234  uint256 digest;
235  beast::rngfill(digest.data(), digest.size(), crypto_prng());
236 
237  auto sig = signDigest(pk, sk, digest);
238 
239  BEAST_EXPECT(sig.size() != 0);
240  BEAST_EXPECT(verifyDigest(pk, digest, sig, true));
241 
242  // Wrong digest:
243  BEAST_EXPECT(!verifyDigest(pk, ~digest, sig, true));
244 
245  // Slightly change the signature:
246  if (auto ptr = sig.data())
247  ptr[j % sig.size()]++;
248 
249  // Wrong signature:
250  BEAST_EXPECT(!verifyDigest(pk, digest, sig, true));
251 
252  // Wrong digest and signature:
253  BEAST_EXPECT(!verifyDigest(pk, ~digest, sig, true));
254  }
255  }
256  }
257 
258  void
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);
271  beast::rngfill(data.data(), data.size(), crypto_prng());
272 
273  auto sig = sign(pk, sk, makeSlice(data));
274 
275  BEAST_EXPECT(sig.size() != 0);
276  BEAST_EXPECT(verify(pk, makeSlice(data), sig, true));
277 
278  // Construct wrong data:
279  auto badData = data;
280 
281  // swaps the smallest and largest elements in buffer
283  std::min_element(badData.begin(), badData.end()),
284  std::max_element(badData.begin(), badData.end()));
285 
286  // Wrong data: should fail
287  BEAST_EXPECT(!verify(pk, makeSlice(badData), sig, true));
288 
289  // Slightly change the signature:
290  if (auto ptr = sig.data())
291  ptr[j % sig.size()]++;
292 
293  // Wrong signature: should fail
294  BEAST_EXPECT(!verify(pk, makeSlice(data), sig, true));
295 
296  // Wrong data and signature: should fail
297  BEAST_EXPECT(!verify(pk, makeSlice(badData), sig, true));
298  }
299  }
300  }
301 
302  void
304  {
305  testcase("Base58");
306 
307  // Ensure that parsing some well-known secret keys works
308  {
309  auto const sk1 = generateSecretKey(
310  KeyType::secp256k1, generateSeed("masterpassphrase"));
311 
312  auto const sk2 = parseBase58<SecretKey>(
314  "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe");
315  BEAST_EXPECT(sk2);
316 
317  BEAST_EXPECT(sk1 == *sk2);
318  }
319 
320  {
321  auto const sk1 = generateSecretKey(
322  KeyType::ed25519, generateSeed("masterpassphrase"));
323 
324  auto const sk2 = parseBase58<SecretKey>(
326  "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36");
327  BEAST_EXPECT(sk2);
328 
329  BEAST_EXPECT(sk1 == *sk2);
330  }
331 
332  // Try converting short, long and malformed data
333  BEAST_EXPECT(!parseBase58<SecretKey>(TokenType::NodePrivate, ""));
334  BEAST_EXPECT(!parseBase58<SecretKey>(TokenType::NodePrivate, " "));
335  BEAST_EXPECT(!parseBase58<SecretKey>(
336  TokenType::NodePrivate, "!35gty9mhju8nfjl"));
337 
338  auto const good = toBase58(TokenType::NodePrivate, randomSecretKey());
339 
340  // Short (non-empty) strings
341  {
342  auto s = good;
343 
344  // Remove all characters from the string in random order:
346 
347  while (!s.empty())
348  {
349  s.erase(r(s) % s.size(), 1);
350  BEAST_EXPECT(
351  !parseBase58<SecretKey>(TokenType::NodePrivate, s));
352  }
353  }
354 
355  // Long strings
356  for (std::size_t i = 1; i != 16; i++)
357  {
358  auto s = good;
359  s.resize(s.size() + i, s[i % s.size()]);
360  BEAST_EXPECT(!parseBase58<SecretKey>(TokenType::NodePrivate, s));
361  }
362 
363  // Strings with invalid Base58 characters
364  for (auto c : std::string("0IOl"))
365  {
366  for (std::size_t i = 0; i != good.size(); ++i)
367  {
368  auto s = good;
369  s[i % s.size()] = c;
370  BEAST_EXPECT(
371  !parseBase58<SecretKey>(TokenType::NodePrivate, s));
372  }
373  }
374 
375  // Strings with incorrect prefix
376  {
377  auto s = good;
378 
379  for (auto c : std::string("ansrJqtv7"))
380  {
381  s[0] = c;
382  BEAST_EXPECT(
383  !parseBase58<SecretKey>(TokenType::NodePrivate, s));
384  }
385  }
386 
387  // Try some random secret keys
389 
390  for (std::size_t i = 0; i != keys.size(); ++i)
391  keys[i] = randomSecretKey();
392 
393  for (std::size_t i = 0; i != keys.size(); ++i)
394  {
395  auto const si = toBase58(TokenType::NodePrivate, keys[i]);
396  BEAST_EXPECT(!si.empty());
397 
398  auto const ski = parseBase58<SecretKey>(TokenType::NodePrivate, si);
399  BEAST_EXPECT(ski && keys[i] == *ski);
400 
401  for (std::size_t j = i; j != keys.size(); ++j)
402  {
403  BEAST_EXPECT((keys[i] == keys[j]) == (i == j));
404 
405  auto const sj = toBase58(TokenType::NodePrivate, keys[j]);
406 
407  BEAST_EXPECT((si == sj) == (i == j));
408 
409  auto const skj =
410  parseBase58<SecretKey>(TokenType::NodePrivate, sj);
411  BEAST_EXPECT(skj && keys[j] == *skj);
412 
413  BEAST_EXPECT((*ski == *skj) == (i == j));
414  }
415  }
416  }
417 
418  void
420  {
421  testcase("Miscellaneous operations");
422 
423  auto const sk1 = generateSecretKey(
424  KeyType::secp256k1, generateSeed("masterpassphrase"));
425 
426  SecretKey sk2(sk1);
427  BEAST_EXPECT(sk1 == sk2);
428 
429  SecretKey sk3;
430  BEAST_EXPECT(sk3 != sk2);
431  sk3 = sk2;
432  BEAST_EXPECT(sk3 == sk2);
433  }
434 
435  void
436  run() override
437  {
438  testBase58();
442 
443  testcase("secp256k1");
445 
446  testcase("ed25519");
448  }
449 };
450 
451 BEAST_DEFINE_TESTSUITE(SecretKey, protocol, ripple);
452 
453 } // 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:194
ripple::SecretKey_test::testMiscOperations
void testMiscOperations()
Definition: SecretKey_test.cpp:419
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:436
ripple::SecretKey_test::testSigning
void testSigning(KeyType type)
Definition: SecretKey_test.cpp:259
ripple::SecretKey_test::testBase58
void testBase58()
Definition: SecretKey_test.cpp:303
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: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:43
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< 256 >
ripple::SecretKey_test::testDigestSigning
void testDigestSigning()
Definition: SecretKey_test.cpp:221
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:178
ripple::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition: SecretKey.cpp:167
std::hash
string