shared.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #pragma once
  2. #include <array>
  3. #include <cassert>
  4. #include <iostream>
  5. #include <openssl/sha.h>
  6. #include <sstream>
  7. #include <vector>
  8. #include "../native/secp256k1/include/secp256k1.h"
  9. #include "hexxer.hpp"
  10. #include "json.hpp"
  11. typedef std::array<uint8_t, 32> uint8_t_32;
  12. typedef std::array<uint8_t, 33> uint8_t_33;
  13. typedef std::array<uint8_t, 64> uint8_t_64;
  14. typedef std::array<uint8_t, 65> uint8_t_65;
  15. typedef std::vector<uint8_t> uint8_t_vec;
  16. template <typename A>
  17. auto vectorify (const A a) {
  18. return uint8_t_vec(a.begin(), a.end());
  19. }
  20. namespace {
  21. uint32_t s = 0xdeadbeef;
  22. uint32_t xorshift32() {
  23. s ^= s << 13;
  24. s ^= s >> 17;
  25. s ^= s << 5;
  26. return s;
  27. }
  28. }
  29. auto randomUInt8 () {
  30. return xorshift32() % 255;
  31. }
  32. template <typename A>
  33. auto random () {
  34. A a;
  35. for (auto& x : a) x = randomUInt8();
  36. return a;
  37. }
  38. template <typename A>
  39. auto randomHigh () {
  40. auto x = random<A>();
  41. for (auto i = x.size() / 2; i < x.size(); ++i) {
  42. x.at(i) = 0xff;
  43. }
  44. return x;
  45. }
  46. template <typename A>
  47. auto randomLow () {
  48. auto x = random<A>();
  49. for (auto i = 0ul; i < x.size() / 2; ++i) {
  50. x.at(i) = 0;
  51. }
  52. return x;
  53. }
  54. template <typename A>
  55. auto fromUInt32 (const uint32_t i) {
  56. A x;
  57. x.fill(0);
  58. const auto s = x.size();
  59. x.at(s - 4) = i >> 24;
  60. x.at(s - 3) = i >> 16;
  61. x.at(s - 2) = i >> 8;
  62. x.at(s - 1) = i & 0xff;
  63. return x;
  64. }
  65. auto randomScalar () { return random<uint8_t_32>(); }
  66. auto randomScalarHigh () { return randomHigh<uint8_t_32>(); }
  67. auto randomScalarLow () { return randomLow<uint8_t_32>(); }
  68. auto scalarFromUInt32 (const uint32_t i) { return fromUInt32<uint8_t_32>(i); }
  69. template <typename A>
  70. auto fromHex (const std::string& s) {
  71. assert(s.size() == sizeof(A) * 2);
  72. A x;
  73. auto i = 0;
  74. for (auto& y : x) {
  75. const auto a = s.at(i++);
  76. const auto b = s.at(i++);
  77. y = hexxer::decode(a, b);
  78. }
  79. return x;
  80. }
  81. auto pointFromHex (const std::string& s) {
  82. if (s.size() == 66) return vectorify(fromHex<uint8_t_33>(s));
  83. if (s.size() == 130) return vectorify(fromHex<uint8_t_65>(s));
  84. assert(false);
  85. }
  86. auto scalarFromHex (const std::string& s) { return fromHex<uint8_t_32>(s); }
  87. auto signatureFromHex (const std::string& s) { return fromHex<uint8_t_64>(s); }
  88. secp256k1_context* ctx = nullptr;
  89. auto randomPrivate () {
  90. while (true) {
  91. const auto key = randomScalar();
  92. if (secp256k1_ec_seckey_verify(ctx, key.data())) return key;
  93. }
  94. }
  95. auto randomPrivateHigh () {
  96. while (true) {
  97. const auto key = randomScalarHigh();
  98. if (secp256k1_ec_seckey_verify(ctx, key.data())) return key;
  99. }
  100. }
  101. auto randomPrivateLow () {
  102. while (true) {
  103. const auto key = randomScalarLow();
  104. if (secp256k1_ec_seckey_verify(ctx, key.data())) return key;
  105. }
  106. }
  107. // utility functions
  108. void _ec_init () {
  109. ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
  110. }
  111. auto _privAdd (uint8_t_32 key, const uint8_t_32 tweak, bool& ok) {
  112. ok &= secp256k1_ec_privkey_tweak_add(ctx, key.data(), tweak.data());
  113. return key;
  114. }
  115. auto _privSub (uint8_t_32 key, uint8_t_32 tweak, bool& ok) {
  116. ok &= secp256k1_ec_privkey_negate(ctx, tweak.data());
  117. ok &= secp256k1_ec_privkey_tweak_add(ctx, key.data(), tweak.data());
  118. return key;
  119. }
  120. template <typename A>
  121. uint8_t_vec _ec_pubkey_to_vec (const secp256k1_pubkey& public_key, bool& ok) {
  122. static_assert(sizeof(A) == 33 || sizeof(A) == 65);
  123. if (!ok) return {};
  124. A out;
  125. size_t outlen = out.size();
  126. ok &= secp256k1_ec_pubkey_serialize(ctx, out.data(), &outlen, &public_key,
  127. sizeof(A) == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
  128. return vectorify<A>(out);
  129. }
  130. template <typename A, typename V>
  131. auto _pointAdd (const V p, const V q, bool& ok) {
  132. secp256k1_pubkey a, b;
  133. ok &= secp256k1_ec_pubkey_parse(ctx, &a, p.data(), p.size());
  134. ok &= secp256k1_ec_pubkey_parse(ctx, &b, q.data(), q.size());
  135. const secp256k1_pubkey* points[] = { &a, &b };
  136. secp256k1_pubkey public_key;
  137. ok &= secp256k1_ec_pubkey_combine(ctx, &public_key, points, 2);
  138. return _ec_pubkey_to_vec<A>(public_key, ok);
  139. }
  140. template <typename A, typename V>
  141. auto _pointMul (const V p, const uint8_t_32 d, bool& ok) {
  142. secp256k1_pubkey public_key;
  143. ok &= secp256k1_ec_pubkey_parse(ctx, &public_key, p.data(), p.size());
  144. ok &= secp256k1_ec_pubkey_tweak_mul(ctx, &public_key, d.data());
  145. return _ec_pubkey_to_vec<A>(public_key, ok);
  146. }
  147. template <typename A, typename V>
  148. auto _pointAddScalar (const V p, const uint8_t_32 d, bool& ok) {
  149. secp256k1_pubkey public_key;
  150. ok &= secp256k1_ec_pubkey_parse(ctx, &public_key, p.data(), p.size());
  151. ok &= secp256k1_ec_pubkey_tweak_add(ctx, &public_key, d.data());
  152. return _ec_pubkey_to_vec<A>(public_key, ok);
  153. }
  154. uint8_t_vec _pointFlip (const uint8_t_vec& p) {
  155. assert(!p.empty());
  156. secp256k1_pubkey public_key;
  157. bool ok = secp256k1_ec_pubkey_parse(ctx, &public_key, p.data(), p.size());
  158. assert(ok);
  159. uint8_t_vec r;
  160. if (p.size() == 33) r = _ec_pubkey_to_vec<uint8_t_65>(public_key, ok);
  161. else r = _ec_pubkey_to_vec<uint8_t_33>(public_key, ok);
  162. assert(ok);
  163. return std::move(r);
  164. }
  165. template <typename A>
  166. auto _pointFromScalar (const uint8_t_32 s, bool& ok) {
  167. secp256k1_pubkey public_key;
  168. ok &= secp256k1_ec_pubkey_create(ctx, &public_key, s.data());
  169. return _ec_pubkey_to_vec<A>(public_key, ok);
  170. }
  171. template <typename A>
  172. auto _pointFromUInt32 (const uint32_t i, bool& ok) {
  173. return _pointFromScalar<A>(scalarFromUInt32(i), ok);
  174. }
  175. auto _pointFromX (const uint8_t_32 x, uint8_t prefix) {
  176. uint8_t_vec p = { prefix };
  177. p.reserve(33);
  178. for (auto i : x) p.emplace_back(i);
  179. return p;
  180. }
  181. auto _pointFromXY (const uint8_t_32 x, const uint8_t_32 y, const uint8_t prefix = 0x04) {
  182. uint8_t_vec p = { prefix };
  183. p.reserve(65);
  184. for (auto i : x) p.emplace_back(i);
  185. for (auto i : y) p.emplace_back(i);
  186. return p;
  187. }
  188. auto _signatureFromRS (const uint8_t_32 r, const uint8_t_32 s) {
  189. uint8_t_64 sig;
  190. std::copy(r.begin(), r.end(), sig.begin());
  191. std::copy(s.begin(), s.end(), sig.begin() + 32);
  192. return sig;
  193. }
  194. auto _eccSign (const uint8_t_32 d, const uint8_t_32 message, bool& ok) {
  195. uint8_t_64 output;
  196. secp256k1_ecdsa_signature signature;
  197. ok &= secp256k1_ecdsa_sign(ctx, &signature, message.data(), d.data(), nullptr, nullptr);
  198. ok &= secp256k1_ecdsa_signature_serialize_compact(ctx, output.data(), &signature);
  199. return output;
  200. }
  201. template <typename A>
  202. auto _eccVerify (const A& p, const uint8_t_32 message, const uint8_t_64 signature) {
  203. secp256k1_pubkey public_key;
  204. bool ok = true;
  205. ok &= secp256k1_ec_pubkey_parse(ctx, &public_key, p.data(), p.size());
  206. if (!ok) return false;
  207. secp256k1_ecdsa_signature _signature;
  208. ok &= secp256k1_ecdsa_signature_parse_compact(ctx, &_signature, signature.data());
  209. if (!ok) return false;
  210. ok &= secp256k1_ecdsa_verify(ctx, &_signature, message.data(), &public_key);
  211. return ok;
  212. }
  213. template <typename A>
  214. auto sha256 (const A& m) {
  215. uint8_t_32 h;
  216. SHA256_CTX hctx;
  217. SHA256_Init(&hctx);
  218. SHA256_Update(&hctx, m.data(), m.size());
  219. SHA256_Final(h.data(), &hctx);
  220. return h;
  221. }
  222. // we use 0xfefefefefefefe.... as a null placeholder
  223. template <typename A>
  224. auto Null () {
  225. A a;
  226. a.fill(0xfe);
  227. return a;
  228. }
  229. template <typename A>
  230. auto isNull (const A& a) {
  231. for (auto x : a) if (x != 0xfe) return false;
  232. return true;
  233. }
  234. const auto ZERO = scalarFromHex("0000000000000000000000000000000000000000000000000000000000000000");
  235. const auto ONE = scalarFromHex("0000000000000000000000000000000000000000000000000000000000000001");
  236. const auto TWO = scalarFromHex("0000000000000000000000000000000000000000000000000000000000000002");
  237. const auto THREE = scalarFromHex("0000000000000000000000000000000000000000000000000000000000000003");
  238. const auto FOUR = scalarFromHex("0000000000000000000000000000000000000000000000000000000000000004");
  239. const auto GROUP_ORDER = scalarFromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
  240. const auto GROUP_ORDER_LESS_3 = scalarFromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e");
  241. const auto GROUP_ORDER_LESS_2 = scalarFromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f");
  242. const auto GROUP_ORDER_LESS_1 = scalarFromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140");
  243. const auto GROUP_ORDER_OVER_1 = scalarFromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142");
  244. const auto UINT256_MAX = scalarFromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  245. const auto G = pointFromHex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798");
  246. const auto GU = pointFromHex("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
  247. const auto P_LESS_1 = scalarFromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2e");
  248. const auto P_LESS_2 = scalarFromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2d");
  249. const auto P = scalarFromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f");
  250. const auto P_OVER_1 = scalarFromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30");
  251. template <typename A> struct B { A a; std::string desc = ""; };
  252. const std::vector<B<uint8_t_32>> BAD_PRIVATES = {
  253. { ZERO, "Private key == 0" }, // #L3145, #L3684, fail, == 0
  254. { GROUP_ORDER, "Private key >= G" }, // #L3115, #L3670, fail, == G
  255. { GROUP_ORDER_OVER_1, "Private key >= G" }, // #L3162, #L3701, fail, >= G
  256. { UINT256_MAX, "Private key >= G" } // #L3131, #L3676, fail, > G
  257. };
  258. // excludes exact complement of a key, assumed to be tested elsewhere
  259. const std::vector<B<uint8_t_32>> BAD_TWEAKS = {
  260. { GROUP_ORDER, "Tweak >= G" },
  261. { GROUP_ORDER_OVER_1, "Tweak >= G" },
  262. { UINT256_MAX, "Tweak >= G" }
  263. };
  264. const std::vector<B<uint8_t_64>> BAD_SIGNATURES_VERIFY = {
  265. { _signatureFromRS(ZERO, ZERO), "Invalid r, s values (== 0)" },
  266. { _signatureFromRS(ZERO, ONE), "Invalid r value (== 0)" },
  267. { _signatureFromRS(ONE, ZERO), "Invalid s value (== 0)" },
  268. };
  269. const std::vector<B<uint8_t_64>> BAD_SIGNATURES = {
  270. { _signatureFromRS(GROUP_ORDER, ONE), "Invalid r value (>= n)" },
  271. { _signatureFromRS(ONE, GROUP_ORDER), "Invalid s value (>= n)" }
  272. };
  273. // from https://github.com/cryptocoinjs/ecurve/blob/14d72f5f468d53ff33dc13c1c7af350a41d52aab/test/fixtures/point.json#L84
  274. template <typename A = uint8_t_33>
  275. std::vector<B<uint8_t_vec>> generateBadPoints () {
  276. return {
  277. { _pointFromX(ONE, 0x01), "Bad sequence prefix" },
  278. { _pointFromX(ONE, 0x04), "Bad sequence prefix" },
  279. { _pointFromX(ONE, 0x05), "Bad sequence prefix" },
  280. { _pointFromX(ZERO, 0x02), "Bad X coordinate (== 0)" },
  281. { _pointFromX(ZERO, 0x03), "Bad X coordinate (== 0)" },
  282. { _pointFromX(P, 0x02), "Bad X coordinate (== P)" },
  283. { _pointFromX(P, 0x03), "Bad X coordinate (== P)" },
  284. { _pointFromX(P_LESS_2, 0x02), "Bad X coordinate (P - 2)" },
  285. { _pointFromX(P_LESS_2, 0x03), "Bad X coordinate (P - 2)" },
  286. { _pointFromX(P_OVER_1, 0x03), "Bad X coordinate (> P)" },
  287. };
  288. }
  289. template <>
  290. std::vector<B<uint8_t_vec>> generateBadPoints<uint8_t_65> () {
  291. return {
  292. { _pointFromXY(ONE, ONE, 0x01), "Bad sequence prefix" },
  293. { _pointFromXY(ONE, ONE, 0x02), "Bad sequence prefix" },
  294. { _pointFromXY(ONE, ONE, 0x03), "Bad sequence prefix" },
  295. { _pointFromXY(ONE, ONE, 0x05), "Bad sequence prefix" },
  296. { _pointFromXY(ZERO, ONE), "Bad X coordinate (== 0)" },
  297. { _pointFromXY(ONE, ZERO), "Bad Y coordinate (== 0)" },
  298. { _pointFromXY(ZERO, ZERO, 0x04), "Bad X/Y coordinate (== 0)" },
  299. { _pointFromXY(P, ONE), "Bad X coordinate (== P)" },
  300. { _pointFromXY(ONE, P), "Bad Y coordinate (== P)" },
  301. { _pointFromXY(P_OVER_1, ONE), "Bad X coordinate (> P)" },
  302. { _pointFromXY(ONE, P_OVER_1), "Bad Y coordinate (> P)" },
  303. };
  304. }
  305. const auto THROW_BAD_PRIVATE = "Expected Private";
  306. const auto THROW_BAD_POINT = "Expected Point";
  307. const auto THROW_BAD_TWEAK = "Expected Tweak";
  308. const auto THROW_BAD_HASH = "Expected Hash";
  309. const auto THROW_BAD_SIGNATURE = "Expected Signature";