#if USE_MONERO START_TEST(test_xmr_base58) { static const struct { uint64_t tag; char *v1; char *v2; } tests[] = { {0x12, "3bec484c5d7f0246af520aab550452b5b6013733feabebd681c4a60d457b7fc12d5918e31d3c003da3c778592c07b398ad6f961a67082a75fd49394d51e69bbe", "43tpGG9PKbwCpjRvNLn1jwXPpnacw2uVUcszAtgmDiVcZK4VgHwjJT9BJz1WGF9eMxSYASp8yNMkuLjeQfWqJn3CNWdWfzV" }, {0x12, "639050436fa36c8288706771412c5972461578d564188cd7fc6f81d6973d064fa461afe66fb23879936d7225051bebbf7f3ae0c801a90bb99fbb346b2fd4d702", "45PwgoUKaDHNqLL8o3okzLL7biv7GqPVmd8LTcTrYVrMEKdSYwFcyJfMLSRpfU3nh8Z2m81FJD4sUY3nXCdGe61k1HAp8T1" }, {53, "5a10cca900ee47a7f412cd661b29f5ab356d6a1951884593bb170b5ec8b6f2e83b1da411527d062c9fedeb2dad669f2f5585a00a88462b8c95c809a630e5734c", "9vacMKaj8JJV6MnwDzh2oNVdwTLJfTDyNRiB6NzV9TT7fqvzLivH2dB8Tv7VYR3ncn8vCb3KdNMJzQWrPAF1otYJ9cPKpkr" }, }; uint8_t rawn[512]; char strn[512]; int r; uint64_t tag; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { const char *raw = tests[i].v1; const char *str = tests[i].v2; const size_t len = strlen(raw) / 2; memcpy(rawn, fromhex(raw), len); r = xmr_base58_addr_encode_check(tests[i].tag, rawn, len, strn, sizeof(strn)); ck_assert_int_eq((size_t) r, strlen(str)); ck_assert_mem_eq(strn, str, r); r = xmr_base58_addr_decode_check(strn, r, &tag, rawn, len); ck_assert_int_eq(r, len); ck_assert_mem_eq(rawn, fromhex(raw), len); } } END_TEST START_TEST(test_xmr_getset256_modm) { static const struct { uint64_t val; int r; char *a; } tests[] = { {0x0, 1, "0000000000000000000000000000000000000000000000000000000000000000"}, {0x7fffffffULL, 1, "ffffff7f00000000000000000000000000000000000000000000000000000000"}, {0x7fffffffffffffffULL, 1, "ffffffffffffff7f000000000000000000000000000000000000000000000000"}, {0xdeadc0deULL, 1, "dec0adde00000000000000000000000000000000000000000000000000000000"}, {0x0, 0, "dec0adde000000000000000000000000000000000000000000000000000000ff"}, {0x0, 0, "ffffffffffffffffff0000000000000000000000000000000000000000000000"}, }; uint8_t rawn[32]; uint64_t v1; bignum256modm a1 = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { int get_res = tests[i].r; if (get_res) { set256_modm(a1, tests[i].val); ck_assert_int_eq(get256_modm(&v1, a1), 1); ck_assert(v1 == tests[i].val); contract256_modm(rawn, a1); ck_assert_mem_eq(rawn, fromhex(tests[i].a), 32); } else { expand256_modm(a1, fromhex(tests[i].a), 32); ck_assert_int_eq(get256_modm(&v1, a1), 0); } } } END_TEST START_TEST(test_xmr_cmp256_modm) { static const struct { char *a; char *b; int res_eq; int res_cmp; int res_is_zero_a; } tests[] = { { "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", 1, 0, 1 }, { "0000000000000000000000000000000000000000000000000000000000000000", "0100000000000000000000000000000000000000000000000000000000000000", 0, -1, 1 }, { "dec0adde00000000000000000000000000000000000000000000000000000000", "dec0adde00000000000000000000000000000000000000000000000000000000", 1, 0, 0 }, { "863346d8863c461cde2ec7c2759352c2b952228f33a86ca06bb79574bbe5c30d", "3ddbd65a6d3ba5e2ab120603685a353a27ce3fd21dfdbea7952d2dd26f1ca00a", 0, 1, 0 }, { "f7667f392edbea6e224b1aa9fbf2a3b238b4f977fb4a8f39130cc45f49b5c40a", "b41b9b1e7e80be71cf290ed4bded58924086b8ac6bdfa1faa0c80c255f074d07", 0, 1, 0 }, { "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27501", "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 0, -1, 0 }, { "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 1, 0, 0 }, { "0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", "0e4005c7826de8f9978749903f41efd140e4ae6d3bed09e558fcce8367b27504", 0, -1, 0 }, }; bignum256modm a1 = {0}, a2 = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(a1, fromhex(tests[i].a), 32); expand256_modm(a2, fromhex(tests[i].b), 32); ck_assert_int_eq(eq256_modm(a1, a2), tests[i].res_eq); ck_assert_int_eq(cmp256_modm(a1, a2), tests[i].res_cmp); ck_assert_int_eq(iszero256_modm(a1), tests[i].res_is_zero_a); } } END_TEST START_TEST(test_xmr_copy_check_modm) { static const struct { int check; char *a; } tests[] = { {0, "0000000000000000000000000000000000000000000000000000000000000000"}, {1, "ffffff7f00000000000000000000000000000000000000000000000000000000"}, {1, "ffffffffffffff7f000000000000000000000000000000000000000000000000"}, {1, "dec0adde00000000000000000000000000000000000000000000000000000000"}, {0, "dec0adde000000000000000000000fffffffffffffffffffffffffffffffffff"}, }; bignum256modm a1 = {0}, a2 = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand_raw256_modm(a1, fromhex(tests[i].a)); copy256_modm(a2, a1); ck_assert_int_eq(eq256_modm(a1, a2), 1); ck_assert_int_eq(check256_modm(a1), tests[i].check); } } END_TEST START_TEST(test_xmr_mulsub256_modm) { static const struct { char *a; char *b; char *c; char *r; } tests[] = { { "713c199348cf7d14b67ae6265ea49c02c8647f07afcbcb6f8d3254b3db972e02", "4e48a7b7a03ab1106fdfa9441a03c97c644395a12ac4b8effac7344e0719c200", "1a5711b8c43bcab0161a620368d82727e1d027dc248f420d9bb4db2486c16405", "6edcc08aa6ec3a5b3d333b5f826be7de9c268be8aaf9521586fbcccbed3b1c0c", }, { "d4ade2c62d34af8cfd9daec6f46bf7e57962a8aa46935cb11fab64fa599b4700", "22ea7989a9f4d34cd8c9442e03b5062dfe8493757cd18a63411cb1a25e44960f", "772053e613f0859387badcefeb7fbe551a05b00b9337539c8d72661de5929806", "a5063258df4520b33e97c0a46d80feeace5c251fc7ef7a938d160b8f25795106", }, { "01fd2ef25c8221277a2b6daf1f1642bacb8d6ac0dd4f62731cdd73e26eb77900", "0611b9357530aa638428002769ce0ad553421e971bea1f10d7009bf26d9af805", "dfece232068b2f8059ca569f345baaed13ab464eb3bebb99de5625dc90a8cf03", "85752e62bd8085c7c02d5edeb74969d22f1a5bb34349258d2e96de300176bb07", }, }; bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(a, fromhex(tests[i].a), 32); expand256_modm(b, fromhex(tests[i].b), 32); expand256_modm(c, fromhex(tests[i].c), 32); expand256_modm(r, fromhex(tests[i].r), 32); mulsub256_modm(r2, a, b, c); ck_assert_int_eq(eq256_modm(r, r2), 1); } } END_TEST START_TEST(test_xmr_muladd256_modm) { static const struct { char *a; char *b; char *c; char *r; } tests[] = { { "7c3fd8abfbe2be3739d91679ac8dbda086961b941e0d4a00561f758927d8aa09", "ac2d8d37e4f344aa4040d0f0fc29d45423ab7e69ecacb94ca9fc36819e0e990e", "2f03f1bac09bc7d002848b68be069dc98b2db028390ae37e13a5166fcae08105", "dce113add3392f08e3b38b7d31e237eba5066e5a95a1fdbf755b92d05e1ec70b", }, { "6979b70f6198d043f4b14e2069f7b89cc9f09e3465e71d472946443989e0e80c", "8dd5177bc8d7c5bd58c0be74b336952a73ac259ebb812ac8cd755773c6aab807", "d7658e508a7454ccfb29e2890d6156ac10e18ebe6e00cc5a2d2d87a5080c7f06", "51b33f6263772781cdbab26ef48870eaf94899894a437dac39496f15b9d0ae00", }, { "ebfdb4eabedb1fb9a45b3204735b0511871e20358392fa16a851c519e3a29b09", "59d98831e9f9e24260158986c4d4035438de9b8876cc11bdcf4c364c75f72908", "93bce4764eee97dc67f2e37da40bc5641f2cdc637285d273287a3d4383b68f02", "21547ca6855c85d5adcd673b9d801d0cb0f10dced8f8b68a8c2f74163defde0e", }, }; bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(a, fromhex(tests[i].a), 32); expand256_modm(b, fromhex(tests[i].b), 32); expand256_modm(c, fromhex(tests[i].c), 32); expand256_modm(r, fromhex(tests[i].r), 32); muladd256_modm(r2, a, b, c); ck_assert_int_eq(eq256_modm(r, r2), 1); } } END_TEST START_TEST(test_xmr_curve25519_set) { static const struct { uint32_t val; char *a; } tests[] = { {0x0, "0000000000000000000000000000000000000000000000000000000000000000"}, {0x1, "0100000000000000000000000000000000000000000000000000000000000000"}, {0xdeadc0deUL, "dec0adde00000000000000000000000000000000000000000000000000000000"}, }; unsigned char buff[32]; bignum25519 a = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { curve25519_set(a, tests[i].val); curve25519_contract(buff, a); ck_assert_mem_eq(buff, fromhex(tests[i].a), 32); } } END_TEST START_TEST(test_xmr_curve25519_consts) { char *d = "a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352"; char *d2 = "59f1b226949bd6eb56b183829a14e00030d1f3eef2808e19e7fcdf56dcd90624"; char *sqrtneg1 = "b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b"; unsigned char buff[32]; bignum25519 a = {0}; curve25519_set_d(a); curve25519_contract(buff, a); ck_assert_mem_eq(buff, fromhex(d), 32); curve25519_set_2d(a); curve25519_contract(buff, a); ck_assert_mem_eq(buff, fromhex(d2), 32); curve25519_set_sqrtneg1(a); curve25519_contract(buff, a); ck_assert_mem_eq(buff, fromhex(sqrtneg1), 32); } END_TEST START_TEST(test_xmr_curve25519_tests) { static const struct { char *a; int res_neg; int res_nonzero; } tests[] = { { "0000000000000000000000000000000000000000000000000000000000000000", 0, 0, }, { "0100000000000000000000000000000000000000000000000000000000000000", 1, 1, }, { "05737aa6100ee54283dc0d483b8e39e61846f6b3736908243d0c824d250b3139", 1, 1, }, { "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", 1, 1, }, { "02587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", 0, 1, }, }; bignum25519 a = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { curve25519_expand(a, fromhex(tests[i].a)); ck_assert_int_eq(curve25519_isnegative(a), tests[i].res_neg); ck_assert_int_eq(curve25519_isnonzero(a), tests[i].res_nonzero); } } END_TEST START_TEST(test_xmr_curve25519_expand_reduce) { static const struct { char *a; char *b; } tests[] = { { "dec0adde00000000000000000000000000000000000000000000000000000000", "dec0adde00000000000000000000000000000000000000000000000000000000" }, { "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15", "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15" }, { "95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bcff", "a8587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc7f" }, { "95587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bcff", "a8587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bc7f" }, }; unsigned char buff[32]; bignum25519 a = {0}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { curve25519_expand_reduce(a, fromhex(tests[i].a)); curve25519_contract(buff, a); ck_assert_mem_eq(buff, fromhex(tests[i].b), 32); } } END_TEST START_TEST(test_xmr_ge25519_base) { unsigned char buff[32]; char *base = "5866666666666666666666666666666666666666666666666666666666666666"; ge25519 b; ge25519_set_base(&b); ge25519_pack(buff, &b); ck_assert_mem_eq(buff, fromhex(base), 32); } END_TEST START_TEST(test_xmr_ge25519_check) { static const struct { char *x; char *y; char *z; char *t; int r; } tests[] = { { "4ff97748221f954414f836d84e8e7e207786bcd20eb67044756dca307e792c60", "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63", "0100000000000000000000000000000000000000000000000000000000000000", "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 1 }, { "358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", "ca48045f790145a1eec3946dfd73747fde0fdb4238607e0a203f8ef5bef90e0e", "0100000000000000000000000000000000000000000000000000000000000000", "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 1 }, { "4ff97748221f954414f836d84e8e7e207786bcd20eb6704475ffca307e792c60", "2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63", "0100000000000000000000000000000000000000000000000000000000000000", "3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 0 }, { "358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e", "0100000000000000000000000000000000000000000000000000000000000000", "6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0 }, { "358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c", "ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e", "0100000000000000000000000000000000000000000000000000000000000000", "6c5e5ffae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0 }, }; struct ge25519_t p; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { curve25519_expand_reduce(p.x, fromhex(tests[i].x)); curve25519_expand_reduce(p.y, fromhex(tests[i].y)); curve25519_expand_reduce(p.z, fromhex(tests[i].z)); curve25519_expand_reduce(p.t, fromhex(tests[i].t)); ck_assert_int_eq(ge25519_check(&p), tests[i].r); } } END_TEST START_TEST(test_xmr_ge25519_scalarmult_base_wrapper) { static const struct { char *sc; char *pt; } tests[] = { { "40be740e26bd1c84f5a8fec737c0ed30e87bd45adfcd91e320f8dfb68b1a870e", "b7a8b2f3dbfd41b38d20aec733a316dbfc2633503799cd36f38570cafc8ea887", }, { "1b3746add992215d427e43a58354c11ff9e6dfa1c187250938f7f9334fa41d05", "e2a1bfbe38a9749fe6ede79d923b778fa4c89393473d633bec01fa68617d0828", }, { "69af25c54090a9746d3f6043348452429ffd53c1530fa114fd0055b70d61020f", "6bf1783b0a7495d5f6c36605dca95e723ca120a306c255084787f09b12771124", }, { "0000000000000000000000000000000000000000000000000000000000000000", "0100000000000000000000000000000000000000000000000000000000000000", }, { "0100000000000000000000000000000000000000000000000000000000000000", "5866666666666666666666666666666666666666666666666666666666666666", }, { "0800000000000000000000000000000000000000000000000000000000000000", "b4b937fca95b2f1e93e41e62fc3c78818ff38a66096fad6e7973e5c90006d321", }, { "ffffffffffffffff000000000000000000000000000000000000000000000000", "e185757a3fdc6519a6e7bebd97aa52bdc999e4c87d5c3aad0d995763ab6c6985", }, }; ge25519 pt, pt2; bignum256modm sc; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(sc, fromhex(tests[i].sc), 32); ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); ge25519_scalarmult_base_wrapper(&pt2, sc); ck_assert_int_eq(ge25519_eq(&pt, &pt2), 1); } } END_TEST START_TEST(test_xmr_ge25519_scalarmult) { static const struct { char *sc; char *pt; char *pt2; } tests[] = { { "0000000000000000000000000000000000000000000000000000000000000000", "5cbb3b2784c16f0e7eb4f2a7f93288552bb24ec51c5e01504c1e6885cfbca6d0", "0100000000000000000000000000000000000000000000000000000000000000", }, { "0100000000000000000000000000000000000000000000000000000000000000", "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6", "f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6", }, { "3930000000000000000000000000000000000000000000000000000000000000", "2835b3983e3cc01a640fd188bf6bbbafbf997a3344d800eed22e4e82a412941c", "2fe8b2dd0f23e02fca6989e170135584d684583c0a44f6a7d3ebd964685d36c7", }, { "ffffffffffffffff000000000000000000000000000000000000000000000000", "bb8af7a53a8f1b477c810e833a84cdc789a6b81a6b6417be4f97ffd9ae0fe0b8", "3a5c9a7dacca9dd8827881f38c36aad7d402a5efc2cab58c7553b903876e1491", }, { "864203a09e1c788a482685c739af07355ebb2c840b7de6af87eff5f19ee3b807", "d404a9bbf351e7320ea6d11cdeeccaf505f706731cb5e5d839b950edb7ba6286", "11e09c89e0be7663e0e2d4a01fb05d6a3fd84a78a6fa4fd7daaacf2d19311a38", }, { "3e01f05920a238e33766814d10f0c3a3e975072399ad90a823d4808db1d85209", "52a2d35798a0ac209b8fa194fe398b869aba5f20d80ee3d8ca77759a8e0bae0d", "4256addc2f036150f3fdc0a7905f01285239d6dd4eecc4be8e3b134eef4639fe", }, { "ad63d591716a9e89a024a074bc6ce661268d1bb3665f91e8b981f189b1a49507", "3928bde7a92e1341c3dfee35a66fa5639204f5b9747963278af430145028648d", "9c959003ba91004956df98800a5024d94031db5ac659675b26350657d93c34f9", }, }; ge25519 pt, pt2, pt3; bignum256modm sc; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(sc, fromhex(tests[i].sc), 32); ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); ge25519_unpack_vartime(&pt2, fromhex(tests[i].pt2)); ge25519_scalarmult(&pt3, &pt, sc); ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1); } } END_TEST START_TEST(test_xmr_ge25519_ops) { int tests[] = {1, 2, 7, 8, 637, 9912, 12345}; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { struct ge25519_t a, b, c, d; bignum256modm s1 = {0}, s2 = {0}, s3 = {0}, s4 = {0}; set256_modm(s1, tests[i]); set256_modm(s2, 8 * tests[i]); set256_modm(s3, 8); set256_modm(s4, 2); ge25519_scalarmult_base_niels(&a, ge25519_niels_base_multiples, s1); ge25519_scalarmult_base_niels(&b, ge25519_niels_base_multiples, s2); ge25519_scalarmult(&c, &a, s4); ge25519_scalarmult(&c, &c, s4); ge25519_scalarmult(&c, &c, s4); ck_assert_int_eq(ge25519_eq(&c, &b), 1); ck_assert_int_eq(ge25519_eq(&a, &b), 0); ge25519_scalarmult_base_wrapper(&a, s1); ge25519_mul8(&b, &a); ge25519_scalarmult_base_wrapper(&c, s2); ck_assert_int_eq(ge25519_eq(&b, &c), 1); ge25519_scalarmult(&d, &a, s3); ck_assert_int_eq(ge25519_eq(&d, &c), 1); ge25519_copy(&a, &b); ge25519_neg_full(&b); ck_assert_int_eq(ge25519_eq(&b, &c), 0); ge25519_add(&c, &a, &b, 0); set256_modm(s2, 0); ge25519_scalarmult_base_wrapper(&a, s2); ck_assert_int_eq(ge25519_eq(&a, &c), 1); } } END_TEST START_TEST(test_xmr_check_point) { static const struct { char *p; bool on; } tests[] = { {"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", true}, {"54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5", true}, {"bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808", true}, {"00000000000000c60073ec000000000000ff0000000000000000000000000080", false}, {"00000000000000004e0000000000000000000000000000000000000000000000", false}, {"0000008b0000000000000000b200000000000000000000000000000000000080", false}, {"a0953eebe2f676256c37af4f6f84f32d397aaf3b73606e96c5ddfcecbb1ceec8", false}, {"a82cd837efee505ec8425769ea925bee869ec3c78a57708c64c2ef2bd6ad3b88", false}, {"031c56cfc99758f6f025630e77c6dea0b853c3ab0bf6cf8c8dab03d1a4618178", false}, }; ge25519 tmp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { int res = ge25519_unpack_negative_vartime(&tmp, fromhex(tests[i].p)); ck_assert_int_eq(ge25519_check(&tmp), tests[i].on); ck_assert_int_eq(res, tests[i].on); } } END_TEST START_TEST(test_xmr_h) { char *H = "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"; ge25519 H2, Z; ge25519_p1p1 P_11; ge25519_pniels P_ni; uint8_t buff[32] = {0}; ge25519_pack(buff, &xmr_h); ck_assert_mem_eq(buff, fromhex(H), 32); int res = ge25519_unpack_vartime(&H2, buff); ck_assert_int_eq(res, 1); ck_assert_int_eq(ge25519_eq(&xmr_h, &xmr_h), 1); ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1); res = ge25519_unpack_negative_vartime(&H2, buff); ck_assert_int_eq(res, 1); ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 0); ge25519_neg_full(&H2); ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1); ge25519_full_to_pniels(&P_ni, &xmr_h); ge25519_pnielsadd_p1p1(&P_11, &H2, &P_ni, 1); ge25519_p1p1_to_full(&H2, &P_11); ge25519_set_neutral(&Z); ck_assert_int_eq(ge25519_eq(&Z, &H2), 1); } END_TEST START_TEST(test_xmr_fast_hash) { uint8_t hash[32]; char tests[][2][65] = { {"", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"}, {"00", "bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"}, {"000102", "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"}, {"000102030405", "51e8babe8b42352100dffa7f7b3843c95245d3d545c6cbf5052e80258ae80627"}, {"000102030406", "74e7a0111ee2390dc68269a549a76dcfb553ca1260035eae982d669ff6494f32"}, {"000102030407", "3a81c5d02a87786343f88414aae150a09f6933b1d3bb660d0a9ac54e12e5cd86"}, {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64", "7fb4d1c8e32f7414fe8c7b2774ec05bff6845e4278565d17f95559513a244da2"}, {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", "2998fe52f8b9883149babd9c546912c3edfbd3cd98896a0e57b1b5929fa5ff7b"}, }; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { xmr_fast_hash(hash, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); ck_assert_mem_eq(hash, fromhex(tests[i][1]), 32); } } END_TEST START_TEST(test_xmr_hasher) { Hasher hasher; uint8_t hash[32]; static const struct { char * chunk[3]; char * hash; } tests[] = { { {"00", "01", "02"}, "f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"}, { {"001122334455667788", "00", ""}, "72a228ee8d0d01c815f112ce315cfc215a0594abcec24162304ae0ffda139d9e"}, { {"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", "", "00112233445566"}, "c3deafd96ff10cc190c6024548c344f6401cfe5151ab2fcd40df7cc501147e01"}, }; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { xmr_hasher_init(&hasher); for(int j = 0; j < 3; j++){ xmr_hasher_update(&hasher, fromhex(tests[i].chunk[j]), strlen(tests[i].chunk[j]) / 2); } xmr_hasher_final(&hasher, hash); ck_assert_mem_eq(hash, fromhex(tests[i].hash), 32); } } END_TEST START_TEST(test_xmr_hash_to_scalar) { bignum256modm a1; unsigned char out[32]; char tests[][2][65] = { {"", "4a078e76cd41a3d3b534b83dc6f2ea2de500b653ca82273b7bfad8045d85a400"}, {"00", "5497c9b6a7059553835f85118dc089d66512f7b477d66591ff96a9e064bcc90a"}, {"000102", "5727ca206dbafa2e099b022ed528f5bdf7874e3ec09c8f012159dfeeaab2b106"}, {"000102030405", "7740cf04577c107153a50b3abe44859f5245d3d545c6cbf5052e80258ae80607"}, {"000102030406", "ad6bbffaceb8020543ac82bcadb9d090b553ca1260035eae982d669ff6494f02"}, {"000102030407", "d2e116e9576ee5a29011c8fcb41259f99e6933b1d3bb660d0a9ac54e12e5cd06"}, {"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64", "3d6d3727dc50bca39e6ccfc9c12950eef5845e4278565d17f95559513a244d02"}, {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", "aecc45c83f0408c96c70f8273e94f930edfbd3cd98896a0e57b1b5929fa5ff0b"}, }; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { xmr_hash_to_scalar(a1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); contract256_modm(out, a1); ck_assert_mem_eq(out, fromhex(tests[i][1]), 32); } } END_TEST START_TEST(test_xmr_hash_to_ec) { ge25519 p1; unsigned char out[32]; char tests[][2][65] = { {"", "d6d7d783ab18e1be65586adb7902a4175b737ef0b902875e1d1d5c5cf0478c0b"}, {"00", "8e2fecb36320bc4e192e10ef54afc7c83fbeb0c38b7debd4fea51301f0bd4f3d"}, {"000102", "73b233e2e75d81b9657a857e38e7ab2bc3600e5c56622b9fe4b976ff312220fa"}, {"000102030405", "bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808"}, {"000102030406", "525567a6a40a94f2d916bc1efea234bbd3b9162403ec2faba871a90f8d0d487e"}, {"000102030407", "99b1be2a92cbd22b24b48fb7a9daadd4d13a56915c4f6ed696f271ad5bdbc149"}, {"42f6835bf83114a1f5f6076fe79bdfa0bd67c74b88f127d54572d3910dd09201", "54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5"}, {"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05", "001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608"}, }; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { xmr_hash_to_ec(&p1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2); ge25519_pack(out, &p1); ck_assert_mem_eq(out, fromhex(tests[i][1]), 32); } } END_TEST START_TEST(test_xmr_derivation_to_scalar) { static const struct { char *pt; uint32_t idx; char *sc; } tests[] = { { "c655b2d9d2670a1c9f26f7586b6d6b1ec5173b8b33bca64c3d305a42d66738b1", 0, "ca7ce31b273dd1ac00dc3553e654fb66036804800e27c826bd2b78649243900b", }, { "2b1dbd7a007dcc4d729fa8359705595599737fcef60afb36b379fe033095dca7", 1, "60afd5a63b14845d3b92d16eac386713e4ff617fdc5c1a07c3212098c1f5610c", }, { "a48ed3797225dab4b4316b5e40107b6bd63e5f4dc517ba602774d703576ec771", 24, "fe81804091e50a5c2233faa6277360fbe1948ea15dddbae62c1d40bbd1918606", }, { "fa27b5b39741f5341b4e89269e3a05ff7e76ec7739843872468fc4bec8475410", 65537, "1ba36841f57aa8b799c4dd02b39d53e5fb7780d3f09f91a57a86dcb418d8d506", }, }; ge25519 pt; bignum256modm sc, sc2; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(sc, fromhex(tests[i].sc), 32); ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); xmr_derivation_to_scalar(sc2, &pt, tests[i].idx); ck_assert_int_eq(eq256_modm(sc, sc2), 1); xmr_derivation_to_scalar(sc2, &pt, tests[i].idx + 1); ck_assert_int_eq(eq256_modm(sc, sc2), 0); } } END_TEST START_TEST(test_xmr_generate_key_derivation) { static const struct { char *pt; char *sc; char *r; } tests[] = { { "38f94f27c8037aff025e365275ed1029fd636dda5f69e5f98fdcf92e0a28f31a", "8f1c73ee5327a43264a7b60b9e7882312b582f33e89846a8694dbf094bb3a90a", "1fbfe4dcc8c824c274649545f297fa320cd4c1689b1d0ff4887567c4d4a75649", }, { "26785c3941a32f194228eb659c5ee305e63868896defc50ee6c4e0e92d1e246a", "dbbffec4686ba8ab25e2f1b04c0e7ae51c5143c91353bfb5998430ebe365a609", "cca34db8dd682ec164d8973b555253934596b77849ef7709d9321121c25aba02", }, { "43505a8ce7248f70d3aae4f57fb59c254ce2b2a0cc2bcf50f2344e51d59b36b3", "19a802e35f6ff94efe96ec016effe04e635bbd9c1ce2612d5ba2ee4659456b06", "fc6c93a93f77ff89c18b9abf95b28ec8591ab97eee8e4afee93aa766a4bd3934", }, }; ge25519 pt, pt2, pt3; bignum256modm sc; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(sc, fromhex(tests[i].sc), 32); ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); ge25519_unpack_vartime(&pt2, fromhex(tests[i].r)); xmr_generate_key_derivation(&pt3, &pt, sc); ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1); ck_assert_int_eq(ge25519_eq(&pt3, &pt), 0); } } END_TEST START_TEST(test_xmr_derive_private_key) { static const struct { char *pt; uint32_t idx; char *base; char *r; } tests[] = { { "0541d8f069e5e80a892e39bbf1944ef578008cf9ecf1d100760a05858c1b709e", 0, "76967eeb0a3d181bb0b384be71c680a4287599f27b2ddbd07f8e06ab6f2c880e", "45728c5cb658e470790f124a01699d2126832b7e5c6b7760b6f11119b96ad603", }, { "fc6e0bd785a84e62c9ac8a97e0e604a79494bc2cf7b3b38ef8af7791c87b5bb8", 1, "32fbe149562b7ccb34bc4105b87b2a834024799336c8eea5e94df77f1ae9a807", "64508e83bbadf63f8ecfae4d9dcdd39a4ba23508a545e1a37026f0fa2539d601", }, { "f6bd7a72dc9444dc7e09a0eb4d312d36fe173693d6405b132a5b090297a04ea9", 65537, "333a8fcce6726457e4222a87b9b475c1fcf985f756c2029fcb39184c0a5c4804", "37c16a22da4c0082ebf4bf807403b169f75142a9bd8560ed45f3f9347218260e", }, }; ge25519 pt; bignum256modm base, res, res_exp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(base, fromhex(tests[i].base), 32); expand256_modm(res_exp, fromhex(tests[i].r), 32); ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); xmr_derive_private_key(res, &pt, tests[i].idx, base); ck_assert_int_eq(eq256_modm(res, res_exp), 1); ck_assert_int_eq(eq256_modm(res, base), 0); } } END_TEST START_TEST(test_xmr_derive_public_key) { static const struct { char *pt; uint32_t idx; char *base; char *r; } tests[] = { { "653f03e7766d472826aa49793bc0cfde698e6745ae5e4217980ba307739f2ed9", 0, "2a393f0858732970ac8dea003b17e1ce9371f0a045bd9b7af0d998262739f4cc", "f7a3db27c45f265f6a68a30137ca44289a6cf1a6db2cf482c59ebfb0142ad419", }, { "338e93f61e6470a5cc71c07b8caedd1a9a28da037aab65c1ca5538501b012c81", 1, "af3a1d39397d778731c4510110fd117dc02f756e390713d58f94a06203ce39eb", "779e2a043c881f06aba1952741fd753098615c4fafa8f62748467ab9bac43241", }, { "7735e9476440927b89b18d7a1e0645b218a1a6d28c642aebb16c1dba0926d5e4", 65537, "62c3eed062bd602f7f2164c69ad0b5a8eb3ea560c930f6b41abfc1c4839ea432", "6da4ebd29498d16c4e813abb3e328c83f9b01a7ba1da6e818071f8ec563626c8", }, }; ge25519 pt, base, res, res_exp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { ge25519_unpack_vartime(&pt, fromhex(tests[i].pt)); ge25519_unpack_vartime(&base, fromhex(tests[i].base)); ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); xmr_derive_public_key(&res, &pt, tests[i].idx, &base); ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); ck_assert_int_eq(ge25519_eq(&res, &base), 0); } } END_TEST START_TEST(test_xmr_add_keys2) { static const struct { char *a; char *b; char *B; char *r; } tests[] = { { "631238da9578d7cb8db16fc4322671bfcb251cc5228b060664800ec1895be608", "f9a73fca0be058415a148f9e2871be59e1fc7ae6f6193199125237e0d7c1630f", "ef5ca4fc90f330e825adcdc953da0b3becd853aa819219842790bb39775f2255", "06623fd0e7a3d787a4d224f6ca2fdab2dcd9d1221578515974b9c4dee65fdcf5", }, { "dac2e629e5c75c312253b19d1d3a0a423158fdd9cdcf4c7a7bf2717d0b748602", "0483d98d750d4977b499cefd558a0a61580823a37da2b011501e24718e6c7f0a", "51fd3cd2f1a603ec7be3b35da9c105d91c4304e6a63facf48d7730712cedc0ee", "f7a5d645ba01a5b7ccbe9636d14422bb587fc529317b23761f0e39222b783b87", }, { "817c4d2fd3e841d860bdab6b7ccf098f3e637eca468d0a3825c50b71f61d0e0c", "1f6c4795d7fb0d53b5775874ac4c0963607d2b7bd11a7c5d10735badc4a27207", "bef0e0ed09d602bbe1dd38358b5f8fca27fcad60a69440f104441c3fc68df9c7", "bc0fc824d74eca0e10eacd0bc2f3322e0bcb02a44ce53f2f5f1fc472f99be8d2", }, }; bignum256modm a, b; ge25519 B, res, res_exp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(a, fromhex(tests[i].a), 32); expand256_modm(b, fromhex(tests[i].b), 32); ge25519_unpack_vartime(&B, fromhex(tests[i].B)); ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); xmr_add_keys2(&res, a, b, &B); ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); ck_assert_int_eq(ge25519_eq(&res, &B), 0); xmr_add_keys2_vartime(&res, a, b, &B); ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); ck_assert_int_eq(ge25519_eq(&res, &B), 0); } } END_TEST START_TEST(test_xmr_add_keys3) { static const struct { char *a; char *A; char *b; char *B; char *r; } tests[] = { { "7048b8c4603ae194c502fa458b0e11a4c7a330852bbef66b7c1d67e9f919f509", "9167c5b182758699baeb421e7f1200272fc775e4c7c7c183cc47261dccbb569f", "c2cb2bc0249fc7be8eb9b3bed7d37aa6f2c3f433abb3a4a00b13bed64b61f30b", "b3ec53b07a1be70ac8d0fa365b86f0d6d4cbf98641e7704b3d684558e2ea59ef", "4dc016d702d599bde5eaeb2bf0c2d0d3f6b9cede961bc539bcb369c3b3086358", }, { "e9794a6652940474958936f07f3904d514228553247633cfb7ae8ffa9fa0f406", "0e51cea6df2f6f56a9935689364f0d295a7c89f51d40efb2518c17d1b9db792b", "c132e7be08afdd93984c52c6e1c596edc6b8fc8f1faed95f55e2f819ee806706", "1a0e03c6858f6cf1b43f4b8456c03144af553bbbd050e152834fd1615b577cb3", "088f19c6727f8704373d391a36c230395d386f69edb4151ecf8afcd27793fff5", }, { "88920b0c96b15cc04e879f53a76f85f3c7a2a5f275b2772b5b74ee83372aea00", "e95731ab61a98fedcded475cf21b4ecf2ef9f1adecefba8fdc476a5bb1cf60f9", "c86026b66c1045fb69e4f24ff6c15d4fad4d565e646938a2ffb7db37ccb4100d", "d80cbf2986c12e4c7ebac1e55abbdfc4212c00aec8bc90c965becf863262a074", "047cebaeb3ec2132e7386ba52531b04070206ba1106565c0fbd7d7280694568a", }, }; bignum256modm a, b; ge25519 A, B, res, res_exp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(a, fromhex(tests[i].a), 32); expand256_modm(b, fromhex(tests[i].b), 32); ge25519_unpack_vartime(&A, fromhex(tests[i].A)); ge25519_unpack_vartime(&B, fromhex(tests[i].B)); ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); xmr_add_keys3(&res, a, &A, b, &B); ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); ck_assert_int_eq(ge25519_eq(&res, &B), 0); xmr_add_keys3_vartime(&res, a, &A, b, &B); ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); ck_assert_int_eq(ge25519_eq(&res, &B), 0); } } END_TEST START_TEST(test_xmr_get_subaddress_secret_key) { static const struct { uint32_t major, minor; char *m; char *r; } tests[] = { { 0, 0, "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", "8a510a9fe1824b49abbae05958084f9c9098775f29e15427309177882471cf01", }, { 0, 1, "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", "2bbc9366c04abb0523e2b2d6e709670ffe6645bacedfee968d9c6bc8eefe9c0f", }, { 100, 100, "36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207", "c3837d41fedeaed126cf4fc1a5ea47b8b7f38f6a64aa534e3dd45a3c93f37600", }, }; bignum256modm m, res, res_exp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(m, fromhex(tests[i].m), 32); expand256_modm(res_exp, fromhex(tests[i].r), 32); xmr_get_subaddress_secret_key(res, tests[i].major, tests[i].minor, m); ck_assert_int_eq(eq256_modm(res, res_exp), 1); ck_assert_int_eq(eq256_modm(res, m), 0); } } END_TEST START_TEST(test_xmr_gen_c) { static const struct { char *a; uint64_t amount; char *r; } tests[] = { { "e3e6558c291bbb98aa691d068b67d59dc520afb23fdd51bf65283626fc2ad903", 0, "ef19d73bdf3749240b80ee7695f53ad7c2fc2cf868a93209799f41212d099750", }, { "6788c9579c377f3228680bd0e6d01b1ee0c763b35ed39d36fa2146cc2ee16e0e", 1, "4913b9af4f2725d87a4404c22cf366597d1c1e6a1f510ae14081d8b7c5a9de77", }, { "ad9e89d67012935540427c241756d6a9d260c5e134603c41d31e24f8651bef08", 65537, "f005721da08f24e68314abed3ddfd94165e4be3813398fb126e3f366820b9c90", }, { "fdbb70ff07be24d98de3bffa0a33756646497224318fb7fe136f0e7789d12607", 0xffffffffffffffffULL, "a9c38927f299c5f14c98a1a9c9981e59c606ff597274b9b709e1356f12e1498c", }, }; bignum256modm a; ge25519 res, res_exp; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { expand256_modm(a, fromhex(tests[i].a), 32); ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r)); xmr_gen_c(&res, a, tests[i].amount); ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1); } } END_TEST START_TEST(test_xmr_varint) { static const struct { uint64_t x; char *r; } tests[] = { { 0, "00", }, { 24, "18", }, { 65535, "ffff03", }, { 65537, "818004", }, { 0x7fffffffULL, "ffffffff07", }, { 0xffffffffULL, "ffffffff0f", }, { 0xffffffffffffffffULL, "ffffffffffffffffff01", }, { 0xdeadc0deULL, "de81b7f50d", }, }; uint64_t val; unsigned char buff[64]; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { int s1 = xmr_size_varint(tests[i].x); int written = 0; int read = 0; ck_assert_int_eq(s1, strlen(tests[i].r)/2); written = xmr_write_varint(buff, sizeof(buff), tests[i].x); ck_assert_int_eq(s1, written); ck_assert_mem_eq(buff, fromhex(tests[i].r), strlen(tests[i].r)/2); read = xmr_read_varint(buff, sizeof(buff), &val); ck_assert_int_eq(read, written); ck_assert(tests[i].x == val); } } END_TEST START_TEST(test_xmr_gen_range_sig) { uint64_t tests[] = { 0, 1, 65535, 65537, 0xffffffffffffffffULL, 0xdeadc0deULL, }; unsigned char buff[32]; xmr_range_sig_t sig; ge25519 C, Ctmp, Cb, Ch, P1, P2, LL; bignum256modm mask, hsh, ee, s, ee_comp; Hasher hasher; for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { xmr_gen_range_sig(&sig, &C, mask, tests[i], NULL); ge25519_set_neutral(&Ctmp); for(int j = 0; j < XMR_ATOMS; j++){ ge25519_unpack_vartime(&Cb, sig.Ci[j]); ge25519_add(&Ctmp, &Ctmp, &Cb, 0); } ck_assert_int_eq(ge25519_eq(&C, &Ctmp), 1); xmr_hasher_init(&hasher); ge25519_set_xmr_h(&Ch); expand256_modm(ee, sig.asig.ee, 32); for(int j = 0; j < XMR_ATOMS; j++){ ge25519_unpack_vartime(&P1, sig.Ci[j]); ge25519_add(&P2, &P1, &Ch, 1); expand256_modm(s, sig.asig.s0[j], 32); xmr_add_keys2(&LL, s, ee, &P1); ge25519_pack(buff, &LL); xmr_hash_to_scalar(hsh, buff, 32); expand256_modm(s, sig.asig.s1[j], 32); xmr_add_keys2(&LL, s, hsh, &P2); ge25519_pack(buff, &LL); xmr_hasher_update(&hasher, buff, 32); ge25519_double(&Ch, &Ch); } xmr_hasher_final(&hasher, buff); expand256_modm(ee_comp, buff, 32); ck_assert_int_eq(eq256_modm(ee, ee_comp), 1); } } END_TEST #endif