Fabcoin Core  0.16.2
P2P Digital Currency
rlpx.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
23 #include <libdevcore/Guards.h>
24 #include <boost/asio.hpp>
25 #include <boost/test/unit_test.hpp>
26 #include <cryptopp/aes.h>
27 #include <cryptopp/hmac.h>
28 #include <cryptopp/keccak.h>
29 #include <cryptopp/modes.h>
30 #include <cryptopp/sha.h>
31 #include <libdevcore/Common.h>
32 #include <libdevcore/RLP.h>
33 #include <libdevcore/Log.h>
34 #include <libdevcore/SHA3.h>
35 #include <libdevcrypto/ECDHE.h>
36 #include <libdevcrypto/CryptoPP.h>
37 #include <libp2p/RLPxHandshake.h>
38 #include <libp2p/RLPXFrameWriter.h>
39 #include <libp2p/RLPXFrameReader.h>
41 
42 using namespace std;
43 using namespace dev;
44 using namespace dev::crypto;
45 using namespace dev::p2p;
46 using namespace dev::test;
47 using namespace CryptoPP;
48 
50  RLPXTestFixture() : s_secp256k1(Secp256k1PP::get()) {}
52 
54 };
56 
57 BOOST_AUTO_TEST_CASE(test_secrets_cpp_vectors)
58 {
59  KeyPair init(Secret(sha3("initiator")));
60  KeyPair initR(Secret(sha3("initiator-random")));
61  h256 initNonce(sha3("initiator-nonce"));
62 
63  KeyPair recv(Secret(sha3("remote-recv")));
64  KeyPair recvR(Secret(sha3("remote-recv-random")));
65  h256 recvNonce(sha3("remote-recv-nonce"));
66 
67  bytes authCipher(fromHex(""));
68  bytes ackCipher(fromHex(""));
69 
70  CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameEnc;
71  CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameDec;
72  CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_macEnc;
73  CryptoPP::Keccak_256 m_egressMac;
74  CryptoPP::Keccak_256 m_ingressMac;
75 
76  // when originated is true, agreement is with init secrets
77  // when originated is true, remoteNonce = recvNonce
78  // when originated is true, nonce = initNonce
79  bool originated = true;
80  auto remoteNonce = recvNonce;
81  auto nonce = initNonce;
82  bytes keyMaterialBytes(64);
83  bytesRef keyMaterial(&keyMaterialBytes);
84 
85  // shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
86  Secret ephemeralShared;
87  ecdh::agree(initR.secret(), recvR.pub(), ephemeralShared);
88  Secret expected(fromHex("20d82c1092f351dc217bd66fa183e801234af14ead40423b6ee25112201c6e5a"));
89  BOOST_REQUIRE(expected == ephemeralShared);
90 
91  ephemeralShared.ref().copyTo(keyMaterial.cropped(0, h256::size));
92  h512 nonceMaterial;
93  h256 const& leftNonce = originated ? remoteNonce : nonce;
94  h256 const& rightNonce = originated ? nonce : remoteNonce;
95  leftNonce.ref().copyTo(nonceMaterial.ref().cropped(0, h256::size));
96  rightNonce.ref().copyTo(nonceMaterial.ref().cropped(h256::size, h256::size));
97  auto outRef(keyMaterial.cropped(h256::size, h256::size));
98  sha3(nonceMaterial.ref(), outRef); // output h(nonces)
99 
100  // test that keyMaterial = ecdhe-shared-secret || sha3(nonce || initiator-nonce)
101  {
102  BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
103 
104  Keccak_256 ctx;
105  ctx.Update(leftNonce.data(), h256::size);
106  ctx.Update(rightNonce.data(), h256::size);
107  bytes expected(32);
108  ctx.Final(expected.data());
109  bytes given(32);
110  outRef.copyTo(&given);
111  BOOST_REQUIRE(expected == given);
112  }
113  bytes preImage(keyMaterialBytes);
114 
115  // shared-secret <- sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
116  // keyMaterial = ecdhe-shared-secret || shared-secret
117  sha3(keyMaterial, outRef);
118  bytes sharedSecret(32);
119  outRef.copyTo(&sharedSecret);
120  BOOST_REQUIRE(sharedSecret == fromHex("b65319ce56e00f3be75c4d0da92b5957d5583ca25eeeedac8e29b6dfc8b1ddf7"));
121 
122  // test that keyMaterial = ecdhe-shared-secret || shared-secret
123  {
124  BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
125 
126  Keccak_256 ctx;
127  ctx.Update(preImage.data(), preImage.size());
128  bytes expected(32);
129  ctx.Final(expected.data());
130  bytes test(32);
131  outRef.copyTo(&test);
132  BOOST_REQUIRE(expected == test);
133  }
134 
135  // token: sha3(outRef)
136  bytes token(32);
137  sha3(outRef, bytesRef(&token));
138  BOOST_REQUIRE(token == fromHex("db41fe0180f372983cf19fca7ee890f7fb5481079d44683d2c027be9e71bbca2"));
139 
140  // aes-secret = sha3(ecdhe-shared-secret || shared-secret)
141  sha3(keyMaterial, outRef); // output aes-secret
142  bytes aesSecret(32);
143  outRef.copyTo(&aesSecret);
144  BOOST_REQUIRE(aesSecret == fromHex("12347b4784bcb4e74b84637940482852fe25d78e328cf5c6f7a396bf96cc20bb"));
145  m_frameEnc.SetKeyWithIV(outRef.data(), h128::size, h128().data());
146  m_frameDec.SetKeyWithIV(outRef.data(), h128::size, h128().data());
147 
148  // mac-secret = sha3(ecdhe-shared-secret || aes-secret)
149  sha3(keyMaterial, outRef); // output mac-secret
150  bytes macSecret(32);
151  outRef.copyTo(&macSecret);
152  BOOST_REQUIRE(macSecret == fromHex("2ec149072353d54437422837c886b0538a9206e6c559f6b4a55f65a866867723"));
153  m_macEnc.SetKey(outRef.data(), h128::size);
154 
155  // Initiator egress-mac: sha3(mac-secret^recipient-nonce || auth-sent-init)
156  // ingress-mac: sha3(mac-secret^initiator-nonce || auth-recvd-ack)
157  // Recipient egress-mac: sha3(mac-secret^initiator-nonce || auth-sent-ack)
158  // ingress-mac: sha3(mac-secret^recipient-nonce || auth-recvd-init)
159 
160  (*(h256*)outRef.data() ^ remoteNonce).ref().copyTo(keyMaterial);
161  bytes const& egressCipher = originated ? authCipher : ackCipher;
162  keyMaterialBytes.resize(h256::size + egressCipher.size());
163  keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
164  bytesConstRef(&egressCipher).copyTo(keyMaterial.cropped(h256::size, egressCipher.size()));
165  m_egressMac.Update(keyMaterial.data(), keyMaterial.size());
166 
167  {
168  bytes egressMac;
169  Keccak_256 h(m_egressMac);
170  bytes digest(16);
171  h.TruncatedFinal(digest.data(), 16);
172  BOOST_REQUIRE(digest == fromHex("23e5e8efb6e3765ecae1fca9160b18df"));
173  }
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  {
184  bytes ingressMac;
185  Keccak_256 h(m_ingressMac);
186  bytes digest(16);
187  h.TruncatedFinal(digest.data(), 16);
188  BOOST_REQUIRE(digest == fromHex("ceed64135852064cbdde86e7ea05e8f5"));
189  }
190 }
191 
192 BOOST_AUTO_TEST_CASE(test_secrets_from_go)
193 {
194  KeyPair init(Secret(fromHex("0x5e173f6ac3c669587538e7727cf19b782a4f2fda07c1eaa662c593e5e85e3051")));
195  KeyPair initR(Secret(fromHex("0x19c2185f4f40634926ebed3af09070ca9e029f2edd5fae6253074896205f5f6c")));
196  h256 initNonce(fromHex("0xcd26fecb93657d1cd9e9eaf4f8be720b56dd1d39f190c4e1c6b7ec66f077bb11"));
197 
198  KeyPair recv(Secret(fromHex("0xc45f950382d542169ea207959ee0220ec1491755abe405cd7498d6b16adb6df8")));
199  KeyPair recvR(Secret(fromHex("0xd25688cf0ab10afa1a0e2dba7853ed5f1e5bf1c631757ed4e103b593ff3f5620")));
200  h256 recvNonce(fromHex("0xf37ec61d84cea03dcc5e8385db93248584e8af4b4d1c832d8c7453c0089687a7"));
201 
202  bytes authCipher(fromHex("0x04a0274c5951e32132e7f088c9bdfdc76c9d91f0dc6078e848f8e3361193dbdc43b94351ea3d89e4ff33ddcefbc80070498824857f499656c4f79bbd97b6c51a514251d69fd1785ef8764bd1d262a883f780964cce6a14ff206daf1206aa073a2d35ce2697ebf3514225bef186631b2fd2316a4b7bcdefec8d75a1025ba2c5404a34e7795e1dd4bc01c6113ece07b0df13b69d3ba654a36e35e69ff9d482d88d2f0228e7d96fe11dccbb465a1831c7d4ad3a026924b182fc2bdfe016a6944312021da5cc459713b13b86a686cf34d6fe6615020e4acf26bf0d5b7579ba813e7723eb95b3cef9942f01a58bd61baee7c9bdd438956b426a4ffe238e61746a8c93d5e10680617c82e48d706ac4953f5e1c4c4f7d013c87d34a06626f498f34576dc017fdd3d581e83cfd26cf125b6d2bda1f1d56"));
203  bytes ackCipher(fromHex("0x049934a7b2d7f9af8fd9db941d9da281ac9381b5740e1f64f7092f3588d4f87f5ce55191a6653e5e80c1c5dd538169aa123e70dc6ffc5af1827e546c0e958e42dad355bcc1fcb9cdf2cf47ff524d2ad98cbf275e661bf4cf00960e74b5956b799771334f426df007350b46049adb21a6e78ab1408d5e6ccde6fb5e69f0f4c92bb9c725c02f99fa72b9cdc8dd53cff089e0e73317f61cc5abf6152513cb7d833f09d2851603919bf0fbe44d79a09245c6e8338eb502083dc84b846f2fee1cc310d2cc8b1b9334728f97220bb799376233e113"));
204 
205  bytes authPlainExpected(fromHex("0x884c36f7ae6b406637c1f61b2f57e1d2cab813d24c6559aaf843c3f48962f32f46662c066d39669b7b2e3ba14781477417600e7728399278b1b5d801a519aa570034fdb5419558137e0d44cd13d319afe5629eeccb47fd9dfe55cc6089426e46cc762dd8a0636e07a54b31169eba0c7a20a1ac1ef68596f1f283b5c676bae4064abfcce24799d09f67e392632d3ffdc12e3d6430dcb0ea19c318343ffa7aae74d4cd26fecb93657d1cd9e9eaf4f8be720b56dd1d39f190c4e1c6b7ec66f077bb1100"));
206  bytes ackPlainExpected(fromHex("0x802b052f8b066640bba94a4fc39d63815c377fced6fcb84d27f791c9921ddf3e9bf0108e298f490812847109cbd778fae393e80323fd643209841a3b7f110397f37ec61d84cea03dcc5e8385db93248584e8af4b4d1c832d8c7453c0089687a700"));
207 
208  bytes authPlain = authCipher;
209  BOOST_REQUIRE(s_secp256k1->decryptECIES(recv.secret(), authPlain));
210  bytes ackPlain = ackCipher;
211  BOOST_REQUIRE(s_secp256k1->decryptECIES(init.secret(), ackPlain));
212 
213  CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameEnc;
214  CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_frameDec;
215  CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_macEnc;
216  CryptoPP::Keccak_256 m_egressMac;
217  CryptoPP::Keccak_256 m_ingressMac;
218 
219  // when originated is true, agreement is with init secrets
220  // when originated is true, remoteNonce = recvNonce
221  // when originated is true, nonce = initNonce
222  bool originated = true;
223  auto remoteNonce = recvNonce;
224  auto nonce = initNonce;
225  bytes keyMaterialBytes(64);
226  bytesRef keyMaterial(&keyMaterialBytes);
227 
228  // shared-secret = sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
229  Secret ephemeralShared;
230  ecdh::agree(initR.secret(), recvR.pub(), ephemeralShared);
231  Secret expected(fromHex("0xe3f407f83fc012470c26a93fdff534100f2c6f736439ce0ca90e9914f7d1c381"));
232  BOOST_REQUIRE(expected == ephemeralShared);
233 
234  ephemeralShared.ref().copyTo(keyMaterial.cropped(0, h256::size));
235  h512 nonceMaterial;
236  h256 const& leftNonce = originated ? remoteNonce : nonce;
237  h256 const& rightNonce = originated ? nonce : remoteNonce;
238  leftNonce.ref().copyTo(nonceMaterial.ref().cropped(0, h256::size));
239  rightNonce.ref().copyTo(nonceMaterial.ref().cropped(h256::size, h256::size));
240  auto outRef(keyMaterial.cropped(h256::size, h256::size));
241  sha3(nonceMaterial.ref(), outRef); // output h(nonces)
242 
243  // test that keyMaterial = ecdhe-shared-secret || sha3(nonce || initiator-nonce)
244  {
245  BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
246 
247  Keccak_256 ctx;
248  ctx.Update(leftNonce.data(), h256::size);
249  ctx.Update(rightNonce.data(), h256::size);
250  bytes expected(32);
251  ctx.Final(expected.data());
252  bytes given(32);
253  outRef.copyTo(&given);
254  BOOST_REQUIRE(expected == given);
255  }
256  bytes preImage(keyMaterialBytes);
257 
258  // shared-secret <- sha3(ecdhe-shared-secret || sha3(nonce || initiator-nonce))
259  // keyMaterial = ecdhe-shared-secret || shared-secret
260  sha3(keyMaterial, outRef);
261 
262  // test that keyMaterial = ecdhe-shared-secret || shared-secret
263  {
264  BOOST_REQUIRE(ephemeralShared == *(Secret*)keyMaterialBytes.data());
265 
266  Keccak_256 ctx;
267  ctx.Update(preImage.data(), preImage.size());
268  bytes expected(32);
269  ctx.Final(expected.data());
270  bytes test(32);
271  outRef.copyTo(&test);
272  BOOST_REQUIRE(expected == test);
273  }
274 
275  // token: sha3(outRef)
276  bytes token(32);
277  sha3(outRef, bytesRef(&token));
278  BOOST_REQUIRE(token == fromHex("0x3f9ec2592d1554852b1f54d228f042ed0a9310ea86d038dc2b401ba8cd7fdac4"));
279 
280  // aes-secret = sha3(ecdhe-shared-secret || shared-secret)
281  sha3(keyMaterial, outRef); // output aes-secret
282  bytes aesSecret(32);
283  outRef.copyTo(&aesSecret);
284  BOOST_REQUIRE(aesSecret == fromHex("0xc0458fa97a5230830e05f4f20b7c755c1d4e54b1ce5cf43260bb191eef4e418d"));
285  m_frameEnc.SetKeyWithIV(outRef.data(), h128::size, h128().data());
286  m_frameDec.SetKeyWithIV(outRef.data(), h128::size, h128().data());
287 
288  // mac-secret = sha3(ecdhe-shared-secret || aes-secret)
289  sha3(keyMaterial, outRef); // output mac-secret
290  bytes macSecret(32);
291  outRef.copyTo(&macSecret);
292  BOOST_REQUIRE(macSecret == fromHex("0x48c938884d5067a1598272fcddaa4b833cd5e7d92e8228c0ecdfabbe68aef7f1"));
293  m_macEnc.SetKey(outRef.data(), h256::size);
294 
295  // Initiator egress-mac: sha3(mac-secret^recipient-nonce || auth-sent-init)
296  // ingress-mac: sha3(mac-secret^initiator-nonce || auth-recvd-ack)
297  // Recipient egress-mac: sha3(mac-secret^initiator-nonce || auth-sent-ack)
298  // ingress-mac: sha3(mac-secret^recipient-nonce || auth-recvd-init)
299 
300  (*(h256*)outRef.data() ^ remoteNonce).ref().copyTo(keyMaterial);
301  bytes const& egressCipher = originated ? authCipher : ackCipher;
302  keyMaterialBytes.resize(h256::size + egressCipher.size());
303  keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
304  bytesConstRef(&egressCipher).copyTo(keyMaterial.cropped(h256::size, egressCipher.size()));
305  m_egressMac.Update(keyMaterialBytes.data(), keyMaterialBytes.size());
306 
307  {
308  bytes egressMac;
309  Keccak_256 h(m_egressMac);
310  bytes digest(32);
311  h.Final(digest.data());
312  BOOST_REQUIRE(digest == fromHex("0x09771e93b1a6109e97074cbe2d2b0cf3d3878efafe68f53c41bb60c0ec49097e"));
313  }
314 
315  // recover mac-secret by re-xoring remoteNonce
316  bytes recoverMacSecretTest(32);
317  (*(h256*)keyMaterial.data() ^ remoteNonce).ref().copyTo(&recoverMacSecretTest);
318  BOOST_REQUIRE(recoverMacSecretTest == macSecret);
319 
320  (*(h256*)keyMaterial.data() ^ remoteNonce ^ nonce).ref().copyTo(keyMaterial);
321  bytes const& ingressCipher = originated ? ackCipher : authCipher;
322  keyMaterialBytes.resize(h256::size + ingressCipher.size());
323  keyMaterial.retarget(keyMaterialBytes.data(), keyMaterialBytes.size());
324  bytesConstRef(&ingressCipher).copyTo(keyMaterial.cropped(h256::size, ingressCipher.size()));
325  m_ingressMac.Update(keyMaterial.data(), keyMaterial.size());
326 
327  {
328  bytes ingressMac;
329  Keccak_256 h(m_ingressMac);
330  bytes digest(32);
331  h.Final(digest.data());
332  BOOST_CHECK(digest == fromHex("0x75823d96e23136c89666ee025fb21a432be906512b3dd4a3049e898adb433847"));
333  }
334 
335  bytes initHello(fromHex("6ef23fcf1cec7312df623f9ae701e63b550cdb8517fefd8dd398fc2acd1d935e6e0434a2b96769078477637347b7b01924fff9ff1c06df2f804df3b0402bbb9f87365b3c6856b45e1e2b6470986813c3816a71bff9d69dd297a5dbd935ab578f6e5d7e93e4506a44f307c332d95e8a4b102585fd8ef9fc9e3e055537a5cec2e9"));
336 
337  bytes recvHello(fromHex("6ef23fcf1cec7312df623f9ae701e63be36a1cdd1b19179146019984f3625d4a6e0434a2b96769050577657247b7b02bc6c314470eca7e3ef650b98c83e9d7dd4830b3f718ff562349aead2530a8d28a8484604f92e5fced2c6183f304344ab0e7c301a0c05559f4c25db65e36820b4b909a226171a60ac6cb7beea09376d6d8"));
338 
340  {
341  Keccak_256 egressmac(m_egressMac);
342  Keccak_256 prevDigest(egressmac);
343  h128 prevDigestOut;
344  prevDigest.TruncatedFinal(prevDigestOut.data(), h128::size);
345  h128 encDigest;
346  m_macEnc.ProcessData(encDigest.data(), prevDigestOut.data(), h128::size);
347  encDigest ^= *(h128*)initHello.data();
348  egressmac.Update(encDigest.data(), h128::size);
349  egressmac.TruncatedFinal(encDigest.data(), h128::size);
350 
351  bytes provided(16);
352  bytesConstRef(&initHello).cropped(16, 16).copyTo(bytesRef(&provided));
353  BOOST_REQUIRE(*(h128*)encDigest.data() == *(h128*)provided.data());
354  }
355 
356  {
357  Keccak_256 ingressmac(m_ingressMac);
358  Keccak_256 prevDigest(ingressmac);
359  h128 prevDigestOut;
360  prevDigest.TruncatedFinal(prevDigestOut.data(), h128::size);
361  h128 encDigest;
362  m_macEnc.ProcessData(encDigest.data(), prevDigestOut.data(), h128::size);
363  encDigest ^= *(h128*)recvHello.data();
364  ingressmac.Update(encDigest.data(), h128::size);
365  ingressmac.TruncatedFinal(encDigest.data(), h128::size);
366 
367  bytes provided(16);
368  bytesConstRef(&recvHello).cropped(16, 16).copyTo(bytesRef(&provided));
369  BOOST_REQUIRE(*(h128*)encDigest.data() == *(h128*)provided.data());
370  }
371 
372  // test decrypt of frame headers for recvHello
373  bytes plaintext(16);
374  m_frameDec.ProcessData(plaintext.data(), recvHello.data(), h128::size);
375 
376 }
377 
378 #if defined(__GNUC__)
379  #pragma GCC diagnostic pop
380 #endif // defined(__GNUC__)
381 
382 BOOST_AUTO_TEST_CASE(ecies_interop_test_primitives)
383 {
384  CryptoPP::SHA256 sha256ctx;
385  bytes emptyExpected(fromHex("0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
386  bytes empty;
387  sha256ctx.Update(empty.data(), 0);
388  bytes emptyTestOut(32);
389  sha256ctx.Final(emptyTestOut.data());
390  BOOST_REQUIRE(emptyExpected == emptyTestOut);
391 
392  bytes hash1Expected(fromHex("0x8949b278bbafb8da1aaa18cb724175c5952280f74be5d29ab4b37d1b45c84b08"));
393  bytes hash1input(fromHex("0x55a53b55afb12affff3c"));
394  sha256ctx.Update(hash1input.data(), hash1input.size());
395  bytes hash1Out(32);
396  sha256ctx.Final(hash1Out.data());
397  BOOST_REQUIRE(hash1Out == hash1Expected);
398 
399  h128 hmack(fromHex("0x07a4b6dfa06369a570f2dcba2f11a18f"));
400  CryptoPP::HMAC<SHA256> hmacctx(hmack.data(), h128::size);
401  bytes input(fromHex("0x4dcb92ed4fc67fe86832"));
402  hmacctx.Update(input.data(), input.size());
403  bytes hmacExpected(fromHex("0xc90b62b1a673b47df8e395e671a68bfa68070d6e2ef039598bb829398b89b9a9"));
404  bytes hmacOut(hmacExpected.size());
405  hmacctx.Final(hmacOut.data());
406  BOOST_REQUIRE(hmacExpected == hmacOut);
407 
408  // go messageTag
409  bytes tagSecret(fromHex("0xaf6623e52208c596e17c72cea6f1cb09"));
410  bytes tagInput(fromHex("0x3461282bcedace970df2"));
411  bytes tagExpected(fromHex("0xb3ce623bce08d5793677ba9441b22bb34d3e8a7de964206d26589df3e8eb5183"));
412  CryptoPP::HMAC<SHA256> hmactagctx(tagSecret.data(), tagSecret.size());
413  hmactagctx.Update(tagInput.data(), tagInput.size());
414  h256 mac;
415  hmactagctx.Final(mac.data());
416  BOOST_REQUIRE(mac.asBytes() == tagExpected);
417 
418  Secret input1(fromHex("0x0de72f1223915fa8b8bf45dffef67aef8d89792d116eb61c9a1eb02c422a4663"));
419  bytes expect1(fromHex("0x1d0c446f9899a3426f2b89a8cb75c14b"));
420  bytes test1;
421  test1 = s_secp256k1->eciesKDF(input1, bytes(), 16);
422  BOOST_REQUIRE(test1 == expect1);
423 
424  Secret kdfInput2(fromHex("0x961c065873443014e0371f1ed656c586c6730bf927415757f389d92acf8268df"));
425  bytes kdfExpect2(fromHex("0x4050c52e6d9c08755e5a818ac66fabe478b825b1836fd5efc4d44e40d04dabcc"));
426  bytes kdfTest2;
427  kdfTest2 = s_secp256k1->eciesKDF(kdfInput2, bytes(), 32);
428  BOOST_REQUIRE(kdfTest2 == kdfExpect2);
429 
430  KeyPair k(Secret(fromHex("0x332143e9629eedff7d142d741f896258f5a1bfab54dab2121d3ec5000093d74b")));
431  Public p(fromHex("0xf0d2b97981bd0d415a843b5dfe8ab77a30300daab3658c578f2340308a2da1a07f0821367332598b6aa4e180a41e92f4ebbae3518da847f0b1c0bbfe20bcf4e1"));
432  Secret agreeExpected(fromHex("0xee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08"));
433  Secret agreeTest;
434  ecdh::agree(k.secret(), p, agreeTest);
435  BOOST_REQUIRE(agreeExpected == agreeTest);
436 
437  KeyPair kmK(Secret(fromHex("0x57baf2c62005ddec64c357d96183ebc90bf9100583280e848aa31d683cad73cb")));
438  bytes kmCipher(fromHex("0x04ff2c874d0a47917c84eea0b2a4141ca95233720b5c70f81a8415bae1dc7b746b61df7558811c1d6054333907333ef9bb0cc2fbf8b34abb9730d14e0140f4553f4b15d705120af46cf653a1dc5b95b312cf8444714f95a4f7a0425b67fc064d18f4d0a528761565ca02d97faffdac23de10"));
439  bytes kmPlain = kmCipher;
440  bytes kmExpected(asBytes("a"));
441  BOOST_REQUIRE(s_secp256k1->decryptECIES(kmK.secret(), kmPlain));
442  BOOST_REQUIRE(kmExpected == kmPlain);
443 
444  KeyPair kenc(Secret(fromHex("0x472413e97f1fd58d84e28a559479e6b6902d2e8a0cee672ef38a3a35d263886b")));
445  Public penc(Public(fromHex("0x7a2aa2951282279dc1171549a7112b07c38c0d97c0fe2c0ae6c4588ba15be74a04efc4f7da443f6d61f68a9279bc82b73e0cc8d090048e9f87e838ae65dd8d4c")));
446  BOOST_REQUIRE(penc == kenc.pub());
447 
448  bytes cipher1(fromHex("0x046f647e1bd8a5cd1446d31513bac233e18bdc28ec0e59d46de453137a72599533f1e97c98154343420d5f16e171e5107999a7c7f1a6e26f57bcb0d2280655d08fb148d36f1d4b28642d3bb4a136f0e33e3dd2e3cffe4b45a03fb7c5b5ea5e65617250fdc89e1a315563c20504b9d3a72555"));
449  bytes plainTest1 = cipher1;
450  bytes expectedPlain1 = asBytes("a");
451  BOOST_REQUIRE(s_secp256k1->decryptECIES(kenc.secret(), plainTest1));
452  BOOST_REQUIRE(plainTest1 == expectedPlain1);
453 
454  bytes cipher2(fromHex("0x0443c24d6ccef3ad095140760bb143078b3880557a06392f17c5e368502d79532bc18903d59ced4bbe858e870610ab0d5f8b7963dd5c9c4cf81128d10efd7c7aa80091563c273e996578403694673581829e25a865191bdc9954db14285b56eb0043b6288172e0d003c10f42fe413222e273d1d4340c38a2d8344d7aadcbc846ee"));
455  bytes plainTest2 = cipher2;
456  bytes expectedPlain2 = asBytes("aaaaaaaaaaaaaaaa");
457  BOOST_REQUIRE(s_secp256k1->decryptECIES(kenc.secret(), plainTest2));
458  BOOST_REQUIRE(plainTest2 == expectedPlain2);
459 
460  bytes cipher3(fromHex("0x04c4e40c86bb5324e017e598c6d48c19362ae527af8ab21b077284a4656c8735e62d73fb3d740acefbec30ca4c024739a1fcdff69ecaf03301eebf156eb5f17cca6f9d7a7e214a1f3f6e34d1ee0ec00ce0ef7d2b242fbfec0f276e17941f9f1bfbe26de10a15a6fac3cda039904ddd1d7e06e7b96b4878f61860e47f0b84c8ceb64f6a900ff23844f4359ae49b44154980a626d3c73226c19e"));
461  bytes plainTest3 = cipher3;
462  bytes expectedPlain3 = asBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
463  BOOST_REQUIRE(s_secp256k1->decryptECIES(kenc.secret(), plainTest3));
464  BOOST_REQUIRE(plainTest3 == expectedPlain3);
465 }
466 
467 BOOST_AUTO_TEST_CASE(segmentedPacketFlush)
468 {
469  ECDHE localEph;
470  Secret localNonce = Nonce::get();
471  ECDHE remoteEph;
472  Secret remoteNonce = Nonce::get();
473  bytes ackCipher{0};
474  bytes authCipher{1};
475  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
476 
480 
481  // 64-byte payload minus 3 bytes for packet-type and RLP overhead.
482  // Note: mux() is called with RLPXFrameWriter::MinFrameDequeLength
483  // which is equal to 64byte, however, after overhead this means
484  // there are only 16 bytes of payload which will be dequed.
485  auto dequeLen = 16;
486  bytes stuff = sha3("A").asBytes();
487  bytes payload;
488  payload += stuff;
489  payload += stuff;
490  payload.resize(payload.size() - 3 /* packet-type, rlp-overhead */);
491  BOOST_REQUIRE_EQUAL(61, payload.size());
492 
493  auto drains = (payload.size() + 3) / dequeLen;
494  BOOST_REQUIRE_EQUAL(4, drains);
495 
496  RLPXFrameWriter w(0);
497  RLPStream rlpPayload(RLPStream() << payload);
498  uint8_t packetType = 0;
499  bytes packetTypeRLP = (RLPStream() << packetType).out();
500  w.enque(packetType, rlpPayload);
501  deque<bytes> encframes;
502  for (unsigned i = 1; i < drains; i++)
503  {
504  auto n = w.mux(encoder, RLPXFrameWriter::MinFrameDequeLength, encframes);
505  BOOST_REQUIRE_EQUAL(0, n);
506  BOOST_REQUIRE_EQUAL(encframes.size(), i);
507  }
508  BOOST_REQUIRE_EQUAL(1, w.mux(encoder, RLPXFrameWriter::MinFrameDequeLength, encframes));
509  BOOST_REQUIRE_EQUAL(encframes.size(), drains);
510  BOOST_REQUIRE_EQUAL(0, w.mux(encoder, RLPXFrameWriter::MinFrameDequeLength, encframes));
511  BOOST_REQUIRE_EQUAL(encframes.size(), drains);
512 
513  // we should now have a bunch of ciphertext in encframes
514  BOOST_REQUIRE(encframes.size() == drains);
515  for (auto const& c: encframes)
516  {
517  BOOST_REQUIRE_EQUAL(c.size(), RLPXFrameWriter::MinFrameDequeLength);
518  }
519 
520  // read and assemble dequed encframes
521  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
522  vector<RLPXPacket> packets;
523  RLPXFrameReader r(0);
524  for (size_t i = 0; i < encframes.size(); i++)
525  {
526  bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
527  bytesRef header = frameWithHeader.cropped(0, h256::size);
528  bool decryptedHeader = decoder.authAndDecryptHeader(header);
529  BOOST_REQUIRE(decryptedHeader);
530  bytesRef frame = frameWithHeader.cropped(h256::size);
531  RLPXFrameInfo f(header);
532  for (RLPXPacket& p: r.demux(decoder, f, frame))
533  packets.push_back(move(p));
534  }
535  BOOST_REQUIRE_EQUAL(packets.size(), 1);
536  BOOST_REQUIRE_EQUAL(packets.front().size(), packetTypeRLP.size() + rlpPayload.out().size());
537  BOOST_REQUIRE_EQUAL(sha3(RLP(packets.front().data()).payload()), sha3(payload));
538  BOOST_REQUIRE_EQUAL(sha3(packets.front().type()), sha3(packetTypeRLP));
539 }
540 
541 BOOST_AUTO_TEST_CASE(coalescedPacketsPadded)
542 {
543  ECDHE localEph;
544  Secret localNonce = Nonce::get();
545  ECDHE remoteEph;
546  Secret remoteNonce = Nonce::get();
547  bytes ackCipher{0};
548  bytes authCipher{1};
549  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
550 
553  auto dequeLen = 1024; // sufficient enough for all packets
554  bytes stuff = sha3("A").asBytes();
555  deque<bytes> packetsOut;
556  for (unsigned i = 0; i < 4; i++)
557  packetsOut.push_back(stuff);
558 
559  RLPXFrameWriter w(0);
560  uint8_t packetType = 127;
561  bytes packetTypeRLP((RLPStream() << packetType).out());
562  for (auto const& p: packetsOut)
563  w.enque(packetType, (RLPStream() << p));
564 
565  deque<bytes> encframes;
566  BOOST_REQUIRE_EQUAL(4, w.mux(encoder, dequeLen, encframes));
567  BOOST_REQUIRE_EQUAL(0, w.mux(encoder, dequeLen, encframes));
568  BOOST_REQUIRE_EQUAL(1, encframes.size());
569  auto expectedFrameSize = RLPXFrameWriter::EmptyFrameLength + packetsOut.size() * (/*packet-type*/ 1 + h256::size + /*rlp-prefix*/ 1);
570  expectedFrameSize += ((16 - (expectedFrameSize % 16)) % 16);
571  BOOST_REQUIRE_EQUAL(expectedFrameSize, encframes[0].size());
572 
573  // read and assemble dequed encframes
574  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
575  vector<RLPXPacket> packets;
576  RLPXFrameReader r(0);
577  bytesRef frameWithHeader(encframes[0].data(), encframes[0].size());
578  bytesRef header = frameWithHeader.cropped(0, h256::size);
579  bool decryptedHeader = decoder.authAndDecryptHeader(header);
580  BOOST_REQUIRE(decryptedHeader);
581  bytesRef frame = frameWithHeader.cropped(h256::size);
582  RLPXFrameInfo f(header);
583  BOOST_REQUIRE_EQUAL(f.multiFrame, false);
584  for (RLPXPacket& p: r.demux(decoder, f, frame))
585  packets.push_back(move(p));
586 
587  RLPStream rlpPayload;
588  rlpPayload << stuff;
589  BOOST_REQUIRE_EQUAL(packets.size(), 4);
590  while (!packets.empty())
591  {
592  BOOST_REQUIRE_EQUAL(packets.back().size(), packetTypeRLP.size() + rlpPayload.out().size());
593  BOOST_REQUIRE_EQUAL(sha3(RLP(packets.back().data()).payload()), sha3(stuff));
594  BOOST_REQUIRE_EQUAL(sha3(packets.back().type()), sha3(packetTypeRLP));
595  packets.pop_back();
596  }
597 }
598 
599 BOOST_AUTO_TEST_CASE(singleFramePacketFlush)
600 {
601  ECDHE localEph;
602  Secret localNonce = Nonce::get();
603  ECDHE remoteEph;
604  Secret remoteNonce = Nonce::get();
605  bytes ackCipher{0};
606  bytes authCipher{1};
607  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
608 
609  bytes stuff = sha3("A").asBytes();
610  RLPXFrameWriter w(0);
611  uint8_t packetType = 127;
612  bytes packetTypeRLP((RLPStream() << packetType).out());
613  w.enque(packetType, (RLPStream() << stuff));
614 
615  deque<bytes> encframes;
616  auto dequeLen = RLPXFrameWriter::EmptyFrameLength + 34;
617  dequeLen += ((16 - (dequeLen % 16)) % 16);
618  BOOST_REQUIRE_EQUAL(1, w.mux(encoder, dequeLen, encframes));
619  BOOST_REQUIRE_EQUAL(0, w.mux(encoder, dequeLen, encframes));
620  BOOST_REQUIRE_EQUAL(1, encframes.size());
621  BOOST_REQUIRE_EQUAL(dequeLen, encframes[0].size());
622 
623  // read and assemble dequed encframes
624  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
625  vector<RLPXPacket> packets;
626  RLPXFrameReader r(0);
627  bytesRef frameWithHeader(encframes[0].data(), encframes[0].size());
628  bytesRef header = frameWithHeader.cropped(0, h256::size);
629  bool decryptedHeader = decoder.authAndDecryptHeader(header);
630  BOOST_REQUIRE(decryptedHeader);
631  bytesRef frame = frameWithHeader.cropped(h256::size);
632  RLPXFrameInfo f(header);
633  BOOST_REQUIRE_EQUAL(f.multiFrame, false);
634  for (RLPXPacket& p: r.demux(decoder, f, frame))
635  packets.push_back(move(p));
636 
637  RLPStream rlpPayload;
638  rlpPayload << stuff;
639  BOOST_REQUIRE_EQUAL(packets.size(), 1);
640  BOOST_REQUIRE_EQUAL(packets.back().size(), packetTypeRLP.size() + rlpPayload.out().size());
641  BOOST_REQUIRE_EQUAL(sha3(RLP(packets.back().data()).payload()), sha3(stuff));
642  BOOST_REQUIRE_EQUAL(sha3(packets.back().type()), sha3(packetTypeRLP));
643 }
644 
645 BOOST_AUTO_TEST_CASE(multiProtocol)
646 {
648 
649  ECDHE localEph;
650  ECDHE remoteEph;
651  Secret localNonce = Nonce::get();
652  Secret remoteNonce = Nonce::get();
653  bytes ackCipher{0};
654  bytes authCipher{1};
655  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
656 
657  auto dequeLen = 1024; // sufficient enough for all packets
658  bytes stuff0 = sha3("A").asBytes();
659  bytes stuff1 = sha3("B").asBytes();
660  vector<bytes> vStuff;
661  vStuff.push_back(stuff0);
662  vStuff.push_back(stuff1);
663 
664  vector<bytes> packetsOut;
665  packetsOut.push_back(stuff0);
666  packetsOut.push_back(stuff0);
667  packetsOut.push_back(stuff1);
668  packetsOut.push_back(stuff1);
669 
670  std::map<uint16_t, RLPXFrameWriter*> mw;
671  RLPXFrameWriter w0(0);
672  RLPXFrameWriter w1(1);
673  mw[0] = &w0;
674  mw[1] = &w1;
675 
676  uint8_t const packetType = 127;
677  bytes packetTypeRLP((RLPStream() << packetType).out());
678 
679  unsigned i = 0;
680  mw[0]->enque(packetType, (RLPStream() << packetsOut[i++]));
681  mw[0]->enque(packetType, (RLPStream() << packetsOut[i++]));
682  mw[1]->enque(packetType, (RLPStream() << packetsOut[i++]));
683  mw[1]->enque(packetType, (RLPStream() << packetsOut[i++]));
684 
685  deque<bytes> encframes;
686  BOOST_REQUIRE_EQUAL(2, mw[0]->mux(encoder, dequeLen, encframes));
687  BOOST_REQUIRE_EQUAL(2, mw[1]->mux(encoder, dequeLen, encframes));
688  BOOST_REQUIRE_EQUAL(0, mw[0]->mux(encoder, dequeLen, encframes));
689  BOOST_REQUIRE_EQUAL(0, mw[1]->mux(encoder, dequeLen, encframes));
690  BOOST_REQUIRE_EQUAL(2, encframes.size());
691 
692  auto expectedFrameSize = RLPXFrameWriter::EmptyFrameLength
693  + packetsOut.size() * (/*packet-type*/ 1 + h256::size + /*rlp-prefix*/ 1) / 2;
694 
695  expectedFrameSize += ((16 - (expectedFrameSize % 16)) % 16);
696  BOOST_REQUIRE_EQUAL(expectedFrameSize, encframes[0].size());
697 
698  // read and assemble dequed encframes
699  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
700  vector<RLPXPacket> packets;
701  std::map<uint16_t, RLPXFrameReader*> mr;
702  RLPXFrameReader r0(0);
703  RLPXFrameReader r1(1);
704  mr[0] = &r0;
705  mr[1] = &r1;
706 
707  for (size_t i = 0; i < encframes.size(); i++)
708  {
709  bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
710  bytesRef header = frameWithHeader.cropped(0, h256::size);
711  bool decryptedHeader = decoder.authAndDecryptHeader(header);
712  BOOST_REQUIRE(decryptedHeader);
713  bytesRef frame = frameWithHeader.cropped(h256::size);
714  RLPXFrameInfo f(header);
715  BOOST_REQUIRE_EQUAL(f.multiFrame, false);
716  for (RLPXPacket& p: mr[f.protocolId]->demux(decoder, f, frame))
717  {
718  BOOST_REQUIRE_EQUAL(f.protocolId, p.cap());
719  packets.push_back(move(p));
720  }
721  }
722 
723  BOOST_REQUIRE_EQUAL(packets.size(), 4);
724  RLPStream rlpPayload0;
725  RLPStream rlpPayload1;
726  rlpPayload0 << stuff0;
727  rlpPayload1 << stuff1;
728  vector<RLPStream> vRlpPayloads;
729  vRlpPayloads.push_back(rlpPayload0);
730  vRlpPayloads.push_back(rlpPayload1);
731 
732  for (size_t i = 0; i < packets.size(); i++)
733  {
734  auto prot = packets[i].cap();
735  BOOST_REQUIRE_EQUAL(packets[i].size(), packetTypeRLP.size() + vRlpPayloads[prot].out().size());
736  BOOST_REQUIRE_EQUAL(sha3(RLP(packets[i].data()).payload()), sha3(vStuff[prot]));
737  BOOST_REQUIRE_EQUAL(sha3(packets[i].type()), sha3(packetTypeRLP));
738  }
739 }
740 
741 BOOST_AUTO_TEST_CASE(oddSizedMessages)
742 {
743  ECDHE localEph;
744  Secret localNonce = Nonce::get();
745  ECDHE remoteEph;
746  Secret remoteNonce = Nonce::get();
747  bytes ackCipher{0};
748  bytes authCipher{1};
749  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
750 
751  auto dequeLen = 1024;
752  h256 h = sha3("pseudo-random");
753  vector<bytes> packetsOut;
754  size_t totalMessages = 2;
755  for (unsigned i = 0; i < totalMessages; i++)
756  {
757  h = sha3(h);
758  packetsOut.push_back(h.asBytes());
759  }
760 
761  packetsOut.front().resize(256);
762  packetsOut.back().resize(718);
763 
764  RLPXFrameWriter w(0);
765  uint8_t packetType = 127;
766  bytes packetTypeRLP((RLPStream() << packetType).out());
767  for (auto const& p: packetsOut)
768  w.enque(packetType, (RLPStream() << p));
769 
770  deque<bytes> encframes;
771  size_t n;
772  n = w.mux(encoder, dequeLen, encframes);
773  BOOST_REQUIRE_EQUAL(n, 1);
774  n = w.mux(encoder, dequeLen, encframes);
775  BOOST_REQUIRE_EQUAL(n, 1);
776  BOOST_REQUIRE_EQUAL(encframes.size(), 3);
777 
778  // read and assemble dequed encframes
779  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
780  vector<RLPXPacket> packets;
781  RLPXFrameReader r(0);
782  for (size_t i = 0; i < encframes.size(); i++)
783  {
784  bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
785  bytesRef header = frameWithHeader.cropped(0, h256::size);
786  bool decryptedHeader = decoder.authAndDecryptHeader(header);
787  BOOST_REQUIRE(decryptedHeader);
788  bytesRef frame = frameWithHeader.cropped(h256::size);
789  RLPXFrameInfo f(header);
790  for (RLPXPacket& p: r.demux(decoder, f, frame))
791  packets.push_back(move(p));
792  }
793 
794  BOOST_REQUIRE_EQUAL(packets.size(), totalMessages);
795  BOOST_REQUIRE_EQUAL(sha3(RLP(packets.front().data()).payload()), sha3(packetsOut[0]));
796  BOOST_REQUIRE_EQUAL(sha3(RLP(packets.back().data()).payload()), sha3(packetsOut[1]));
797  BOOST_REQUIRE_EQUAL(sha3(packets.front().type()), sha3(packetTypeRLP));
798  BOOST_REQUIRE_EQUAL(sha3(packets.back().type()), sha3(packetTypeRLP));
799 }
800 
802 {
803  size_t const sz = 16;
804  size_t msgSizes[sz] = { 1536, 1120, 1024, 800, 512, 352, 256, 160, 128, 96, 64, 64, 32, 32, 32, 3200 };
805  size_t index = _h.data()[0] % sz;
806  size_t msgSize = msgSizes[index];
807  bytes ret;
808  ret.reserve(msgSize);
809 
810  while (ret.size() < msgSize)
811  ret += _h.asBytes();
812 
813  ret.resize(msgSize);
814  return ret;
815 }
816 
817 BOOST_AUTO_TEST_CASE(pseudorandom)
818 {
819  ECDHE localEph;
820  ECDHE remoteEph;
821  Secret localNonce = Nonce::get();
822  Secret remoteNonce = Nonce::get();
823  bytes ackCipher{0};
824  bytes authCipher{1};
825  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
826  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
827 
828  int const dequeLen = 1024;
829  size_t const numMessages = 1024;
830  uint8_t const packetType = 127;
831  bytes const packetTypeRLP((RLPStream() << packetType).out());
832  h256 h = sha3("some pseudorandom stuff here");
833  deque<bytes> encframes;
834  vector<bytes> packetsSent;
835  vector<RLPXPacket> packetsReceived;
836  RLPXFrameWriter w(0);
837  RLPXFrameReader r(0);
838 
839  for (size_t i = 0; i < numMessages; ++i)
840  {
842  packetsSent.push_back(pack);
843  h = sha3(h);
844  }
845 
846  for (size_t i = 0; i < numMessages; ++i)
847  w.enque(packetType, (RLPStream() << packetsSent[i]));
848 
849  bool done = false;
850  while (!done)
851  {
852  size_t prev = encframes.size();
853  size_t num = w.mux(encoder, dequeLen, encframes);
854  size_t diff = encframes.size() - prev;
855  done = (!num && !diff);
856  }
857 
858  BOOST_REQUIRE_EQUAL(numMessages, packetsSent.size());
859 
860  for (size_t i = 0; i < encframes.size(); i++)
861  {
862  bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
863  bytesRef header = frameWithHeader.cropped(0, h256::size);
864  bool decryptedHeader = decoder.authAndDecryptHeader(header);
865  BOOST_REQUIRE(decryptedHeader);
866  bytesRef frame = frameWithHeader.cropped(h256::size);
867  RLPXFrameInfo f(header);
868  auto px = r.demux(decoder, f, frame);
869  for (RLPXPacket& p: px)
870  packetsReceived.push_back(move(p));
871  }
872 
873  BOOST_REQUIRE_EQUAL(numMessages, packetsReceived.size());
874 
875  for (size_t i = 0; i < numMessages; i++)
876  {
877  BOOST_REQUIRE(packetsReceived[i].type() == packetTypeRLP);
878  BOOST_REQUIRE_EQUAL(sha3(RLP(packetsReceived[i].data()).payload()), sha3(packetsSent[i]));
879  }
880 }
881 
882 BOOST_AUTO_TEST_CASE(randomizedMultiProtocol)
883 {
884  ECDHE localEph;
885  ECDHE remoteEph;
886  Secret localNonce = Nonce::get();
887  Secret remoteNonce = Nonce::get();
888  bytes ackCipher{0};
889  bytes authCipher{1};
890  RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
891  RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
892 
893  int const dequeLen = 1024;
894  size_t const numMessages = 1024;
895  size_t const numSubprotocols = 8;
896  uint8_t const packetType = 127;
897  bytes const packetTypeRLP((RLPStream() << packetType).out());
898  h256 h = sha3("pseudorandom string");
899  deque<bytes> encframes;
900  vector<bytes> packetsSent;
901  vector<bytes> packetsSentSorted[numSubprotocols];
902  vector<bytes> packetsSentShuffled;
903  vector<RLPXPacket> packetsReceived;
904  vector<RLPXFrameWriter> writers;
905  vector<shared_ptr<RLPXFrameReader> > readers;
906  map<size_t, size_t> msgPerSubprotocolSent;
907  map<size_t, size_t> msgPerSubprotocolReceived;
908 
909  // create readers & writers
910  for (size_t i = 0; i < numSubprotocols; ++i)
911  {
912  writers.push_back(RLPXFrameWriter(i));
913  shared_ptr<RLPXFrameReader> p(new RLPXFrameReader(i));
914  readers.push_back(p);
915  }
916 
917  // create messages
918  for (size_t i = 0; i < numMessages; ++i)
919  {
921  packetsSent.push_back(pack);
922  h = sha3(h);
923  }
924 
925  // enque messages into writers
926  for (size_t i = 0; i < numMessages; ++i)
927  {
928  size_t sub = packetsSent[i][1] % numSubprotocols;
929  writers[sub].enque(packetType, (RLPStream() << packetsSent[i]));
930  msgPerSubprotocolSent[sub]++;
931  packetsSentSorted[sub].push_back(packetsSent[i]);
932  }
933 
934  // note the sent messages sequence
935  for (size_t i = 0; i < numSubprotocols; ++i)
936  for (bytes const& p: packetsSentSorted[i])
937  packetsSentShuffled.push_back(p);
938 
939  // mux
940  size_t total = 0;
941  for (size_t i = 0; i < numSubprotocols; ++i)
942  {
943  bool done = false;
944  while (!done)
945  {
946  size_t prev = encframes.size();
947  size_t num = writers[i].mux(encoder, dequeLen, encframes);
948  size_t diff = encframes.size() - prev;
949  total += num;
950  done = (!num && !diff);
951  }
952  }
953 
954  BOOST_REQUIRE_EQUAL(numMessages, total);
955 
956  // demux
957  for (size_t i = 0; i < encframes.size(); i++)
958  {
959  bytesRef frameWithHeader(encframes[i].data(), encframes[i].size());
960  bytesRef header = frameWithHeader.cropped(0, h256::size);
961  bool decryptedHeader = decoder.authAndDecryptHeader(header);
962  BOOST_REQUIRE(decryptedHeader);
963  bytesRef frame = frameWithHeader.cropped(h256::size);
964  RLPXFrameInfo f(header);
965  auto px = readers[f.protocolId]->demux(decoder, f, frame);
966  for (RLPXPacket& p: px)
967  {
968  BOOST_REQUIRE_EQUAL(f.protocolId, p.cap());
969  packetsReceived.push_back(move(p));
970  msgPerSubprotocolReceived[f.protocolId]++;
971  }
972  }
973 
974  // check if everything is OK
975  BOOST_REQUIRE_EQUAL(numMessages, packetsReceived.size());
976 
977  for (size_t i = 0; i < numSubprotocols; ++i)
978  BOOST_REQUIRE_EQUAL(msgPerSubprotocolReceived[i], msgPerSubprotocolSent[i]);
979 
980  for (size_t i = 0; i < numMessages; i++)
981  {
982  BOOST_REQUIRE(packetsReceived[i].type() == packetTypeRLP);
983  BOOST_REQUIRE_EQUAL(sha3(RLP(packetsReceived[i].data()).payload()), sha3(packetsSentShuffled[i]));
984  }
985 }
986 
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
A modifiable reference to an existing object or vector in memory.
Definition: vector_ref.h:20
vector_ref< _T const > ref(_T const &_t)
Definition: vector_ref.h:115
byte * data()
Definition: FixedHash.h:139
byte const * data() const
Definition: FixedHash.h:293
Class file for modes of operation.
CryptoPP secp256k1 algorithms.
Definition: CryptoPP.h:39
#define h(i)
Definition: sha.cpp:736
bytes const & out() const
Read the byte stream.
Definition: RLP.h:433
Simple class that represents a "key pair".
Definition: Common.h:150
Classes for Keccak message digests.
SecureFixedHash< 32 > Secret
Definition: Common.h:35
#define c(i)
std::hash for asio::adress
Definition: Common.h:323
Secret const & secret() const
Definition: Common.h:167
vector_ref< _T > cropped(size_t _begin, size_t _count) const
Definition: vector_ref.h:62
Secp256k1PP * s_secp256k1
Definition: rlpx.cpp:53
std::vector< RLPXPacket > demux(RLPXFrameCoder &_coder, RLPXFrameInfo const &_info, bytesRef _frame)
Processes a single frame returning complete packets.
h512 Public
A public key: 64 bytes.
Definition: Common.h:39
bytes generatePseudorandomPacket(h256 const &_h)
Definition: rlpx.cpp:801
Public pubkey()
Public key sent to remote.
Definition: ECDHE.h:44
void retarget(_T *_d, size_t _s)
Definition: vector_ref.h:65
bytesConstRef ref() const
Definition: FixedHash.h:292
size_t mux(RLPXFrameCoder &_coder, unsigned _size, std::deque< bytes > &o_toWrite)
Returns number of packets framed and outputs frames to o_bytes. Not thread-safe.
#define r1(i)
Classes for HMAC message authentication codes.
bytes fromHex(std::string const &_s, WhenError _throw=WhenError::DontThrow)
Definition: CommonData.cpp:99
Public const & pub() const
Retrieve the public key.
Definition: Common.h:170
vector_ref< byte > bytesRef
Definition: Common.h:76
bytesRef ref()
Definition: FixedHash.h:133
FixedHash< T > const & makeInsecure() const
Definition: FixedHash.h:253
Encapsulation of Frame.
Class file for the AES cipher (Rijndael)
void enque(uint8_t _packetType, RLPStream &_payload, PacketPriority _priority=PriorityLow)
Moves output to queue, to be muxed into frames by mux() when network buffer is ready for writing...
std::vector< byte > bytes
Definition: Common.h:75
vector_ref< byte const > bytesConstRef
Definition: Common.h:77
bytes asBytes(std::string const &_b)
Converts a string to a byte array containing the string&#39;s (byte) data.
Definition: CommonData.h:92
~RLPXTestFixture()
Definition: rlpx.cpp:51
Keccak_Final< 32 > Keccak_256
Definition: keccak.h:96
size_t size() const
Definition: vector_ref.h:55
Classes for SHA-1 and SHA-2 family of message digests.
bytes asBytes() const
Definition: FixedHash.h:145
#define f(x)
Definition: gost.cpp:57
bool const multiFrame
If this frame is part of a sequence.
FixedHash< 16 > h128
Definition: FixedHash.h:342
_T * data() const
Definition: vector_ref.h:51
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
PlatformStyle::TableColorType type
Definition: rpcconsole.cpp:61
RLPX Packet.
Definition: RLPXPacket.h:39
uint8_t const size_t const size
Definition: sha3.h:20
void copyTo(vector_ref< typename std::remove_const< _T >::type > _t) const
Copies the contents of this vector_ref to the contents of _t, up to the max size of _t...
Definition: vector_ref.h:69
N diff(N const &_a, N const &_b)
Definition: Common.h:212
void agree(Secret const &_s, Public const &_r, Secret &o_s)
Definition: Common.cpp:348
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
Keccak-256 message digest.
RLPFrameReader Reads and assembles RLPX frame byte buffers into RLPX packets.
Class for writing to an RLP bytestream.
Definition: RLP.h:383
Derive DH shared secret from EC keypairs.
Definition: ECDHE.h:37
Encoder/decoder transport for RLPx connection established by RLPXHandshake.
BOOST_AUTO_TEST_CASE(test_secrets_cpp_vectors)
Definition: rlpx.cpp:57
uint8_t const * data
Definition: sha3.h:19
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
RLPXTestFixture()
Definition: rlpx.cpp:50
Helper functions to work with json::spirit and test files.
uint16_t const protocolId
Protocol ID as negotiated by handshake.
#define BOOST_CHECK(expr)
Definition: object.cpp:17
Multiplex packets into encrypted RLPX frames.