essay on programming languages, computer science, information techonlogies and all.

Wednesday, June 13, 2018

C++ thread

std::thread with static function


#include 

void called_from_static_fn( const std::string& arg )
{
  // ...
}

std::thread t1(called_from_static_fn, "static");
// ...
t1.join();

std::thread with member fn


class Foo
{
public:
	void Bar( const string& arg)
	{
		// ...
	}
};

Foo foo;
thread t1(&Foo::Bar, &foo, "member");
// ...
t1.join();

std::thread with lambda


int ret = 0;
thread t( [ &ret ](int m, int n) { ret = m + n; }, 2, 4 );
t.join();

std::thread in array


static int twice(int m) { return 2 * m; }

vector< thread > threads;
for (int i = 0; i < 10; ++i)
{
  threads.push_back( thread(twice, i));
}

for (auto& t : threads)
{
  t.join();
}

catch exception in a thread


static int DoNotTryAtHome()
{
  throw exception("I said NO");
}

thread t1(DoNotTryAtHomeNoThrow);
t1.join();

use mutex on shared variable


class Foo 
{
	int m_Bar = 0;
	mutex m_LockBar;
public:
	void AddBarSafe(int add)
	{
		lock_guard< mutex > guard(m_LockBar);
		int temp = m_Bar;
		this_thread::sleep_for(chrono::milliseconds(10));
		m_Bar = temp + add;
	}
};

{
	Foo foo;
	vector ts;
	ts.emplace_back(thread{ &Foo::AddBarSafe, &foo, 2 });
	ts.emplace_back(thread{ &Foo::AddBarSafe, &foo, 3 });
	ts.emplace_back(thread{ &Foo::AddBarSafe, &foo, 4 });

	for (auto& t : ts) {  t.join(); }
}

std::thread on class operator()


struct funcCount
{
	int &i;
	funcCount(int& i_) : i(i_) {}
	void operator()()
	{
		for (unsigned j = 0; j < 1000; ++j)
		{
			++i;
			this_thread::sleep_for(chrono::milliseconds(1));
		}
	}
};

{
	int some_local_state = 0;
	funcCount my_func(some_local_state);
	std::thread my_thread(my_func);
	// my_thread.detach();				// undefined behaviour
	my_thread.join();
}

thread_guard


class thread_guard
{
	std::thread& t;
public:
	explicit thread_guard(std::thread& t_) : t(t_) {}
	~thread_guard() 
	{ 
		if (t.joinable()) t.join(); 
	}

	thread_guard(thread_guard const&) = delete;
	thread_guard operator = (thread_guard const &) = delete;
};

void do_something_stupid()
{
	for (int i = 1; i < 10; ++i)
	{
		if (i % 5 == 0)
		{
			throw std::exception("ooops");
		}
	}
}

{
	int some_local_state = 0;
	try
	{
		funcCount my_func(some_local_state);
		std::thread t(my_func);
		thread_guard g(t);
		do_something_stupid();
	}
	catch (...)
	{
	}
}

move around thread


{
	std::thread t1(called_from_static_fn, "static");
	std::thread t2 = std::move(t1);
	t1 = std::thread(&TestMultiThread::called_from_member_fn, this, "static");
	std::thread t3;
	t3 = std::move(t2);
	// t1 = std::move(t3);   //  terminate

	t1.join();
	t3.join();
}

async


{
	future result(async(called_from_static_fn, "static"));
	result.get();
}

{
	Foo foo;
	future result(async(&Foo::Bar, &foo, "member"));
	result.get();
}

{
	future result(async([](int m, int n) { return m + n; }, 2, 4));
	int ret = result.get();
}

{
	vector< future< int > > futures;
	for (int i = 0; i < 10; ++i)
	{
		futures.push_back(async(twice, i));
	}

	for (auto& e : futures)
	{
		cout << e.get() << endl;
	}
}

async will throw exception at convenient time


{
	future result(async(DoNotTryAtHome));
		
	try
	{
		int ret = result.get();
	}
	catch (exception& ex)
	{
		printf("exception caught : %s", ex.what());
	}
}

wait for future


{
	future f = async( [](){ cout << "bar" << endl; } );
		
	if (f.wait_for(chrono::milliseconds(0)) == future_status::deferred)
	{
		cout << "foo and wait for bar" << endl;
		f.get();
	}
	else
	{
		while (f.wait_for(chrono::milliseconds(10)) != future_status::ready)
		{
			cout << "foo waiting ... " << endl;
		}

		cout << "foo" << endl;
	}
}

condition_variable


{
	mutex m_LockReadyProcess;
	condition_variable m_Condition;
	string m_Log;
	bool m_Ready = false;
	bool m_Processed = false;
}

void worker_thread()
{
	unique_lock lock(m_LockReadyProcess);
	m_Condition.wait(lock, [=]{return m_Ready; });

	cout << "Worker thread is processing data\n";
	m_Log += " after processing";

	m_Processed = true;
	cout << "Worker thread signals data processing completed\n";

	lock.unlock();
	m_Condition.notify_one();
}

{
	thread worker( &TestMultiThread::worker_thread, this);

	m_Log = "Example data";

	{
		lock_guard guard(m_LockReadyProcess);
		m_Ready = true;
		cout << "main() signals data ready for processing\n";
	}
	m_Condition.notify_one();

	{
		unique_lock lock(m_LockReadyProcess);
		m_Condition.wait(lock, [=]{return m_Processed; });
	}
	cout << "Back in main(), data = " << m_Log << '\n';

	worker.join();
}

Wednesday, June 6, 2018

Cryptography tutorial using Poco

Poco has crypto module and here is a tutorial of cryptography using Poco. Symmetric encryption is encrypt and decrypt using a key known by two player. Simple but hard to make key to be safe.

#include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/CipherKey.h"
#include "Poco/Crypto/CipherFactory.h"

auto& factory = CipherFactory::defaultFactory();
string transmission;

{
  Cipher* alice = factory.createCipher( CipherKey( 
    "aes-256-ecb", "open sesame"));
  transmission = alice->encryptString( 
    "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}

{
  Cipher* bob = factory.createCipher( CipherKey( 
    "aes-256-ecb", "open sesame"));
  string decrypted = bob->decryptString(transmission);
  assert(decrypted == 
    "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}
To remove this unsafe key, asymmetric encryption can be used. To do it, first priavate and public key should be generated. OpenSSL can be used like below.


>openssl.exe genrsa -des3 -out private_bob.pem 2048
Generating RSA private key, 2048 bit long modulus
...................+++
.................................................................+++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase for private_bob.pem:
Verifying - Enter pass phrase for private_bob.pem:


>openssl.exe rsa -in private_bob.pem -outform PEM -pubout -out public_bob.pem
Enter pass phrase for private_bob.pem:
writing RSA key

Then Alice can encode message using Bob's public key. Then only Bob can decode it using his private key.

#include "Poco/Crypto/RSAKey.h"
#include "Poco/Crypto/RSADigestEngine.h“

auto& factory = CipherFactory::defaultFactory();
string transmission;

{
  Cipher* alice = factory.createCipher(RSAKey( "public_bob.pem"));
  transmission = alice->encryptString(
    "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}

{
  Cipher* bob = factory.createCipher(RSAKey( "", "private_bob.pem", "bobbob"));
  string decrypted = bob->decryptString(transmission);
  assert(decrypted == "Tall tree, Spy-glass shoulder, ... Skeleton Island ESE and by E");
}
The assymetric encryption can be extended to make contract between two players which is called digital signature.
Here, Alice can verify Bob's digital signature with the contract he promised.

// Poco::DigestEngine::Digest is std::vector 
tuple transmission;

{
  string contract = 
    "Alice will give Bob $100 and Bob will give Alice two magic mushrooms";
  RSADigestEngine bob(RSAKey("", "private_bob.pem", "bobbob"));
  bob.update(contract);
  transmission = make_tuple(contract, bob.signature());
}

{
  RSADigestEngine alice(RSAKey("public_bob.pem"));
  alice.update(get<0>(transmission));
  bool isValid = alice.verify(get<1>(transmission));
  assert(isValid == true);
}

Imagine, Alice get greedy and forged the contract, then Bob's signature doesn't work anymore.

// Poco::DigestEngine::Digest is std::vector 
tuple transmission;

{
  string contract = 
    "Alice will give Bob $100 and Bob will give Alice two magic mushrooms";
  RSADigestEngine bob(RSAKey("", "private_bob.pem", "bobbob"));
  bob.update(contract);
  transmission = make_tuple(contract, bob.signature());
}

{
  RSADigestEngine alice(RSAKey("public_bob.pem"));
  alice.update(
    "Alice will give Bob $100 and Bob will give Alice three magic mushrooms");
  bool isValid = alice.verify(get<1>(transmission));
  assert(isValid == false);
}
This digital signature can be extended further to digital coin. First chained transaction should be established. Here is a diagram from Satoshi Nakamoto's paper which shows the concept.

Here, Queen generate coin and give it to Alice; Queen use Alice's public key to generate transaction hash and sign the hash using majesty private key.

struct Transaction
{
  string Hash;
  vector Signature;
};

Transaction queenToAlice;
{
  // Queen
  RSAKey alicePublic("public_alice.pem");
  stringstream alicePublickey;
  alicePublic.save(&alicePublickey);

  Crypto::DigestEngine hasher("SHA256");
  hasher.update("Queen's own right to create coin");
  hasher.update(alicePublickey.str());
  string hash = Crypto::DigestEngine::digestToHex(
  hasher.digest());

  RSADigestEngine queen(RSAKey("", "private_queen.pem", "queenqueen"));
  queen.update(hash);

  queenToAlice = Transaction{ hash, queen.signature() };
}
Now, Alice can verify Queen's benevolence using Queen's public key.

{
  // Alice
  RSADigestEngine alice(RSAKey("public_queen.pem"));
  alice.update( queenToAlice.Hash );
  assert( true == alice.verify(queenToAlice.Signature));
}
Then Alice send the coin to Bob; Update the transaction 's hash with Bob's public key and sign it with Alice's private key.

Transaction aliceToBob;
{
  // Alice
  RSAKey bobPublic("public_bob.pem");
  stringstream bobPublickey;
  bobPublic.save(&bobPublickey);

  Crypto::DigestEngine hasher("SHA256");
  hasher.update(queenToAlice.Hash);
  hasher.update(queenToAlice.Signature.data(), 
  queenToAlice.Signature.size());
  hasher.update(bobPublickey.str());
  string hash = Crypto::DigestEngine::digestToHex(
  hasher.digest());

  RSADigestEngine alice(RSAKey("", 
    "private_alice.pem", "alicealice"));
  alice.update(hash);

  aliceToBob = Transaction{ hash, alice.signature() };
}
And Bob can verfiy Alice's coin given to himself.

{
  // Bob
  RSADigestEngine bob(RSAKey("public_alice.pem"));
  bob.update(aliceToBob.Hash);
  assert(true == bob.verify(aliceToBob.Signature));
}
The genuine idea of Bitcoin is BlockChain which verify the transaction in decentralized way. Here is another excerpt from the paper.
It says there should be proof-of-work ; which is basically finding a additional string - nounce - that make hash to start with number of '0' characters. Finding nounce is hard but verifying it is easy. Here is how to verify nounce.

struct Transaction {  string Hash, Signature; };

struct Block {
  string PrevHash, Nounce;
  vector Transactions;
};

Block t0 = {
  "Hello, world!", "4250",  { Transaction{ "", "" } }
};


// verfiy t0 block's transactions and proof-of-work
hasher.update(t0.PrevHash);
for (auto tx : t0.Transactions) {
  hasher.update(tx.Hash); hasher.update(tx.Signature);
}
hasher.update(t0.Nounce);

t1.PrevHash = Crypto::DigestEngine::digestToHex(hasher.digest());
assert(t1.PrevHash.substr(0, 4) == "0000");
Here is a way to finding nounce by brute-force.

// gather transactions
t1.Transactions = { 
  Transaction{ "ab", "cd" }, 
  Transaction{ "12", "34" }, 
  Transaction{ "56", "78" } };

// race for the nounce
for (int nounce = 0;; ++nounce)
{
  hasher.reset();
  hasher.update(t1.PrevHash);
  for (auto tx : t1.Transactions) {
    hasher.update(tx.Hash); hasher.update(tx.Signature);
  }
  hasher.update(to_string(nounce));

  string hash = Crypto::DigestEngine::digestToHex(hasher.digest());
  if (hash.substr(0, 4) == "0000") {
    t1.Nounce = to_string(nounce);
    break;
  }
}

// broadcast t1 block to world