rlpx.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  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 crypto.cpp
  15. * @author Alex Leverington <nessence@gmail.com>
  16. * @date 2015
  17. * RLPx test functions.
  18. */
  19. #include <libdevcore/Common.h>
  20. #include <libdevcore/RLP.h>
  21. #include <libdevcore/Log.h>
  22. #include <boost/test/unit_test.hpp>
  23. #include <libdevcore/SHA3.h>
  24. #include <libdevcrypto/ECDHE.h>
  25. #include <libdevcrypto/CryptoPP.h>
  26. #include <libp2p/RLPxHandshake.h>
  27. #include <libp2p/RLPXFrameWriter.h>
  28. #include <libp2p/RLPXFrameReader.h>
  29. #include <test/TestHelper.h>
  30. using namespace std;
  31. using namespace dev;
  32. using namespace dev::crypto;
  33. using namespace dev::p2p;
  34. using namespace dev::test;
  35. using namespace CryptoPP;
  36. struct RLPXTestFixture: public TestOutputHelper {
  37. RLPXTestFixture() : s_secp256k1(Secp256k1PP::get()) {}
  38. ~RLPXTestFixture() {}
  39. Secp256k1PP* s_secp256k1;
  40. };
  41. BOOST_FIXTURE_TEST_SUITE(rlpx, RLPXTestFixture)
  42. static CryptoPP::AutoSeededRandomPool s_rng;
  43. static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1());
  44. static CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP> s_params(s_curveOID);
  45. static CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP>::EllipticCurve s_curve(s_params.GetCurve());
  46. #if defined(__GNUC__)
  47. // Do not warn about uses of functions (see Function Attributes), variables
  48. // (see Variable Attributes), and types (see Type Attributes) marked as
  49. // deprecated by using the deprecated attribute.
  50. //
  51. // Specifically we are suppressing the warnings from the deprecation
  52. // attributes added to the SHA3_256 and SHA3_512 classes in CryptoPP
  53. // after the 5.6.3 release.
  54. //
  55. // From that header file ...
  56. //
  57. // "The Crypto++ SHA-3 implementation dates back to January 2013 when NIST
  58. // selected Keccak as SHA-3. In August 2015 NIST finalized SHA-3, and it
  59. // was a modified version of the Keccak selection. Crypto++ 5.6.2 through
  60. // 5.6.4 provides the pre-FIPS 202 version of SHA-3; while Crypto++ 5.7
  61. // and above provides the FIPS 202 version of SHA-3.
  62. //
  63. // See also http://en.wikipedia.org/wiki/SHA-3
  64. //
  65. // This means that we will never be able to move to the CryptoPP-5.7.x
  66. // series of releases, because Ethereum requires Keccak, not the final
  67. // SHA-3 standard algorithm. We are planning to migrate cpp-ethereum
  68. // off CryptoPP anyway, so this is unlikely to be a long-standing issue.
  69. //
  70. // https://github.com/ethereum/cpp-ethereum/issues/3088
  71. //
  72. #pragma GCC diagnostic push
  73. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  74. #endif // defined(__GNUC__)
  75. BOOST_AUTO_TEST_CASE(test_secrets_cpp_vectors)
  76. {
  77. KeyPair init(Secret(sha3("initiator")));
  78. KeyPair initR(Secret(sha3("initiator-random")));
  79. h256 initNonce(sha3("initiator-nonce"));
  80. KeyPair recv(Secret(sha3("remote-recv")));
  81. KeyPair recvR(Secret(sha3("remote-recv-random")));
  82. h256 recvNonce(sha3("remote-recv-nonce"));
  83. bytes authCipher(fromHex(""));
  84. bytes ackCipher(fromHex(""));
  85. CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameEnc;
  86. CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameDec;
  87. CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_macEnc;
  88. CryptoPP::SHA3_256 m_egressMac;
  89. CryptoPP::SHA3_256 m_ingressMac;
  90. // when originated is true, agreement is with init secrets
  91. // when originated is true, remoteNonce = recvNonce
  92. // when originated is true, nonce = initNonce
  93. bool originated = true;
  94. auto remoteNonce = recvNonce;
  95. auto nonce = initNonce;
  96. bytes keyMaterialBytes(64);
  97. bytesRef keyMaterial(&keyMaterialBytes);
  98. // shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
  99. Secret ephemeralShared;
  100. s_secp256k1->agree(initR.sec(), recvR.pub(), ephemeralShared);
  101. Secret expected(fromHex("20d82c1092f351dc217bd66fa183e801234af14ead40423b6ee25112201c6e5a"));
  102. BOOST_REQUIRE(expected == ephemeralShared);
  103. ephemeralShared.ref().copyTo(keyMaterial.cropped(0, h256::size));
  104. h512 nonceMaterial;
  105. h256 const& leftNonce = originated ? remoteNonce : nonce;
  106. h256 const& rightNonce = originated ? nonce : remoteNonce;
  107. leftNonce.ref().copyTo(nonceMaterial.ref().cropped(0, h256::size));
  108. rightNonce.ref().copyTo(nonceMaterial.ref().cropped(h256::size, h256::size));
  109. auto outRef(keyMaterial.cropped(h256::size, h256::size));
  110. sha3(nonceMaterial.ref(), outRef); // output h(nonces)
  111. // test that keyMaterial = ecdhe-shared-secret || sha3(nonce || initiator-nonce)
  112. {
  113. BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
  114. SHA3_256 ctx;
  115. ctx.Update(leftNonce.data(), h256::size);
  116. ctx.Update(rightNonce.data(), h256::size);
  117. bytes expected(32);
  118. ctx.Final(expected.data());
  119. bytes given(32);
  120. outRef.copyTo(&given);
  121. BOOST_REQUIRE(expected == given);
  122. }
  123. bytes preImage(keyMaterialBytes);
  124. // shared-secret <- sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
  125. // keyMaterial = ecdhe-shared-secret || shared-secret
  126. sha3(keyMaterial, outRef);
  127. bytes sharedSecret(32);
  128. outRef.copyTo(&sharedSecret);
  129. BOOST_REQUIRE(sharedSecret == fromHex("b65319ce56e00f3be75c4d0da92b5957d5583ca25eeeedac8e29b6dfc8b1ddf7"));
  130. // test that keyMaterial = ecdhe-shared-secret || shared-secret
  131. {
  132. BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
  133. SHA3_256 ctx;
  134. ctx.Update(preImage.data(), preImage.size());
  135. bytes expected(32);
  136. ctx.Final(expected.data());
  137. bytes test(32);
  138. outRef.copyTo(&test);
  139. BOOST_REQUIRE(expected == test);
  140. }
  141. // token: sha3(outRef)
  142. bytes token(32);
  143. sha3(outRef, bytesRef(&token));
  144. BOOST_REQUIRE(token == fromHex("db41fe0180f372983cf19fca7ee890f7fb5481079d44683d2c027be9e71bbca2"));
  145. // aes-secret = sha3(ecdhe-shared-secret || shared-secret)
  146. sha3(keyMaterial, outRef); // output aes-secret
  147. bytes aesSecret(32);
  148. outRef.copyTo(&aesSecret);
  149. BOOST_REQUIRE(aesSecret == fromHex("12347b4784bcb4e74b84637940482852fe25d78e328cf5c6f7a396bf96cc20bb"));
  150. m_frameEnc.SetKeyWithIV(outRef.data(), h128::size, h128().data());
  151. m_frameDec.SetKeyWithIV(outRef.data(), h128::size, h128().data());
  152. // mac-secret = sha3(ecdhe-shared-secret || aes-secret)
  153. sha3(keyMaterial, outRef); // output mac-secret
  154. bytes macSecret(32);
  155. outRef.copyTo(&macSecret);
  156. BOOST_REQUIRE(macSecret == fromHex("2ec149072353d54437422837c886b0538a9206e6c559f6b4a55f65a866867723"));
  157. m_macEnc.SetKey(outRef.data(), h128::size);
  158. // Initiator egress-mac: sha3(mac-secret^recipient-nonce || auth-sent-init)
  159. // ingress-mac: sha3(mac-secret^initiator-nonce || auth-recvd-ack)
  160. // Recipient egress-mac: sha3(mac-secret^initiator-nonce || auth-sent-ack)
  161. // ingress-mac: sha3(mac-secret^recipient-nonce || auth-recvd-init)
  162. (*(h256*)outRef.data() ^ remoteNonce).ref().copyTo(keyMaterial);
  163. bytes const& egressCipher = originated ? authCipher : ackCipher;
  164. keyMaterialBytes.resize(h256::size + egressCipher.size());
  165. keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
  166. bytesConstRef(&egressCipher).copyTo(keyMaterial.cropped(h256::size, egressCipher.size()));
  167. m_egressMac.Update(keyMaterial.data(), keyMaterial.size());
  168. {
  169. bytes egressMac;
  170. SHA3_256 h(m_egressMac);
  171. bytes digest(16);
  172. h.TruncatedFinal(digest.data(), 16);
  173. BOOST_REQUIRE(digest == fromHex("23e5e8efb6e3765ecae1fca9160b18df"));
  174. }
  175. // recover mac-secret by re-xoring remoteNonce
  176. (*(h256*)keyMaterial.data() ^ remoteNonce ^ nonce).ref().copyTo(keyMaterial);
  177. bytes const& ingressCipher = originated ? ackCipher : authCipher;
  178. keyMaterialBytes.resize(h256::size + ingressCipher.size());
  179. keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
  180. bytesConstRef(&ingressCipher).copyTo(keyMaterial.cropped(h256::size, ingressCipher.size()));
  181. m_ingressMac.Update(keyMaterial.data(), keyMaterial.size());
  182. {
  183. bytes ingressMac;
  184. SHA3_256 h(m_ingressMac);
  185. bytes digest(16);
  186. h.TruncatedFinal(digest.data(), 16);
  187. BOOST_REQUIRE(digest == fromHex("ceed64135852064cbdde86e7ea05e8f5"));
  188. }
  189. }
  190. BOOST_AUTO_TEST_CASE(test_secrets_from_go)
  191. {
  192. KeyPair init(Secret(fromHex("0x5e173f6ac3c669587538e7727cf19b782a4f2fda07c1eaa662c593e5e85e3051")));
  193. KeyPair initR(Secret(fromHex("0x19c2185f4f40634926ebed3af09070ca9e029f2edd5fae6253074896205f5f6c")));
  194. h256 initNonce(fromHex("0xcd26fecb93657d1cd9e9eaf4f8be720b56dd1d39f190c4e1c6b7ec66f077bb11"));
  195. KeyPair recv(Secret(fromHex("0xc45f950382d542169ea207959ee0220ec1491755abe405cd7498d6b16adb6df8")));
  196. KeyPair recvR(Secret(fromHex("0xd25688cf0ab10afa1a0e2dba7853ed5f1e5bf1c631757ed4e103b593ff3f5620")));
  197. h256 recvNonce(fromHex("0xf37ec61d84cea03dcc5e8385db93248584e8af4b4d1c832d8c7453c0089687a7"));
  198. bytes authCipher(fromHex("0x04a0274c5951e32132e7f088c9bdfdc76c9d91f0dc6078e848f8e3361193dbdc43b94351ea3d89e4ff33ddcefbc80070498824857f499656c4f79bbd97b6c51a514251d69fd1785ef8764bd1d262a883f780964cce6a14ff206daf1206aa073a2d35ce2697ebf3514225bef186631b2fd2316a4b7bcdefec8d75a1025ba2c5404a34e7795e1dd4bc01c6113ece07b0df13b69d3ba654a36e35e69ff9d482d88d2f0228e7d96fe11dccbb465a1831c7d4ad3a026924b182fc2bdfe016a6944312021da5cc459713b13b86a686cf34d6fe6615020e4acf26bf0d5b7579ba813e7723eb95b3cef9942f01a58bd61baee7c9bdd438956b426a4ffe238e61746a8c93d5e10680617c82e48d706ac4953f5e1c4c4f7d013c87d34a06626f498f34576dc017fdd3d581e83cfd26cf125b6d2bda1f1d56"));
  199. bytes ackCipher(fromHex("0x049934a7b2d7f9af8fd9db941d9da281ac9381b5740e1f64f7092f3588d4f87f5ce55191a6653e5e80c1c5dd538169aa123e70dc6ffc5af1827e546c0e958e42dad355bcc1fcb9cdf2cf47ff524d2ad98cbf275e661bf4cf00960e74b5956b799771334f426df007350b46049adb21a6e78ab1408d5e6ccde6fb5e69f0f4c92bb9c725c02f99fa72b9cdc8dd53cff089e0e73317f61cc5abf6152513cb7d833f09d2851603919bf0fbe44d79a09245c6e8338eb502083dc84b846f2fee1cc310d2cc8b1b9334728f97220bb799376233e113"));
  200. bytes authPlainExpected(fromHex("0x884c36f7ae6b406637c1f61b2f57e1d2cab813d24c6559aaf843c3f48962f32f46662c066d39669b7b2e3ba14781477417600e7728399278b1b5d801a519aa570034fdb5419558137e0d44cd13d319afe5629eeccb47fd9dfe55cc6089426e46cc762dd8a0636e07a54b31169eba0c7a20a1ac1ef68596f1f283b5c676bae4064abfcce24799d09f67e392632d3ffdc12e3d6430dcb0ea19c318343ffa7aae74d4cd26fecb93657d1cd9e9eaf4f8be720b56dd1d39f190c4e1c6b7ec66f077bb1100"));
  201. bytes ackPlainExpected(fromHex("0x802b052f8b066640bba94a4fc39d63815c377fced6fcb84d27f791c9921ddf3e9bf0108e298f490812847109cbd778fae393e80323fd643209841a3b7f110397f37ec61d84cea03dcc5e8385db93248584e8af4b4d1c832d8c7453c0089687a700"));
  202. bytes authPlain = authCipher;
  203. BOOST_REQUIRE(s_secp256k1->decryptECIES(recv.sec(), authPlain));
  204. bytes ackPlain = ackCipher;
  205. BOOST_REQUIRE(s_secp256k1->decryptECIES(init.sec(), ackPlain));
  206. CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameEnc;
  207. CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameDec;
  208. CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_macEnc;
  209. CryptoPP::SHA3_256 m_egressMac;
  210. CryptoPP::SHA3_256 m_ingressMac;
  211. // when originated is true, agreement is with init secrets
  212. // when originated is true, remoteNonce = recvNonce
  213. // when originated is true, nonce = initNonce
  214. bool originated = true;
  215. auto remoteNonce = recvNonce;
  216. auto nonce = initNonce;
  217. bytes keyMaterialBytes(64);
  218. bytesRef keyMaterial(&keyMaterialBytes);
  219. // shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
  220. Secret ephemeralShared;
  221. s_secp256k1->agree(initR.sec(), recvR.pub(), ephemeralShared);
  222. Secret expected(fromHex("0xe3f407f83fc012470c26a93fdff534100f2c6f736439ce0ca90e9914f7d1c381"));
  223. BOOST_REQUIRE(expected == ephemeralShared);
  224. ephemeralShared.ref().copyTo(keyMaterial.cropped(0, h256::size));
  225. h512 nonceMaterial;
  226. h256 const& leftNonce = originated ? remoteNonce : nonce;
  227. h256 const& rightNonce = originated ? nonce : remoteNonce;
  228. leftNonce.ref().copyTo(nonceMaterial.ref().cropped(0, h256::size));
  229. rightNonce.ref().copyTo(nonceMaterial.ref().cropped(h256::size, h256::size));
  230. auto outRef(keyMaterial.cropped(h256::size, h256::size));
  231. sha3(nonceMaterial.ref(), outRef); // output h(nonces)
  232. // test that keyMaterial = ecdhe-shared-secret || sha3(nonce || initiator-nonce)
  233. {
  234. BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
  235. SHA3_256 ctx;
  236. ctx.Update(leftNonce.data(), h256::size);
  237. ctx.Update(rightNonce.data(), h256::size);
  238. bytes expected(32);
  239. ctx.Final(expected.data());
  240. bytes given(32);
  241. outRef.copyTo(&given);
  242. BOOST_REQUIRE(expected == given);
  243. }
  244. bytes preImage(keyMaterialBytes);
  245. // shared-secret <- sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
  246. // keyMaterial = ecdhe-shared-secret || shared-secret
  247. sha3(keyMaterial, outRef);
  248. // test that keyMaterial = ecdhe-shared-secret || shared-secret
  249. {
  250. BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
  251. SHA3_256 ctx;
  252. ctx.Update(preImage.data(), preImage.size());
  253. bytes expected(32);
  254. ctx.Final(expected.data());
  255. bytes test(32);
  256. outRef.copyTo(&test);
  257. BOOST_REQUIRE(expected == test);
  258. }
  259. // token: sha3(outRef)
  260. bytes token(32);
  261. sha3(outRef, bytesRef(&token));
  262. BOOST_REQUIRE(token == fromHex("0x3f9ec2592d1554852b1f54d228f042ed0a9310ea86d038dc2b401ba8cd7fdac4"));
  263. // aes-secret = sha3(ecdhe-shared-secret || shared-secret)
  264. sha3(keyMaterial, outRef); // output aes-secret
  265. bytes aesSecret(32);
  266. outRef.copyTo(&aesSecret);
  267. BOOST_REQUIRE(aesSecret == fromHex("0xc0458fa97a5230830e05f4f20b7c755c1d4e54b1ce5cf43260bb191eef4e418d"));
  268. m_frameEnc.SetKeyWithIV(outRef.data(), h128::size, h128().data());
  269. m_frameDec.SetKeyWithIV(outRef.data(), h128::size, h128().data());
  270. // mac-secret = sha3(ecdhe-shared-secret || aes-secret)
  271. sha3(keyMaterial, outRef); // output mac-secret
  272. bytes macSecret(32);
  273. outRef.copyTo(&macSecret);
  274. BOOST_REQUIRE(macSecret == fromHex("0x48c938884d5067a1598272fcddaa4b833cd5e7d92e8228c0ecdfabbe68aef7f1"));
  275. m_macEnc.SetKey(outRef.data(), h256::size);
  276. // Initiator egress-mac: sha3(mac-secret^recipient-nonce || auth-sent-init)
  277. // ingress-mac: sha3(mac-secret^initiator-nonce || auth-recvd-ack)
  278. // Recipient egress-mac: sha3(mac-secret^initiator-nonce || auth-sent-ack)
  279. // ingress-mac: sha3(mac-secret^recipient-nonce || auth-recvd-init)
  280. (*(h256*)outRef.data() ^ remoteNonce).ref().copyTo(keyMaterial);
  281. bytes const& egressCipher = originated ? authCipher : ackCipher;
  282. keyMaterialBytes.resize(h256::size + egressCipher.size());
  283. keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
  284. bytesConstRef(&egressCipher).copyTo(keyMaterial.cropped(h256::size, egressCipher.size()));
  285. m_egressMac.Update(keyMaterialBytes.data(), keyMaterialBytes.size());
  286. {
  287. bytes egressMac;
  288. SHA3_256 h(m_egressMac);
  289. bytes digest(32);
  290. h.Final(digest.data());
  291. BOOST_REQUIRE(digest == fromHex("0x09771e93b1a6109e97074cbe2d2b0cf3d3878efafe68f53c41bb60c0ec49097e"));
  292. }
  293. // recover mac-secret by re-xoring remoteNonce
  294. bytes recoverMacSecretTest(32);
  295. (*(h256*)keyMaterial.data() ^ remoteNonce).ref().copyTo(&recoverMacSecretTest);
  296. BOOST_REQUIRE(recoverMacSecretTest == macSecret);
  297. (*(h256*)keyMaterial.data() ^ remoteNonce ^ nonce).ref().copyTo(keyMaterial);
  298. bytes const& ingressCipher = originated ? ackCipher : authCipher;
  299. keyMaterialBytes.resize(h256::size + ingressCipher.size());
  300. keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
  301. bytesConstRef(&ingressCipher).copyTo(keyMaterial.cropped(h256::size, ingressCipher.size()));
  302. m_ingressMac.Update(keyMaterial.data(), keyMaterial.size());
  303. {
  304. bytes ingressMac;
  305. SHA3_256 h(m_ingressMac);
  306. bytes digest(32);
  307. h.Final(digest.data());
  308. BOOST_CHECK(digest == fromHex("0x75823d96e23136c89666ee025fb21a432be906512b3dd4a3049e898adb433847"));
  309. }
  310. bytes initHello(fromHex("6ef23fcf1cec7312df623f9ae701e63b550cdb8517fefd8dd398fc2acd1d935e6e0434a2b96769078477637347b7b01924fff9ff1c06df2f804df3b0402bbb9f87365b3c6856b45e1e2b6470986813c3816a71bff9d69dd297a5dbd935ab578f6e5d7e93e4506a44f307c332d95e8a4b102585fd8ef9fc9e3e055537a5cec2e9"));
  311. bytes recvHello(fromHex("6ef23fcf1cec7312df623f9ae701e63be36a1cdd1b19179146019984f3625d4a6e0434a2b96769050577657247b7b02bc6c314470eca7e3ef650b98c83e9d7dd4830b3f718ff562349aead2530a8d28a8484604f92e5fced2c6183f304344ab0e7c301a0c05559f4c25db65e36820b4b909a226171a60ac6cb7beea09376d6d8"));
  312. /// test macs of frame headers
  313. {
  314. SHA3_256 egressmac(m_egressMac);
  315. SHA3_256 prevDigest(egressmac);
  316. h128 prevDigestOut;
  317. prevDigest.TruncatedFinal(prevDigestOut.data(), h128::size);
  318. h128 encDigest;
  319. m_macEnc.ProcessData(encDigest.data(), prevDigestOut.data(), h128::size);
  320. encDigest ^= *(h128*)initHello.data();
  321. egressmac.Update(encDigest.data(), h128::size);
  322. egressmac.TruncatedFinal(encDigest.data(), h128::size);
  323. bytes provided(16);
  324. bytesConstRef(&initHello).cropped(16, 16).copyTo(bytesRef(&provided));
  325. BOOST_REQUIRE(*(h128*)encDigest.data() == *(h128*)provided.data());
  326. }
  327. {
  328. SHA3_256 ingressmac(m_ingressMac);
  329. SHA3_256 prevDigest(ingressmac);
  330. h128 prevDigestOut;
  331. prevDigest.TruncatedFinal(prevDigestOut.data(), h128::size);
  332. h128 encDigest;
  333. m_macEnc.ProcessData(encDigest.data(), prevDigestOut.data(), h128::size);
  334. encDigest ^= *(h128*)recvHello.data();
  335. ingressmac.Update(encDigest.data(), h128::size);
  336. ingressmac.TruncatedFinal(encDigest.data(), h128::size);
  337. bytes provided(16);
  338. bytesConstRef(&recvHello).cropped(16, 16).copyTo(bytesRef(&provided));
  339. BOOST_REQUIRE(*(h128*)encDigest.data() == *(h128*)provided.data());
  340. }
  341. // test decrypt of frame headers for recvHello
  342. bytes plaintext(16);
  343. m_frameDec.ProcessData(plaintext.data(), recvHello.data(), h128::size);
  344. }
  345. #if defined(__GNUC__)
  346. #pragma GCC diagnostic pop
  347. #endif // defined(__GNUC__)
  348. BOOST_AUTO_TEST_CASE(ecies_interop_test_primitives)
  349. {
  350. CryptoPP::SHA256 sha256ctx;
  351. bytes emptyExpected(fromHex("0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
  352. bytes empty;
  353. sha256ctx.Update(empty.data(), 0);
  354. bytes emptyTestOut(32);
  355. sha256ctx.Final(emptyTestOut.data());
  356. BOOST_REQUIRE(emptyExpected == emptyTestOut);
  357. bytes hash1Expected(fromHex("0x8949b278bbafb8da1aaa18cb724175c5952280f74be5d29ab4b37d1b45c84b08"));
  358. bytes hash1input(fromHex("0x55a53b55afb12affff3c"));
  359. sha256ctx.Update(hash1input.data(), hash1input.size());
  360. bytes hash1Out(32);
  361. sha256ctx.Final(hash1Out.data());
  362. BOOST_REQUIRE(hash1Out == hash1Expected);
  363. h128 hmack(fromHex("0x07a4b6dfa06369a570f2dcba2f11a18f"));
  364. CryptoPP::HMAC<SHA256> hmacctx(hmack.data(), h128::size);
  365. bytes input(fromHex("0x4dcb92ed4fc67fe86832"));
  366. hmacctx.Update(input.data(), input.size());
  367. bytes hmacExpected(fromHex("0xc90b62b1a673b47df8e395e671a68bfa68070d6e2ef039598bb829398b89b9a9"));
  368. bytes hmacOut(hmacExpected.size());
  369. hmacctx.Final(hmacOut.data());
  370. BOOST_REQUIRE(hmacExpected == hmacOut);
  371. // go messageTag
  372. bytes tagSecret(fromHex("0xaf6623e52208c596e17c72cea6f1cb09"));
  373. bytes tagInput(fromHex("0x3461282bcedace970df2"));
  374. bytes tagExpected(fromHex("0xb3ce623bce08d5793677ba9441b22bb34d3e8a7de964206d26589df3e8eb5183"));
  375. CryptoPP::HMAC<SHA256> hmactagctx(tagSecret.data(), tagSecret.size());
  376. hmactagctx.Update(tagInput.data(), tagInput.size());
  377. h256 mac;
  378. hmactagctx.Final(mac.data());
  379. BOOST_REQUIRE(mac.asBytes() == tagExpected);
  380. Secret input1(fromHex("0x0de72f1223915fa8b8bf45dffef67aef8d89792d116eb61c9a1eb02c422a4663"));
  381. bytes expect1(fromHex("0x1d0c446f9899a3426f2b89a8cb75c14b"));
  382. bytes test1;
  383. test1 = s_secp256k1->eciesKDF(input1, bytes(), 16);
  384. BOOST_REQUIRE(test1 == expect1);
  385. Secret kdfInput2(fromHex("0x961c065873443014e0371f1ed656c586c6730bf927415757f389d92acf8268df"));
  386. bytes kdfExpect2(fromHex("0x4050c52e6d9c08755e5a818ac66fabe478b825b1836fd5efc4d44e40d04dabcc"));
  387. bytes kdfTest2;
  388. kdfTest2 = s_secp256k1->eciesKDF(kdfInput2, bytes(), 32);
  389. BOOST_REQUIRE(kdfTest2 == kdfExpect2);
  390. KeyPair k(Secret(fromHex("0x332143e9629eedff7d142d741f896258f5a1bfab54dab2121d3ec5000093d74b")));
  391. Public p(fromHex("0xf0d2b97981bd0d415a843b5dfe8ab77a30300daab3658c578f2340308a2da1a07f0821367332598b6aa4e180a41e92f4ebbae3518da847f0b1c0bbfe20bcf4e1"));
  392. Secret agreeExpected(fromHex("0xee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08"));
  393. Secret agreeTest;
  394. s_secp256k1->agree(k.sec(), p, agreeTest);
  395. BOOST_REQUIRE(agreeExpected == agreeTest);
  396. KeyPair kmK(Secret(fromHex("0x57baf2c62005ddec64c357d96183ebc90bf9100583280e848aa31d683cad73cb")));
  397. bytes kmCipher(fromHex("0x04ff2c874d0a47917c84eea0b2a4141ca95233720b5c70f81a8415bae1dc7b746b61df7558811c1d6054333907333ef9bb0cc2fbf8b34abb9730d14e0140f4553f4b15d705120af46cf653a1dc5b95b312cf8444714f95a4f7a0425b67fc064d18f4d0a528761565ca02d97faffdac23de10"));
  398. bytes kmPlain = kmCipher;
  399. bytes kmExpected(asBytes("a"));
  400. BOOST_REQUIRE(s_secp256k1->decryptECIES(kmK.sec(), kmPlain));
  401. BOOST_REQUIRE(kmExpected == kmPlain);
  402. KeyPair kenc(Secret(fromHex("0x472413e97f1fd58d84e28a559479e6b6902d2e8a0cee672ef38a3a35d263886b")));
  403. Public penc(Public(fromHex("0x7a2aa2951282279dc1171549a7112b07c38c0d97c0fe2c0ae6c4588ba15be74a04efc4f7da443f6d61f68a9279bc82b73e0cc8d090048e9f87e838ae65dd8d4c")));
  404. BOOST_REQUIRE(penc == kenc.pub());
  405. bytes cipher1(fromHex("0x046f647e1bd8a5cd1446d31513bac233e18bdc28ec0e59d46de453137a72599533f1e97c98154343420d5f16e171e5107999a7c7f1a6e26f57bcb0d2280655d08fb148d36f1d4b28642d3bb4a136f0e33e3dd2e3cffe4b45a03fb7c5b5ea5e65617250fdc89e1a315563c20504b9d3a72555"));
  406. bytes plainTest1 = cipher1;
  407. bytes expectedPlain1 = asBytes("a");
  408. BOOST_REQUIRE(s_secp256k1->decryptECIES(kenc.sec(), plainTest1));
  409. BOOST_REQUIRE(plainTest1 == expectedPlain1);
  410. bytes cipher2(fromHex("0x0443c24d6ccef3ad095140760bb143078b3880557a06392f17c5e368502d79532bc18903d59ced4bbe858e870610ab0d5f8b7963dd5c9c4cf81128d10efd7c7aa80091563c273e996578403694673581829e25a865191bdc9954db14285b56eb0043b6288172e0d003c10f42fe413222e273d1d4340c38a2d8344d7aadcbc846ee"));
  411. bytes plainTest2 = cipher2;
  412. bytes expectedPlain2 = asBytes("aaaaaaaaaaaaaaaa");
  413. BOOST_REQUIRE(s_secp256k1->decryptECIES(kenc.sec(), plainTest2));
  414. BOOST_REQUIRE(plainTest2 == expectedPlain2);
  415. bytes cipher3(fromHex("0x04c4e40c86bb5324e017e598c6d48c19362ae527af8ab21b077284a4656c8735e62d73fb3d740acefbec30ca4c024739a1fcdff69ecaf03301eebf156eb5f17cca6f9d7a7e214a1f3f6e34d1ee0ec00ce0ef7d2b242fbfec0f276e17941f9f1bfbe26de10a15a6fac3cda039904ddd1d7e06e7b96b4878f61860e47f0b84c8ceb64f6a900ff23844f4359ae49b44154980a626d3c73226c19e"));
  416. bytes plainTest3 = cipher3;
  417. bytes expectedPlain3 = asBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
  418. BOOST_REQUIRE(s_secp256k1->decryptECIES(kenc.sec(), plainTest3));
  419. BOOST_REQUIRE(plainTest3 == expectedPlain3);
  420. }
  421. BOOST_AUTO_TEST_CASE(segmentedPacketFlush)
  422. {
  423. ECDHE localEph;
  424. Secret localNonce = Nonce::get();
  425. ECDHE remoteEph;
  426. Secret remoteNonce = Nonce::get();
  427. bytes ackCipher{0};
  428. bytes authCipher{1};
  429. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  430. /// Test writing a 64byte RLPStream and drain with frame size that
  431. /// forces packet to be pieced into 4 frames.
  432. /// (Minimum frame size has room for 16 bytes of payload)
  433. // 64-byte payload minus 3 bytes for packet-type and RLP overhead.
  434. // Note: mux() is called with RLPXFrameWriter::MinFrameDequeLength
  435. // which is equal to 64byte, however, after overhead this means
  436. // there are only 16 bytes of payload which will be dequed.
  437. auto dequeLen = 16;
  438. bytes stuff = sha3("A").asBytes();
  439. bytes payload;
  440. payload += stuff;
  441. payload += stuff;
  442. payload.resize(payload.size() - 3 /* packet-type, rlp-overhead */);
  443. BOOST_REQUIRE_EQUAL(61, payload.size());
  444. auto drains = (payload.size() + 3) / dequeLen;
  445. BOOST_REQUIRE_EQUAL(4, drains);
  446. RLPXFrameWriter w(0);
  447. RLPStream rlpPayload(RLPStream() << payload);
  448. uint8_t packetType = 0;
  449. bytes packetTypeRLP = (RLPStream() << packetType).out();
  450. w.enque(packetType, rlpPayload);
  451. deque<bytes> encframes;
  452. for (unsigned i = 1; i < drains; i++)
  453. {
  454. auto n = w.mux(encoder, RLPXFrameWriter::MinFrameDequeLength, encframes);
  455. BOOST_REQUIRE_EQUAL(0, n);
  456. BOOST_REQUIRE_EQUAL(encframes.size(), i);
  457. }
  458. BOOST_REQUIRE_EQUAL(1, w.mux(encoder, RLPXFrameWriter::MinFrameDequeLength, encframes));
  459. BOOST_REQUIRE_EQUAL(encframes.size(), drains);
  460. BOOST_REQUIRE_EQUAL(0, w.mux(encoder, RLPXFrameWriter::MinFrameDequeLength, encframes));
  461. BOOST_REQUIRE_EQUAL(encframes.size(), drains);
  462. // we should now have a bunch of ciphertext in encframes
  463. BOOST_REQUIRE(encframes.size() == drains);
  464. for (auto const& c: encframes)
  465. {
  466. BOOST_REQUIRE_EQUAL(c.size(), RLPXFrameWriter::MinFrameDequeLength);
  467. }
  468. // read and assemble dequed encframes
  469. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  470. vector<RLPXPacket> packets;
  471. RLPXFrameReader r(0);
  472. for (size_t i = 0; i < encframes.size(); i++)
  473. {
  474. bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
  475. bytesRef header = frameWithHeader.cropped(0, h256::size);
  476. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  477. BOOST_REQUIRE(decryptedHeader);
  478. bytesRef frame = frameWithHeader.cropped(h256::size);
  479. RLPXFrameInfo f(header);
  480. for (RLPXPacket& p: r.demux(decoder, f, frame))
  481. packets.push_back(move(p));
  482. }
  483. BOOST_REQUIRE_EQUAL(packets.size(), 1);
  484. BOOST_REQUIRE_EQUAL(packets.front().size(), packetTypeRLP.size() + rlpPayload.out().size());
  485. BOOST_REQUIRE_EQUAL(sha3(RLP(packets.front().data()).payload()), sha3(payload));
  486. BOOST_REQUIRE_EQUAL(sha3(packets.front().type()), sha3(packetTypeRLP));
  487. }
  488. BOOST_AUTO_TEST_CASE(coalescedPacketsPadded)
  489. {
  490. ECDHE localEph;
  491. Secret localNonce = Nonce::get();
  492. ECDHE remoteEph;
  493. Secret remoteNonce = Nonce::get();
  494. bytes ackCipher{0};
  495. bytes authCipher{1};
  496. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  497. /// Test writing four 32 byte RLPStream packets such that
  498. /// a single 1KB frame will incldue all four packets.
  499. auto dequeLen = 1024; // sufficient enough for all packets
  500. bytes stuff = sha3("A").asBytes();
  501. deque<bytes> packetsOut;
  502. for (unsigned i = 0; i < 4; i++)
  503. packetsOut.push_back(stuff);
  504. RLPXFrameWriter w(0);
  505. uint8_t packetType = 127;
  506. bytes packetTypeRLP((RLPStream() << packetType).out());
  507. for (auto const& p: packetsOut)
  508. w.enque(packetType, (RLPStream() << p));
  509. deque<bytes> encframes;
  510. BOOST_REQUIRE_EQUAL(4, w.mux(encoder, dequeLen, encframes));
  511. BOOST_REQUIRE_EQUAL(0, w.mux(encoder, dequeLen, encframes));
  512. BOOST_REQUIRE_EQUAL(1, encframes.size());
  513. auto expectedFrameSize = RLPXFrameWriter::EmptyFrameLength + packetsOut.size() * (/*packet-type*/ 1 + h256::size + /*rlp-prefix*/ 1);
  514. expectedFrameSize += ((16 - (expectedFrameSize % 16)) % 16);
  515. BOOST_REQUIRE_EQUAL(expectedFrameSize, encframes[0].size());
  516. // read and assemble dequed encframes
  517. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  518. vector<RLPXPacket> packets;
  519. RLPXFrameReader r(0);
  520. bytesRef frameWithHeader(encframes[0].data(), encframes[0].size());
  521. bytesRef header = frameWithHeader.cropped(0, h256::size);
  522. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  523. BOOST_REQUIRE(decryptedHeader);
  524. bytesRef frame = frameWithHeader.cropped(h256::size);
  525. RLPXFrameInfo f(header);
  526. BOOST_REQUIRE_EQUAL(f.multiFrame, false);
  527. for (RLPXPacket& p: r.demux(decoder, f, frame))
  528. packets.push_back(move(p));
  529. RLPStream rlpPayload;
  530. rlpPayload << stuff;
  531. BOOST_REQUIRE_EQUAL(packets.size(), 4);
  532. while (!packets.empty())
  533. {
  534. BOOST_REQUIRE_EQUAL(packets.back().size(), packetTypeRLP.size() + rlpPayload.out().size());
  535. BOOST_REQUIRE_EQUAL(sha3(RLP(packets.back().data()).payload()), sha3(stuff));
  536. BOOST_REQUIRE_EQUAL(sha3(packets.back().type()), sha3(packetTypeRLP));
  537. packets.pop_back();
  538. }
  539. }
  540. BOOST_AUTO_TEST_CASE(singleFramePacketFlush)
  541. {
  542. ECDHE localEph;
  543. Secret localNonce = Nonce::get();
  544. ECDHE remoteEph;
  545. Secret remoteNonce = Nonce::get();
  546. bytes ackCipher{0};
  547. bytes authCipher{1};
  548. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  549. bytes stuff = sha3("A").asBytes();
  550. RLPXFrameWriter w(0);
  551. uint8_t packetType = 127;
  552. bytes packetTypeRLP((RLPStream() << packetType).out());
  553. w.enque(packetType, (RLPStream() << stuff));
  554. deque<bytes> encframes;
  555. auto dequeLen = RLPXFrameWriter::EmptyFrameLength + 34;
  556. dequeLen += ((16 - (dequeLen % 16)) % 16);
  557. BOOST_REQUIRE_EQUAL(1, w.mux(encoder, dequeLen, encframes));
  558. BOOST_REQUIRE_EQUAL(0, w.mux(encoder, dequeLen, encframes));
  559. BOOST_REQUIRE_EQUAL(1, encframes.size());
  560. BOOST_REQUIRE_EQUAL(dequeLen, encframes[0].size());
  561. // read and assemble dequed encframes
  562. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  563. vector<RLPXPacket> packets;
  564. RLPXFrameReader r(0);
  565. bytesRef frameWithHeader(encframes[0].data(), encframes[0].size());
  566. bytesRef header = frameWithHeader.cropped(0, h256::size);
  567. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  568. BOOST_REQUIRE(decryptedHeader);
  569. bytesRef frame = frameWithHeader.cropped(h256::size);
  570. RLPXFrameInfo f(header);
  571. BOOST_REQUIRE_EQUAL(f.multiFrame, false);
  572. for (RLPXPacket& p: r.demux(decoder, f, frame))
  573. packets.push_back(move(p));
  574. RLPStream rlpPayload;
  575. rlpPayload << stuff;
  576. BOOST_REQUIRE_EQUAL(packets.size(), 1);
  577. BOOST_REQUIRE_EQUAL(packets.back().size(), packetTypeRLP.size() + rlpPayload.out().size());
  578. BOOST_REQUIRE_EQUAL(sha3(RLP(packets.back().data()).payload()), sha3(stuff));
  579. BOOST_REQUIRE_EQUAL(sha3(packets.back().type()), sha3(packetTypeRLP));
  580. }
  581. BOOST_AUTO_TEST_CASE(multiProtocol)
  582. {
  583. /// Test writing four 32 byte RLPStream packets with different protocol ID.
  584. ECDHE localEph;
  585. ECDHE remoteEph;
  586. Secret localNonce = Nonce::get();
  587. Secret remoteNonce = Nonce::get();
  588. bytes ackCipher{0};
  589. bytes authCipher{1};
  590. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  591. auto dequeLen = 1024; // sufficient enough for all packets
  592. bytes stuff0 = sha3("A").asBytes();
  593. bytes stuff1 = sha3("B").asBytes();
  594. vector<bytes> vStuff;
  595. vStuff.push_back(stuff0);
  596. vStuff.push_back(stuff1);
  597. vector<bytes> packetsOut;
  598. packetsOut.push_back(stuff0);
  599. packetsOut.push_back(stuff0);
  600. packetsOut.push_back(stuff1);
  601. packetsOut.push_back(stuff1);
  602. std::map<uint16_t, RLPXFrameWriter*> mw;
  603. RLPXFrameWriter w0(0);
  604. RLPXFrameWriter w1(1);
  605. mw[0] = &w0;
  606. mw[1] = &w1;
  607. uint8_t const packetType = 127;
  608. bytes packetTypeRLP((RLPStream() << packetType).out());
  609. unsigned i = 0;
  610. mw[0]->enque(packetType, (RLPStream() << packetsOut[i++]));
  611. mw[0]->enque(packetType, (RLPStream() << packetsOut[i++]));
  612. mw[1]->enque(packetType, (RLPStream() << packetsOut[i++]));
  613. mw[1]->enque(packetType, (RLPStream() << packetsOut[i++]));
  614. deque<bytes> encframes;
  615. BOOST_REQUIRE_EQUAL(2, mw[0]->mux(encoder, dequeLen, encframes));
  616. BOOST_REQUIRE_EQUAL(2, mw[1]->mux(encoder, dequeLen, encframes));
  617. BOOST_REQUIRE_EQUAL(0, mw[0]->mux(encoder, dequeLen, encframes));
  618. BOOST_REQUIRE_EQUAL(0, mw[1]->mux(encoder, dequeLen, encframes));
  619. BOOST_REQUIRE_EQUAL(2, encframes.size());
  620. auto expectedFrameSize = RLPXFrameWriter::EmptyFrameLength
  621. + packetsOut.size() * (/*packet-type*/ 1 + h256::size + /*rlp-prefix*/ 1) / 2;
  622. expectedFrameSize += ((16 - (expectedFrameSize % 16)) % 16);
  623. BOOST_REQUIRE_EQUAL(expectedFrameSize, encframes[0].size());
  624. // read and assemble dequed encframes
  625. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  626. vector<RLPXPacket> packets;
  627. std::map<uint16_t, RLPXFrameReader*> mr;
  628. RLPXFrameReader r0(0);
  629. RLPXFrameReader r1(1);
  630. mr[0] = &r0;
  631. mr[1] = &r1;
  632. for (size_t i = 0; i < encframes.size(); i++)
  633. {
  634. bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
  635. bytesRef header = frameWithHeader.cropped(0, h256::size);
  636. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  637. BOOST_REQUIRE(decryptedHeader);
  638. bytesRef frame = frameWithHeader.cropped(h256::size);
  639. RLPXFrameInfo f(header);
  640. BOOST_REQUIRE_EQUAL(f.multiFrame, false);
  641. for (RLPXPacket& p: mr[f.protocolId]->demux(decoder, f, frame))
  642. {
  643. BOOST_REQUIRE_EQUAL(f.protocolId, p.cap());
  644. packets.push_back(move(p));
  645. }
  646. }
  647. BOOST_REQUIRE_EQUAL(packets.size(), 4);
  648. RLPStream rlpPayload0;
  649. RLPStream rlpPayload1;
  650. rlpPayload0 << stuff0;
  651. rlpPayload1 << stuff1;
  652. vector<RLPStream> vRlpPayloads;
  653. vRlpPayloads.push_back(rlpPayload0);
  654. vRlpPayloads.push_back(rlpPayload1);
  655. for (size_t i = 0; i < packets.size(); i++)
  656. {
  657. auto prot = packets[i].cap();
  658. BOOST_REQUIRE_EQUAL(packets[i].size(), packetTypeRLP.size() + vRlpPayloads[prot].out().size());
  659. BOOST_REQUIRE_EQUAL(sha3(RLP(packets[i].data()).payload()), sha3(vStuff[prot]));
  660. BOOST_REQUIRE_EQUAL(sha3(packets[i].type()), sha3(packetTypeRLP));
  661. }
  662. }
  663. BOOST_AUTO_TEST_CASE(oddSizedMessages)
  664. {
  665. ECDHE localEph;
  666. Secret localNonce = Nonce::get();
  667. ECDHE remoteEph;
  668. Secret remoteNonce = Nonce::get();
  669. bytes ackCipher{0};
  670. bytes authCipher{1};
  671. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  672. auto dequeLen = 1024;
  673. h256 h = sha3("pseudo-random");
  674. vector<bytes> packetsOut;
  675. size_t totalMessages = 2;
  676. for (unsigned i = 0; i < totalMessages; i++)
  677. {
  678. h = sha3(h);
  679. packetsOut.push_back(h.asBytes());
  680. }
  681. packetsOut.front().resize(256);
  682. packetsOut.back().resize(718);
  683. RLPXFrameWriter w(0);
  684. uint8_t packetType = 127;
  685. bytes packetTypeRLP((RLPStream() << packetType).out());
  686. for (auto const& p: packetsOut)
  687. w.enque(packetType, (RLPStream() << p));
  688. deque<bytes> encframes;
  689. size_t n;
  690. n = w.mux(encoder, dequeLen, encframes);
  691. BOOST_REQUIRE_EQUAL(n, 1);
  692. n = w.mux(encoder, dequeLen, encframes);
  693. BOOST_REQUIRE_EQUAL(n, 1);
  694. BOOST_REQUIRE_EQUAL(encframes.size(), 3);
  695. // read and assemble dequed encframes
  696. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  697. vector<RLPXPacket> packets;
  698. RLPXFrameReader r(0);
  699. for (size_t i = 0; i < encframes.size(); i++)
  700. {
  701. bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
  702. bytesRef header = frameWithHeader.cropped(0, h256::size);
  703. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  704. BOOST_REQUIRE(decryptedHeader);
  705. bytesRef frame = frameWithHeader.cropped(h256::size);
  706. RLPXFrameInfo f(header);
  707. for (RLPXPacket& p: r.demux(decoder, f, frame))
  708. packets.push_back(move(p));
  709. }
  710. BOOST_REQUIRE_EQUAL(packets.size(), totalMessages);
  711. BOOST_REQUIRE_EQUAL(sha3(RLP(packets.front().data()).payload()), sha3(packetsOut[0]));
  712. BOOST_REQUIRE_EQUAL(sha3(RLP(packets.back().data()).payload()), sha3(packetsOut[1]));
  713. BOOST_REQUIRE_EQUAL(sha3(packets.front().type()), sha3(packetTypeRLP));
  714. BOOST_REQUIRE_EQUAL(sha3(packets.back().type()), sha3(packetTypeRLP));
  715. }
  716. bytes generatePseudorandomPacket(h256 const& _h)
  717. {
  718. size_t const sz = 16;
  719. size_t msgSizes[sz] = { 1536, 1120, 1024, 800, 512, 352, 256, 160, 128, 96, 64, 64, 32, 32, 32, 3200 };
  720. size_t index = _h.data()[0] % sz;
  721. size_t msgSize = msgSizes[index];
  722. bytes ret;
  723. ret.reserve(msgSize);
  724. while (ret.size() < msgSize)
  725. ret += _h.asBytes();
  726. ret.resize(msgSize);
  727. return ret;
  728. }
  729. BOOST_AUTO_TEST_CASE(pseudorandom)
  730. {
  731. ECDHE localEph;
  732. ECDHE remoteEph;
  733. Secret localNonce = Nonce::get();
  734. Secret remoteNonce = Nonce::get();
  735. bytes ackCipher{0};
  736. bytes authCipher{1};
  737. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  738. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  739. int const dequeLen = 1024;
  740. size_t const numMessages = 1024;
  741. uint8_t const packetType = 127;
  742. bytes const packetTypeRLP((RLPStream() << packetType).out());
  743. h256 h = sha3("some pseudorandom stuff here");
  744. deque<bytes> encframes;
  745. vector<bytes> packetsSent;
  746. vector<RLPXPacket> packetsReceived;
  747. RLPXFrameWriter w(0);
  748. RLPXFrameReader r(0);
  749. for (size_t i = 0; i < numMessages; ++i)
  750. {
  751. bytes pack = generatePseudorandomPacket(h);
  752. packetsSent.push_back(pack);
  753. h = sha3(h);
  754. }
  755. for (size_t i = 0; i < numMessages; ++i)
  756. w.enque(packetType, (RLPStream() << packetsSent[i]));
  757. bool done = false;
  758. while (!done)
  759. {
  760. size_t prev = encframes.size();
  761. size_t num = w.mux(encoder, dequeLen, encframes);
  762. size_t diff = encframes.size() - prev;
  763. done = (!num && !diff);
  764. }
  765. BOOST_REQUIRE_EQUAL(numMessages, packetsSent.size());
  766. for (size_t i = 0; i < encframes.size(); i++)
  767. {
  768. bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
  769. bytesRef header = frameWithHeader.cropped(0, h256::size);
  770. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  771. BOOST_REQUIRE(decryptedHeader);
  772. bytesRef frame = frameWithHeader.cropped(h256::size);
  773. RLPXFrameInfo f(header);
  774. auto px = r.demux(decoder, f, frame);
  775. for (RLPXPacket& p: px)
  776. packetsReceived.push_back(move(p));
  777. }
  778. BOOST_REQUIRE_EQUAL(numMessages, packetsReceived.size());
  779. for (size_t i = 0; i < numMessages; i++)
  780. {
  781. BOOST_REQUIRE(packetsReceived[i].type() == packetTypeRLP);
  782. BOOST_REQUIRE_EQUAL(sha3(RLP(packetsReceived[i].data()).payload()), sha3(packetsSent[i]));
  783. }
  784. }
  785. BOOST_AUTO_TEST_CASE(randomizedMultiProtocol)
  786. {
  787. ECDHE localEph;
  788. ECDHE remoteEph;
  789. Secret localNonce = Nonce::get();
  790. Secret remoteNonce = Nonce::get();
  791. bytes ackCipher{0};
  792. bytes authCipher{1};
  793. RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
  794. RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
  795. int const dequeLen = 1024;
  796. size_t const numMessages = 1024;
  797. size_t const numSubprotocols = 8;
  798. uint8_t const packetType = 127;
  799. bytes const packetTypeRLP((RLPStream() << packetType).out());
  800. h256 h = sha3("pseudorandom string");
  801. deque<bytes> encframes;
  802. vector<bytes> packetsSent;
  803. vector<bytes> packetsSentSorted[numSubprotocols];
  804. vector<bytes> packetsSentShuffled;
  805. vector<RLPXPacket> packetsReceived;
  806. vector<RLPXFrameWriter> writers;
  807. vector<shared_ptr<RLPXFrameReader> > readers;
  808. map<size_t, size_t> msgPerSubprotocolSent;
  809. map<size_t, size_t> msgPerSubprotocolReceived;
  810. // create readers & writers
  811. for (size_t i = 0; i < numSubprotocols; ++i)
  812. {
  813. writers.push_back(RLPXFrameWriter(i));
  814. shared_ptr<RLPXFrameReader> p(new RLPXFrameReader(i));
  815. readers.push_back(p);
  816. }
  817. // create messages
  818. for (size_t i = 0; i < numMessages; ++i)
  819. {
  820. bytes pack = generatePseudorandomPacket(h);
  821. packetsSent.push_back(pack);
  822. h = sha3(h);
  823. }
  824. // enque messages into writers
  825. for (size_t i = 0; i < numMessages; ++i)
  826. {
  827. size_t sub = packetsSent[i][1] % numSubprotocols;
  828. writers[sub].enque(packetType, (RLPStream() << packetsSent[i]));
  829. msgPerSubprotocolSent[sub]++;
  830. packetsSentSorted[sub].push_back(packetsSent[i]);
  831. }
  832. // note the sent messages sequence
  833. for (size_t i = 0; i < numSubprotocols; ++i)
  834. for (bytes const& p: packetsSentSorted[i])
  835. packetsSentShuffled.push_back(p);
  836. // mux
  837. size_t total = 0;
  838. for (size_t i = 0; i < numSubprotocols; ++i)
  839. {
  840. bool done = false;
  841. while (!done)
  842. {
  843. size_t prev = encframes.size();
  844. size_t num = writers[i].mux(encoder, dequeLen, encframes);
  845. size_t diff = encframes.size() - prev;
  846. total += num;
  847. done = (!num && !diff);
  848. }
  849. }
  850. BOOST_REQUIRE_EQUAL(numMessages, total);
  851. // demux
  852. for (size_t i = 0; i < encframes.size(); i++)
  853. {
  854. bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
  855. bytesRef header = frameWithHeader.cropped(0, h256::size);
  856. bool decryptedHeader = decoder.authAndDecryptHeader(header);
  857. BOOST_REQUIRE(decryptedHeader);
  858. bytesRef frame = frameWithHeader.cropped(h256::size);
  859. RLPXFrameInfo f(header);
  860. auto px = readers[f.protocolId]->demux(decoder, f, frame);
  861. for (RLPXPacket& p: px)
  862. {
  863. BOOST_REQUIRE_EQUAL(f.protocolId, p.cap());
  864. packetsReceived.push_back(move(p));
  865. msgPerSubprotocolReceived[f.protocolId]++;
  866. }
  867. }
  868. // check if everything is OK
  869. BOOST_REQUIRE_EQUAL(numMessages, packetsReceived.size());
  870. for (size_t i = 0; i < numSubprotocols; ++i)
  871. BOOST_REQUIRE_EQUAL(msgPerSubprotocolReceived[i], msgPerSubprotocolSent[i]);
  872. for (size_t i = 0; i < numMessages; i++)
  873. {
  874. BOOST_REQUIRE(packetsReceived[i].type() == packetTypeRLP);
  875. BOOST_REQUIRE_EQUAL(sha3(RLP(packetsReceived[i].data()).payload()), sha3(packetsSentShuffled[i]));
  876. }
  877. }
  878. BOOST_AUTO_TEST_SUITE_END()