CryptoPP.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file CryptoPP.cpp
  15. * @author Alex Leverington <nessence@gmail.com>
  16. * @date 2014
  17. */
  18. #include <libdevcore/Guards.h>
  19. #include <libdevcore/Assertions.h>
  20. #include "ECDHE.h"
  21. // At 5.6.3 the ECIES implementation has been deprecated and a warning has
  22. // been added. A new implementation will be added in 6.0. Until then and for
  23. // -Werror to not fail the build we have to have this warning ignore pragma here
  24. // and until the end of the file.
  25. //
  26. // Refer here for more information:
  27. // https://www.cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme#5.6.3_and_6.0_Changes
  28. //
  29. // There is also a warning which needs suppressing for Debian builds to work,
  30. // presumably because to older GCC version (4.9.2) in Debian Jesse compared to
  31. // other distros.
  32. //
  33. // /home/ricardo/cpp-ethereum/cryptopp/misc.h:1074:20:
  34. // error: ‘std::string CryptoPP::StringNarrow(const wchar_t*, bool)’ defined but not used [-Werror=unused-function]
  35. // static std::string StringNarrow(const wchar_t *str, bool throwOnError = true)
  36. #if defined(__GNUC__)
  37. #pragma GCC diagnostic push
  38. // Do not warn about uses of functions, variables, and types marked as deprecated by using the deprecated attribute
  39. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  40. #endif // defined(__GNUC__)
  41. #include "CryptoPP.h"
  42. using namespace std;
  43. using namespace dev;
  44. using namespace dev::crypto;
  45. using namespace CryptoPP;
  46. static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
  47. static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
  48. static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
  49. Secp256k1PP* Secp256k1PP::s_this = nullptr;
  50. bytes Secp256k1PP::eciesKDF(Secret const& _z, bytes _s1, unsigned kdByteLen)
  51. {
  52. auto reps = ((kdByteLen + 7) * 8) / (CryptoPP::SHA256::BLOCKSIZE * 8);
  53. // SEC/ISO/Shoup specify counter size SHOULD be equivalent
  54. // to size of hash output, however, it also notes that
  55. // the 4 bytes is okay. NIST specifies 4 bytes.
  56. bytes ctr({0, 0, 0, 1});
  57. bytes k;
  58. CryptoPP::SHA256 ctx;
  59. for (unsigned i = 0; i <= reps; i++)
  60. {
  61. ctx.Update(ctr.data(), ctr.size());
  62. ctx.Update(_z.data(), Secret::size);
  63. ctx.Update(_s1.data(), _s1.size());
  64. // append hash to k
  65. bytes digest(32);
  66. ctx.Final(digest.data());
  67. ctx.Restart();
  68. k.reserve(k.size() + h256::size);
  69. move(digest.begin(), digest.end(), back_inserter(k));
  70. if (++ctr[3] || ++ctr[2] || ++ctr[1] || ++ctr[0])
  71. continue;
  72. }
  73. k.resize(kdByteLen);
  74. return k;
  75. }
  76. void Secp256k1PP::encryptECIES(Public const& _k, bytes& io_cipher)
  77. {
  78. encryptECIES(_k, bytesConstRef(), io_cipher);
  79. }
  80. void Secp256k1PP::encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytes& io_cipher)
  81. {
  82. // interop w/go ecies implementation
  83. auto r = KeyPair::create();
  84. Secret z;
  85. ecdh::agree(r.sec(), _k, z);
  86. auto key = eciesKDF(z, bytes(), 32);
  87. bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16);
  88. bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16);
  89. CryptoPP::SHA256 ctx;
  90. ctx.Update(mKeyMaterial.data(), mKeyMaterial.size());
  91. bytes mKey(32);
  92. ctx.Final(mKey.data());
  93. auto iv = h128::random();
  94. bytes cipherText = encryptSymNoAuth(SecureFixedHash<16>(eKey), iv, bytesConstRef(&io_cipher));
  95. if (cipherText.empty())
  96. return;
  97. bytes msg(1 + Public::size + h128::size + cipherText.size() + 32);
  98. msg[0] = 0x04;
  99. r.pub().ref().copyTo(bytesRef(&msg).cropped(1, Public::size));
  100. iv.ref().copyTo(bytesRef(&msg).cropped(1 + Public::size, h128::size));
  101. bytesRef msgCipherRef = bytesRef(&msg).cropped(1 + Public::size + h128::size, cipherText.size());
  102. bytesConstRef(&cipherText).copyTo(msgCipherRef);
  103. // tag message
  104. CryptoPP::HMAC<SHA256> hmacctx(mKey.data(), mKey.size());
  105. bytesConstRef cipherWithIV = bytesRef(&msg).cropped(1 + Public::size, h128::size + cipherText.size());
  106. hmacctx.Update(cipherWithIV.data(), cipherWithIV.size());
  107. hmacctx.Update(_sharedMacData.data(), _sharedMacData.size());
  108. hmacctx.Final(msg.data() + 1 + Public::size + cipherWithIV.size());
  109. io_cipher.resize(msg.size());
  110. io_cipher.swap(msg);
  111. }
  112. bool Secp256k1PP::decryptECIES(Secret const& _k, bytes& io_text)
  113. {
  114. return decryptECIES(_k, bytesConstRef(), io_text);
  115. }
  116. bool Secp256k1PP::decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytes& io_text)
  117. {
  118. // interop w/go ecies implementation
  119. // io_cipher[0] must be 2, 3, or 4, else invalidpublickey
  120. if (io_text.empty() || io_text[0] < 2 || io_text[0] > 4)
  121. // invalid message: publickey
  122. return false;
  123. if (io_text.size() < (1 + Public::size + h128::size + 1 + h256::size))
  124. // invalid message: length
  125. return false;
  126. Secret z;
  127. ecdh::agree(_k, *(Public*)(io_text.data() + 1), z);
  128. auto key = eciesKDF(z, bytes(), 64);
  129. bytesConstRef eKey = bytesConstRef(&key).cropped(0, 16);
  130. bytesRef mKeyMaterial = bytesRef(&key).cropped(16, 16);
  131. bytes mKey(32);
  132. CryptoPP::SHA256 ctx;
  133. ctx.Update(mKeyMaterial.data(), mKeyMaterial.size());
  134. ctx.Final(mKey.data());
  135. bytes plain;
  136. size_t cipherLen = io_text.size() - 1 - Public::size - h128::size - h256::size;
  137. bytesConstRef cipherWithIV(io_text.data() + 1 + Public::size, h128::size + cipherLen);
  138. bytesConstRef cipherIV = cipherWithIV.cropped(0, h128::size);
  139. bytesConstRef cipherNoIV = cipherWithIV.cropped(h128::size, cipherLen);
  140. bytesConstRef msgMac(cipherNoIV.data() + cipherLen, h256::size);
  141. h128 iv(cipherIV.toBytes());
  142. // verify tag
  143. CryptoPP::HMAC<SHA256> hmacctx(mKey.data(), mKey.size());
  144. hmacctx.Update(cipherWithIV.data(), cipherWithIV.size());
  145. hmacctx.Update(_sharedMacData.data(), _sharedMacData.size());
  146. h256 mac;
  147. hmacctx.Final(mac.data());
  148. for (unsigned i = 0; i < h256::size; i++)
  149. if (mac[i] != msgMac[i])
  150. return false;
  151. plain = decryptSymNoAuth(SecureFixedHash<16>(eKey), iv, cipherNoIV).makeInsecure();
  152. io_text.resize(plain.size());
  153. io_text.swap(plain);
  154. return true;
  155. }
  156. void Secp256k1PP::encrypt(Public const& _k, bytes& io_cipher)
  157. {
  158. ECIES<ECP>::Encryptor e;
  159. initializeDLScheme(_k, e);
  160. size_t plen = io_cipher.size();
  161. bytes ciphertext;
  162. ciphertext.resize(e.CiphertextLength(plen));
  163. {
  164. Guard l(x_rng);
  165. e.Encrypt(m_rng, io_cipher.data(), plen, ciphertext.data());
  166. }
  167. memset(io_cipher.data(), 0, io_cipher.size());
  168. io_cipher = std::move(ciphertext);
  169. }
  170. void Secp256k1PP::decrypt(Secret const& _k, bytes& io_text)
  171. {
  172. CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d;
  173. initializeDLScheme(_k, d);
  174. if (!io_text.size())
  175. {
  176. io_text.resize(1);
  177. io_text[0] = 0;
  178. }
  179. size_t clen = io_text.size();
  180. bytes plain;
  181. plain.resize(d.MaxPlaintextLength(io_text.size()));
  182. DecodingResult r;
  183. {
  184. Guard l(x_rng);
  185. r = d.Decrypt(m_rng, io_text.data(), clen, plain.data());
  186. }
  187. if (!r.isValidCoding)
  188. {
  189. io_text.clear();
  190. return;
  191. }
  192. io_text.resize(r.messageLength);
  193. io_text = std::move(plain);
  194. }
  195. Signature Secp256k1PP::sign(Secret const& _k, bytesConstRef _message)
  196. {
  197. return sign(_k, sha3(_message));
  198. }
  199. Signature Secp256k1PP::sign(Secret const& _key, h256 const& _hash)
  200. {
  201. // assumption made by signing alogrithm
  202. asserts(m_q == m_qs);
  203. Signature sig;
  204. Integer k(kdf(_key, _hash).data(), 32);
  205. if (k == 0)
  206. BOOST_THROW_EXCEPTION(InvalidState());
  207. k = 1 + (k % (m_qs - 1));
  208. ECP::Point rp;
  209. Integer r;
  210. {
  211. Guard l(x_params);
  212. rp = m_params.ExponentiateBase(k);
  213. r = m_params.ConvertElementToInteger(rp);
  214. }
  215. sig[64] = 0;
  216. // sig[64] = (r >= m_q) ? 2 : 0;
  217. Integer kInv = k.InverseMod(m_q);
  218. Integer z(_hash.asBytes().data(), 32);
  219. Integer s = (kInv * (Integer(_key.data(), 32) * r + z)) % m_q;
  220. if (r == 0 || s == 0)
  221. BOOST_THROW_EXCEPTION(InvalidState());
  222. // if (s > m_qs)
  223. // {
  224. // s = m_q - s;
  225. // if (sig[64])
  226. // sig[64] ^= 1;
  227. // }
  228. sig[64] |= rp.y.IsOdd() ? 1 : 0;
  229. r.Encode(sig.data(), 32);
  230. s.Encode(sig.data() + 32, 32);
  231. return sig;
  232. }
  233. bool Secp256k1PP::verify(Signature const& _signature, bytesConstRef _message)
  234. {
  235. return !!recover(_signature, _message);
  236. }
  237. bool Secp256k1PP::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
  238. {
  239. // todo: verify w/o recovery (if faster)
  240. return _p == (_hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref()));
  241. }
  242. Public Secp256k1PP::recover(Signature _signature, bytesConstRef _message)
  243. {
  244. Public recovered;
  245. Integer r(_signature.data(), 32);
  246. Integer s(_signature.data()+32, 32);
  247. // cryptopp encodes sign of y as 0x02/0x03 instead of 0/1 or 27/28
  248. byte encodedpoint[33];
  249. encodedpoint[0] = _signature[64] | 2;
  250. memcpy(&encodedpoint[1], _signature.data(), 32);
  251. ECP::Element x;
  252. {
  253. m_curve.DecodePoint(x, encodedpoint, 33);
  254. if (!m_curve.VerifyPoint(x))
  255. return recovered;
  256. }
  257. // if (_signature[64] & 2)
  258. // {
  259. // r += m_q;
  260. // Guard l(x_params);
  261. // if (r >= m_params.GetMaxExponent())
  262. // return recovered;
  263. // }
  264. Integer z(_message.data(), 32);
  265. Integer rn = r.InverseMod(m_q);
  266. Integer u1 = m_q - (rn.Times(z)).Modulo(m_q);
  267. Integer u2 = (rn.Times(s)).Modulo(m_q);
  268. ECP::Point p;
  269. byte recoveredbytes[65];
  270. {
  271. // todo: make generator member
  272. p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
  273. if (p.identity)
  274. return Public();
  275. m_curve.EncodePoint(recoveredbytes, p, false);
  276. }
  277. memcpy(recovered.data(), &recoveredbytes[1], 64);
  278. return recovered;
  279. }
  280. bool Secp256k1PP::verifySecret(Secret const& _s, Public& _p)
  281. {
  282. DL_PrivateKey_EC<ECP> k;
  283. k.Initialize(m_params, secretToExponent(_s));
  284. if (!k.Validate(m_rng, 3))
  285. return false;
  286. DL_PublicKey_EC<CryptoPP::ECP> pub;
  287. k.MakePublicKey(pub);
  288. if (!k.Validate(m_rng, 3))
  289. return false;
  290. exportPublicKey(pub, _p);
  291. return true;
  292. }
  293. void Secp256k1PP::agree(Secret const& _s, Public const& _r, Secret& o_s)
  294. {
  295. // TODO: mutex ASN1::secp256k1() singleton
  296. // Creating Domain is non-const for m_oid and m_oid is not thread-safe
  297. ECDH<ECP>::Domain d(ASN1::secp256k1());
  298. assert(d.AgreedValueLength() == sizeof(o_s));
  299. byte remote[65] = {0x04};
  300. memcpy(&remote[1], _r.data(), 64);
  301. d.Agree(o_s.writable().data(), _s.data(), remote);
  302. }
  303. void Secp256k1PP::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& o_p)
  304. {
  305. bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
  306. {
  307. Guard l(x_params);
  308. m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
  309. assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
  310. }
  311. memcpy(o_p.data(), &prefixedKey[1], Public::size);
  312. }
  313. void Secp256k1PP::exponentToPublic(Integer const& _e, Public& o_p)
  314. {
  315. CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pk;
  316. {
  317. Guard l(x_params);
  318. pk.Initialize(m_params, m_params.ExponentiateBase(_e));
  319. }
  320. exportPublicKey(pk, o_p);
  321. }
  322. #if defined(__GNUC__)
  323. #pragma GCC diagnostic pop
  324. #endif // defined(__GNUC__)