xrpld
Loading...
Searching...
No Matches
PublicKey_test.cpp
1#include <xrpl/basics/Slice.h>
2#include <xrpl/beast/unit_test/suite.h>
3#include <xrpl/protocol/KeyType.h>
4#include <xrpl/protocol/PublicKey.h>
5#include <xrpl/protocol/SecretKey.h>
6#include <xrpl/protocol/Seed.h>
7#include <xrpl/protocol/tokens.h>
8
9#include <algorithm>
10#include <cstddef>
11#include <cstdint>
12#include <functional>
13#include <optional>
14#include <string>
15#include <vector>
16
17namespace xrpl {
18
20{
21public:
23
24 template <class FwdIter, class Container>
25 static void
26 hexToBinary(FwdIter first, FwdIter last, Container& out)
27 {
28 struct Table
29 {
30 int val[256]{};
31 Table()
32 {
33 std::fill(val, val + 256, 0);
34 for (int i = 0; i < 10; ++i)
35 val['0' + i] = i;
36 for (int i = 0; i < 6; ++i)
37 {
38 val['A' + i] = 10 + i;
39 val['a' + i] = 10 + i;
40 }
41 }
42 int
43 operator[](int i)
44 {
45 return val[i];
46 }
47 };
48
49 static Table kLut;
50 out.reserve(std::distance(first, last) / 2);
51 while (first != last)
52 {
53 auto const hi(kLut[(*first++)]);
54 auto const lo(kLut[(*first++)]);
55 out.push_back((hi * 16) + lo);
56 }
57 }
58
59 static blob
60 sig(std::string const& hex)
61 {
62 blob b;
63 hexToBinary(hex.begin(), hex.end(), b);
64 return b;
65 }
66
67 static bool
69 {
70 return ecdsaCanonicality(makeSlice(sig(s))) == answer;
71 }
72
73 void
75 {
76 testcase("Canonical");
77
78 // Fully canonical
79 BEAST_EXPECT(check(
81 "3045"
82 "022100FF478110D1D4294471EC76E0157540C2181F47DEBD25D7F9E7DDCCCD47EE"
83 "E905"
84 "0220078F07CDAE6C240855D084AD91D1479609533C147C93B0AEF19BC9724D003F"
85 "28"));
86 BEAST_EXPECT(check(
88 "3045"
89 "0221009218248292F1762D8A51BE80F8A7F2CD288D810CE781D5955700DA1684DF"
90 "1D2D"
91 "022041A1EE1746BFD72C9760CC93A7AAA8047D52C8833A03A20EAAE92EA19717B4"
92 "54"));
93 BEAST_EXPECT(check(
95 "3044"
96 "02206A9E43775F73B6D1EC420E4DDD222A80D4C6DF5D1BEECC431A91B63C928B75"
97 "81"
98 "022023E9CC2D61DDA6F73EAA6BCB12688BEB0F434769276B3127E4044ED895C9D9"
99 "6B"));
100 BEAST_EXPECT(check(
102 "3044"
103 "022056E720007221F3CD4EFBB6352741D8E5A0968D48D8D032C2FBC4F6304AD1D0"
104 "4E"
105 "02201F39EB392C20D7801C3E8D81D487E742FA84A1665E923225BD6323847C7187"
106 "9F"));
107 BEAST_EXPECT(check(
109 "3045"
110 "022100FDFD5AD05518CEA0017A2DCB5C4DF61E7C73B6D3A38E7AE93210A1564E8C"
111 "2F12"
112 "0220214FF061CCC123C81D0BB9D0EDEA04CD40D96BF1425D311DA62A7096BB18EA"
113 "18"));
114
115 // Canonical but not fully canonical
116 BEAST_EXPECT(check(
118 "3046"
119 "022100F477B3FA6F31C7CB3A0D1AD94A231FDD24B8D78862EE334CEA7CD08F6CBC"
120 "0A1B"
121 "022100928E6BCF1ED2684679730C5414AEC48FD62282B090041C41453C1D064AF5"
122 "97A1"));
123 BEAST_EXPECT(check(
125 "3045"
126 "022063E7C7CA93CB2400E413A342C027D00665F8BAB9C22EF0A7B8AE3AAF092230"
127 "B6"
128 "0221008F2E8BB7D09521ABBC277717B14B93170AE6465C5A1B36561099319C4BEB"
129 "254C"));
130 BEAST_EXPECT(check(
132 "3046"
133 "02210099DCA1188663DDEA506A06A7B20C2B7D8C26AFF41DECE69D6C5F7C967D32"
134 "625F"
135 "022100897658A6B1F9EEE5D140D7A332DA0BD73BB98974EA53F6201B01C1B594F2"
136 "86EA"));
137 BEAST_EXPECT(check(
139 "3045"
140 "02200855DE366E4E323AA2CE2A25674401A7D11F72EC432770D07F7B57DF7387AE"
141 "C0"
142 "022100DA4C6ADDEA14888858DE2AC5B91ED9050D6972BB388DEF582628CEE32869"
143 "AE35"));
144
145 // valid
146 BEAST_EXPECT(check(
148 "3006"
149 "020101"
150 "020102"));
151 BEAST_EXPECT(check(
153 "3044"
154 "02203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df"
155 "0c"
156 "022030b61dd36543125d56b9f9f3a1f53189e5af33cdda8d77a5209aec03978fa0"
157 "01"));
158 BEAST_EXPECT(check(
160 "3045"
161 "0220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f9"
162 "0a"
163 "0221008fffd599910eefe00bc803c688eca1d2ba7f6b180620eaa03488e6585db6"
164 "ba01"));
165 BEAST_EXPECT(check(
167 "3046"
168 "022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40"
169 "f90a"
170 "0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585d"
171 "b6ba"));
172
173 BEAST_EXPECT(check(
174 std::nullopt,
175 "3005"
176 "0201FF"
177 "0200"));
178 BEAST_EXPECT(check(
179 std::nullopt,
180 "3006"
181 "020101"
182 "020202"));
183 BEAST_EXPECT(check(
184 std::nullopt,
185 "3006"
186 "020701"
187 "020102"));
188 BEAST_EXPECT(check(
189 std::nullopt,
190 "3006"
191 "020401"
192 "020102"));
193 BEAST_EXPECT(check(
194 std::nullopt,
195 "3006"
196 "020501"
197 "020102"));
198 BEAST_EXPECT(check(
199 std::nullopt,
200 "3006"
201 "020201"
202 "020102"));
203 BEAST_EXPECT(check(
204 std::nullopt,
205 "3006"
206 "020301"
207 "020202"));
208 BEAST_EXPECT(check(
209 std::nullopt,
210 "3006"
211 "020401"
212 "020202"));
213 BEAST_EXPECT(check(
214 std::nullopt,
215 "3047"
216 "0221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba"
217 "6105"
218 "022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e56"
219 "6695ed"));
220 BEAST_EXPECT(check(
221 std::nullopt,
222 "3144"
223 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
224 "05"
225 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
226 "ed"));
227 BEAST_EXPECT(check(
228 std::nullopt,
229 "3045"
230 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
231 "05"
232 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
233 "ed"));
234 BEAST_EXPECT(check(
235 std::nullopt,
236 "301F"
237 "01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1"));
238 BEAST_EXPECT(check(
239 std::nullopt,
240 "3045"
241 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
242 "05"
243 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
244 "ed00"));
245 BEAST_EXPECT(check(
246 std::nullopt,
247 "3044"
248 "01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
249 "05"
250 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
251 "ed"));
252 BEAST_EXPECT(check(
253 std::nullopt,
254 "3024"
255 "0200"
256 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
257 "ed"));
258 BEAST_EXPECT(check(
259 std::nullopt,
260 "3044"
261 "02208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
262 "05"
263 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
264 "ed"));
265 BEAST_EXPECT(check(
266 std::nullopt,
267 "3045"
268 "0221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba"
269 "6105"
270 "02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
271 "ed"));
272 BEAST_EXPECT(check(
273 std::nullopt,
274 "3044"
275 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
276 "05012"
277 "02d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695e"
278 "d"));
279 BEAST_EXPECT(check(
280 std::nullopt,
281 "3024"
282 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
283 "05"
284 "0200"));
285 BEAST_EXPECT(check(
286 std::nullopt,
287 "3044"
288 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
289 "05"
290 "0220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695"
291 "ed"));
292 BEAST_EXPECT(check(
293 std::nullopt,
294 "3045"
295 "02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61"
296 "05"
297 "0221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e5666"
298 "95ed"));
299 }
300
301 void
303 {
304 // Try converting short, long and malformed data
307 BEAST_EXPECT(!parseBase58<PublicKey>(TokenType::NodePublic, "!ty89234gh45"));
308
309 auto const good =
311
312 // Short (non-empty) strings
313 {
314 auto s = good;
315
316 // Remove all characters from the string in random order:
318
319 while (!s.empty())
320 {
321 s.erase(r(s) % s.size(), 1);
323 }
324 }
325
326 // Long strings
327 for (std::size_t i = 1; i != 16; i++)
328 {
329 auto s = good;
330 s.resize(s.size() + i, s[i % s.size()]);
332 }
333
334 // Strings with invalid Base58 characters
335 for (auto c : std::string("0IOl"))
336 {
337 for (std::size_t i = 0; i != good.size(); ++i)
338 {
339 auto s = good;
340 s[i % s.size()] = c;
342 }
343 }
344
345 // Strings with incorrect prefix
346 {
347 auto s = good;
348
349 for (auto c : std::string("apsrJqtv7"))
350 {
351 s[0] = c;
353 }
354 }
355
356 // Try some random secret keys
358 keys.reserve(32);
359
360 for (std::size_t i = 0; i != keys.capacity(); ++i)
362 BEAST_EXPECT(keys.size() == 32);
363
364 for (std::size_t i = 0; i != keys.size(); ++i)
365 {
366 auto const si = toBase58(TokenType::NodePublic, keys[i]);
367 BEAST_EXPECT(!si.empty());
368
369 auto const ski = parseBase58<PublicKey>(TokenType::NodePublic, si);
370 BEAST_EXPECT(ski && (keys[i] == *ski));
371
372 for (std::size_t j = i; j != keys.size(); ++j)
373 {
374 BEAST_EXPECT((keys[i] == keys[j]) == (i == j));
375
376 auto const sj = toBase58(TokenType::NodePublic, keys[j]);
377
378 BEAST_EXPECT((si == sj) == (i == j));
379
380 auto const skj = parseBase58<PublicKey>(TokenType::NodePublic, sj);
381 BEAST_EXPECT(skj && (keys[j] == *skj));
382
383 BEAST_EXPECT(
384 (*ski == *skj) == (i == j)); // NOLINT(bugprone-unchecked-optional-access)
385 }
386 }
387 }
388
389 void
391 {
392 testcase("Base58: secp256k1");
393
394 {
395 auto const pk1 = derivePublicKey(
398
399 auto const pk2 = parseBase58<PublicKey>(
400 TokenType::NodePublic, "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9");
401 BEAST_EXPECT(pk2);
402
403 BEAST_EXPECT(pk1 == *pk2); // NOLINT(bugprone-unchecked-optional-access)
404 }
405
407
408 testcase("Base58: ed25519");
409
410 {
411 auto const pk1 = derivePublicKey(
413 generateSecretKey(KeyType::Ed25519, generateSeed("masterpassphrase")));
414
415 auto const pk2 = parseBase58<PublicKey>(
416 TokenType::NodePublic, "nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf");
417 BEAST_EXPECT(pk2);
418
419 BEAST_EXPECT(pk1 == *pk2); // NOLINT(bugprone-unchecked-optional-access)
420 }
421
423 }
424
425 void
427 {
428 testcase("Miscellaneous operations");
429
430 auto const pk1 = derivePublicKey(
433
434 PublicKey const pk2(pk1);
435 BEAST_EXPECT(pk1 == pk2);
436 BEAST_EXPECT(pk2 == pk1);
437
440 generateSecretKey(KeyType::Secp256k1, generateSeed("arbitraryPassPhrase")));
441 // Testing the copy assignment operation of PublicKey class
442 pk3 = pk2;
443 BEAST_EXPECT(pk3 == pk2);
444 BEAST_EXPECT(pk1 == pk3);
445 }
446
447 void
448 run() override
449 {
450 testBase58();
453 }
454};
455
457
458} // namespace xrpl
T capacity(T... args)
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
void run() override
Runs the suite.
void testBase58(KeyType keyType)
static bool check(std::optional< ECDSACanonicality > answer, std::string const &s)
static blob sig(std::string const &hex)
std::vector< std::uint8_t > blob
static void hexToBinary(FwdIter first, FwdIter last, Container &out)
A public key.
Definition PublicKey.h:42
T distance(T... args)
T emplace_back(T... args)
T fill(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
KeyType
Definition KeyType.h:8
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:93
std::optional< ECDSACanonicality > ecdsaCanonicality(Slice const &sig)
Determines the canonicality of a signature.
SecretKey generateSecretKey(KeyType type, Seed const &seed)
Generate a new secret key deterministically.
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition Seed.cpp:58
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
std::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:215
T reserve(T... args)
T size(T... args)