text: /*
  
  Copyright (c) 2007, Un Shyam
  Copyright (c) 2007, 2011, 2013, 2015-2021, Arvid Norberg
  Copyright (c) 2016, 2018, 2020-2021, Alden Torres
  Copyright (c) 2018, Steven Siloti
  All rights reserved.
  
  You may use, distribute and modify this code under the terms of the BSD license,
  see LICENSE file.
  */
  
  #include <algorithm>
  #include <iostream>
  
  #include "libtorrent/hasher.hpp"
  #include "libtorrent/aux_/pe_crypto.hpp"
  #include "libtorrent/aux_/random.hpp"
  #include "libtorrent/span.hpp"
  
  #include "test.hpp"
  
  #if !defined TORRENT_DISABLE_ENCRYPTION
  
  namespace {
  
  void test_enc_handler(lt::crypto_plugin& a, lt::crypto_plugin& b)
  {
  	int const repcount = 128;
  	for (int rep = 0; rep < repcount; ++rep)
  	{
  		std::ptrdiff_t const buf_len = lt::aux::random(512 * 1024);
  		std::vector<char> buf(static_cast<std::size_t>(buf_len));
  		std::vector<char> cmp_buf(static_cast<std::size_t>(buf_len));
  
  		lt::aux::random_bytes(buf);
  		std::copy(buf.begin(), buf.end(), cmp_buf.begin());
  
  		using namespace lt::aux;
  
  		{
  			lt::span<char> iovec(buf.data(), buf_len);
  			auto const [next_barrier, iovec_out] = a.encrypt(iovec);
  			TEST_CHECK(buf != cmp_buf);
  			TEST_EQUAL(iovec_out.size(), 0);
  			TEST_EQUAL(next_barrier, int(buf_len));
  		}
  
  		{
  			lt::span<char> iovec(buf.data(), buf_len);
  			auto const [consume, produce, packet_size] = b.decrypt(iovec);
  			TEST_CHECK(buf == cmp_buf);
  			TEST_EQUAL(consume, 0);
  			TEST_EQUAL(produce, int(buf_len));
  			TEST_EQUAL(packet_size, 0);
  		}
  
  		{
  			lt::span<char> iovec(buf.data(), buf_len);
  			auto const [next_barrier, iovec_out] = b.encrypt(iovec);
  			TEST_EQUAL(iovec_out.size(), 0);
  			TEST_CHECK(buf != cmp_buf);
  			TEST_EQUAL(next_barrier, int(buf_len));
  
  			lt::span<char> iovec2(buf.data(), buf_len);
  			auto const [consume, produce, packet_size] = a.decrypt(iovec2);
  			TEST_CHECK(buf == cmp_buf);
  			TEST_EQUAL(consume, 0);
  			TEST_EQUAL(produce, int(buf_len));
  			TEST_EQUAL(packet_size, 0);
  		}
  	}
  }
  
  } // anonymous namespace
  
  TORRENT_TEST(diffie_hellman)
  {
  	using namespace lt;
  
  	const int repcount = 128;
  
  	for (int rep = 0; rep < repcount; ++rep)
  	{
  		aux::dh_key_exchange DH1, DH2;
  
  		DH1.compute_secret(DH2.get_local_key());
  		DH2.compute_secret(DH1.get_local_key());
  
  		TEST_EQUAL(DH1.get_secret(), DH2.get_secret());
  		if (!DH1.get_secret() != DH2.get_secret())
  		{
  			std::printf("DH1 local: ");
  			std::cout << DH1.get_local_key() << std::endl;
  
  			std::printf("DH2 local: ");
  			std::cout << DH2.get_local_key() << std::endl;
  
  			std::printf("DH1 shared_secret: ");
  			std::cout << DH1.get_secret() << std::endl;
  
  			std::printf("DH2 shared_secret: ");
  			std::cout << DH2.get_secret() << std::endl;
  		}
  	}
  }
  
  TORRENT_TEST(rc4)
  {
  	using namespace lt;
  
  	sha1_hash test1_key = hasher("test1_key",8).final();
  	sha1_hash test2_key = hasher("test2_key",8).final();
  
  	std::printf("testing RC4 handler\n");
  	aux::rc4_handler rc41;
  	rc41.set_incoming_key(test2_key);
  	rc41.set_outgoing_key(test1_key);
  	aux::rc4_handler rc42;
  	rc42.set_incoming_key(test1_key);
  	rc42.set_outgoing_key(test2_key);
  	test_enc_handler(rc41, rc42);
  }
  
  #else
  TORRENT_TEST(disabled)
  {
  	std::printf("PE test not run because it's disabled\n");
  }
  #endif
  