key.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. // ECOin - Copyright (c) - 2014/2024 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #include <map>
  3. #include <openssl/ecdsa.h>
  4. #include <openssl/obj_mac.h>
  5. #include "key.h"
  6. // Generate a private key from just the secret parameter
  7. int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
  8. {
  9. int ok = 0;
  10. BN_CTX *ctx = NULL;
  11. EC_POINT *pub_key = NULL;
  12. if (!eckey) return 0;
  13. const EC_GROUP *group = EC_KEY_get0_group(eckey);
  14. if ((ctx = BN_CTX_new()) == NULL)
  15. goto err;
  16. pub_key = EC_POINT_new(group);
  17. if (pub_key == NULL)
  18. goto err;
  19. if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
  20. goto err;
  21. EC_KEY_set_private_key(eckey,priv_key);
  22. EC_KEY_set_public_key(eckey,pub_key);
  23. ok = 1;
  24. err:
  25. if (pub_key)
  26. EC_POINT_free(pub_key);
  27. if (ctx != NULL)
  28. BN_CTX_free(ctx);
  29. return(ok);
  30. }
  31. // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
  32. // recid selects which key is recovered
  33. // if check is non-zero, additional checks are performed
  34. int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
  35. {
  36. if (!eckey) return 0;
  37. int ret = 0;
  38. BN_CTX *ctx = NULL;
  39. BIGNUM *x = NULL;
  40. BIGNUM *e = NULL;
  41. BIGNUM *order = NULL;
  42. BIGNUM *sor = NULL;
  43. BIGNUM *eor = NULL;
  44. BIGNUM *field = NULL;
  45. EC_POINT *R = NULL;
  46. EC_POINT *O = NULL;
  47. EC_POINT *Q = NULL;
  48. BIGNUM *rr = NULL;
  49. BIGNUM *zero = NULL;
  50. BIGNUM *s = 0;
  51. int n = 0;
  52. int i = recid / 2;
  53. const EC_GROUP *group = EC_KEY_get0_group(eckey);
  54. if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
  55. BN_CTX_start(ctx);
  56. order = BN_CTX_get(ctx);
  57. if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
  58. x = BN_CTX_get(ctx);
  59. if (!BN_copy(x, order)) { ret=-1; goto err; }
  60. if (!BN_mul_word(x, i)) { ret=-1; goto err; }
  61. ECDSA_SIG_get0(ecsig, (const BIGNUM **)&s, 0);
  62. if (!BN_add(x, x, s)) { ret=-1; goto err; }
  63. field = BN_CTX_get(ctx);
  64. if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
  65. if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
  66. if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
  67. if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
  68. if (check)
  69. {
  70. if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
  71. if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
  72. if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
  73. }
  74. if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
  75. n = EC_GROUP_get_degree(group);
  76. e = BN_CTX_get(ctx);
  77. if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
  78. if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
  79. zero = BN_CTX_get(ctx);
  80. BN_zero(zero); // Set the value of 'zero' to zero
  81. if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
  82. rr = BN_CTX_get(ctx);
  83. ECDSA_SIG_get0(ecsig, (const BIGNUM **)&s, 0);
  84. if (!BN_mod_inverse(rr, s, order, ctx)) { ret=-1; goto err; }
  85. sor = BN_CTX_get(ctx);
  86. ECDSA_SIG_get0(ecsig, 0, (const BIGNUM **)&s);
  87. if (!BN_mod_mul(sor, s, rr, order, ctx)) { ret=-1; goto err; }
  88. eor = BN_CTX_get(ctx);
  89. if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
  90. if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
  91. if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
  92. ret = 1;
  93. err:
  94. if (ctx) {
  95. BN_CTX_end(ctx);
  96. BN_CTX_free(ctx);
  97. }
  98. if (R != NULL) EC_POINT_free(R);
  99. if (O != NULL) EC_POINT_free(O);
  100. if (Q != NULL) EC_POINT_free(Q);
  101. return ret;
  102. }
  103. void CKey::SetCompressedPubKey()
  104. {
  105. EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
  106. fCompressedPubKey = true;
  107. }
  108. void CKey::Reset()
  109. {
  110. fCompressedPubKey = false;
  111. if (pkey != NULL)
  112. EC_KEY_free(pkey);
  113. pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
  114. if (pkey == NULL)
  115. throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
  116. fSet = false;
  117. }
  118. CKey::CKey()
  119. {
  120. pkey = NULL;
  121. Reset();
  122. }
  123. CKey::CKey(const CKey& b)
  124. {
  125. pkey = EC_KEY_dup(b.pkey);
  126. if (pkey == NULL)
  127. throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
  128. fSet = b.fSet;
  129. }
  130. CKey& CKey::operator=(const CKey& b)
  131. {
  132. if (!EC_KEY_copy(pkey, b.pkey))
  133. throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
  134. fSet = b.fSet;
  135. return (*this);
  136. }
  137. CKey::~CKey()
  138. {
  139. EC_KEY_free(pkey);
  140. }
  141. bool CKey::IsNull() const
  142. {
  143. return !fSet;
  144. }
  145. bool CKey::IsCompressed() const
  146. {
  147. return fCompressedPubKey;
  148. }
  149. void CKey::MakeNewKey(bool fCompressed)
  150. {
  151. if (!EC_KEY_generate_key(pkey))
  152. throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
  153. if (fCompressed)
  154. SetCompressedPubKey();
  155. fSet = true;
  156. }
  157. bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
  158. {
  159. const unsigned char* pbegin = &vchPrivKey[0];
  160. if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
  161. {
  162. // In testing, d2i_ECPrivateKey can return true
  163. // but fill in pkey with a key that fails
  164. // EC_KEY_check_key, so:
  165. if (EC_KEY_check_key(pkey))
  166. {
  167. fSet = true;
  168. return true;
  169. }
  170. }
  171. // If vchPrivKey data is bad d2i_ECPrivateKey() can
  172. // leave pkey in a state where calling EC_KEY_free()
  173. // crashes. To avoid that, set pkey to NULL and
  174. // leak the memory (a leak is better than a crash)
  175. pkey = NULL;
  176. Reset();
  177. return false;
  178. }
  179. bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
  180. {
  181. EC_KEY_free(pkey);
  182. pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
  183. if (pkey == NULL)
  184. throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
  185. if (vchSecret.size() != 32)
  186. throw key_error("CKey::SetSecret() : secret must be 32 bytes");
  187. BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
  188. if (bn == NULL)
  189. throw key_error("CKey::SetSecret() : BN_bin2bn failed");
  190. if (!EC_KEY_regenerate_key(pkey,bn))
  191. {
  192. BN_clear_free(bn);
  193. throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
  194. }
  195. BN_clear_free(bn);
  196. fSet = true;
  197. if (fCompressed || fCompressedPubKey)
  198. SetCompressedPubKey();
  199. return true;
  200. }
  201. CSecret CKey::GetSecret(bool &fCompressed) const
  202. {
  203. CSecret vchRet;
  204. vchRet.resize(32);
  205. const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
  206. int nBytes = BN_num_bytes(bn);
  207. if (bn == NULL)
  208. throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
  209. int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
  210. if (n != nBytes)
  211. throw key_error("CKey::GetSecret(): BN_bn2bin failed");
  212. fCompressed = fCompressedPubKey;
  213. return vchRet;
  214. }
  215. CPrivKey CKey::GetPrivKey() const
  216. {
  217. int nSize = i2d_ECPrivateKey(pkey, NULL);
  218. if (!nSize)
  219. throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
  220. CPrivKey vchPrivKey(nSize, 0);
  221. unsigned char* pbegin = &vchPrivKey[0];
  222. if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
  223. throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
  224. return vchPrivKey;
  225. }
  226. bool CKey::SetPubKey(const CPubKey& vchPubKey)
  227. {
  228. const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
  229. if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
  230. {
  231. fSet = true;
  232. if (vchPubKey.vchPubKey.size() == 33)
  233. SetCompressedPubKey();
  234. return true;
  235. }
  236. pkey = NULL;
  237. Reset();
  238. return false;
  239. }
  240. CPubKey CKey::GetPubKey() const
  241. {
  242. int nSize = i2o_ECPublicKey(pkey, NULL);
  243. if (!nSize)
  244. throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
  245. std::vector<unsigned char> vchPubKey(nSize, 0);
  246. unsigned char* pbegin = &vchPubKey[0];
  247. if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
  248. throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
  249. return CPubKey(vchPubKey);
  250. }
  251. bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
  252. {
  253. unsigned int nSize = ECDSA_size(pkey);
  254. vchSig.resize(nSize); // Make sure it is big enough
  255. if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
  256. {
  257. vchSig.clear();
  258. return false;
  259. }
  260. vchSig.resize(nSize); // Shrink to fit actual size
  261. return true;
  262. }
  263. // create a compact signature (65 bytes), which allows reconstructing the used public key
  264. // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
  265. // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
  266. // 0x1D = second key with even y, 0x1E = second key with odd y
  267. bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
  268. {
  269. bool fOk = false;
  270. BIGNUM *s = 0;
  271. BIGNUM *r = 0;
  272. ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
  273. if (sig==NULL)
  274. return false;
  275. vchSig.clear();
  276. vchSig.resize(65,0);
  277. ECDSA_SIG_get0(sig, (const BIGNUM **)&r, (const BIGNUM **)&s);
  278. int nBitsR = BN_num_bits(r);
  279. int nBitsS = BN_num_bits(s);
  280. if (nBitsR <= 256 && nBitsS <= 256)
  281. {
  282. int nRecId = -1;
  283. for (int i=0; i<4; i++)
  284. {
  285. CKey keyRec;
  286. keyRec.fSet = true;
  287. if (fCompressedPubKey)
  288. keyRec.SetCompressedPubKey();
  289. if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
  290. if (keyRec.GetPubKey() == this->GetPubKey())
  291. {
  292. nRecId = i;
  293. break;
  294. }
  295. }
  296. if (nRecId == -1)
  297. throw key_error("CKey::SignCompact() : unable to construct recoverable key");
  298. vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
  299. ECDSA_SIG_get0(sig, (const BIGNUM **)&r, (const BIGNUM **)&s);
  300. BN_bn2bin(r,&vchSig[33-(nBitsR+7)/8]);
  301. BN_bn2bin(s,&vchSig[65-(nBitsS+7)/8]);
  302. fOk = true;
  303. }
  304. ECDSA_SIG_free(sig);
  305. return fOk;
  306. }
  307. // reconstruct public key from a compact signature
  308. // This is only slightly more CPU intensive than just verifying it.
  309. // If this function succeeds, the recovered public key is guaranteed to be valid
  310. // (the signature is a valid signature of the given data for that key)
  311. bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
  312. {
  313. BIGNUM *s = 0;
  314. BIGNUM *r = 0;
  315. if (vchSig.size() != 65)
  316. return false;
  317. int nV = vchSig[0];
  318. if (nV<27 || nV>=35)
  319. return false;
  320. ECDSA_SIG *sig = ECDSA_SIG_new();
  321. ECDSA_SIG_get0(sig, (const BIGNUM **)&r, (const BIGNUM **)&s);
  322. BN_bin2bn(&vchSig[1],32,r);
  323. BN_bin2bn(&vchSig[33],32,s);
  324. EC_KEY_free(pkey);
  325. pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
  326. if (nV >= 31)
  327. {
  328. SetCompressedPubKey();
  329. nV -= 4;
  330. }
  331. if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
  332. {
  333. fSet = true;
  334. ECDSA_SIG_free(sig);
  335. return true;
  336. }
  337. return false;
  338. }
  339. bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
  340. {
  341. // -1 = error, 0 = bad sig, 1 = good
  342. if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
  343. return false;
  344. return true;
  345. }
  346. bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
  347. {
  348. CKey key;
  349. if (!key.SetCompactSignature(hash, vchSig))
  350. return false;
  351. if (GetPubKey() != key.GetPubKey())
  352. return false;
  353. return true;
  354. }
  355. bool CKey::IsValid()
  356. {
  357. if (!fSet)
  358. return false;
  359. if (!EC_KEY_check_key(pkey))
  360. return false;
  361. bool fCompr;
  362. CSecret secret = GetSecret(fCompr);
  363. CKey key2;
  364. key2.SetSecret(secret, fCompr);
  365. return GetPubKey() == key2.GetPubKey();
  366. }
  367. #if OPENSSL_VERSION_NUMBER < 0x10100000L
  368. void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
  369. {
  370. if (pr != NULL)
  371. *pr = sig->r;
  372. if (ps != NULL)
  373. *ps = sig->s;
  374. }
  375. #endif