A blockchain is a distributed ledger and every block of data is publicly available for everyone to see. You may be wondering what if I want to encrypt messages on blockchain, specifically, on EOS?

How securing messages on a blockchain works

We can incorporate NuCypher. NuCypher helps dApp developers store, share, and manage private data on public blockchains with decentralized proxy re-encryption as a service.

Here is how it works.

Alice has sensitive data that she wants to be able to delegate access to. Alice encrypts her data using her own public key and stores it in the cloud, or decentralized storage. Alice delegates access to Bob. The data is rekeyed to Bob’s key in storage. Bob downloads the data and decrypts it with his private key.

Securing a message on EOS

We’ll start with the scenario where Alice and Bob both have access to the private key and Alice wants to send sensitive data to Bob, and leverage pyUmbral which is NuCypher’s reference implementation of Umbral (split-key threshold proxy re-encryption).

Let’s first build a message queue smart contract on EOS.

It construct one table called messages, which contains uint64_t msg_id, account_name from, account_name to, string ciphertext, and string capsule. msg_id is the primary key.

It provides two actions: sendmsg and deletemsg . sendmsg requires account_name from and to, msg_id, ciphertext and capsule. Ciphertext is the encrypted message and capsule is the concept in Umbral, which is generated using pyUmbral. deletemsg basically takes a msg_id, verifies the given to account_name, then deletes the record.

class queue: public eosio::contract { public:

using contract::contract; //@abi action

void sendmsg( account_name from, account_name to, uint64_t msg_id, const std::string & ciphertext, const std::string & capsule) {

require_auth( from );

messages_index messages( _self, _self );

auto itr = messages.find(msg_id);

if (itr != messages.end()) {

std::string error = "msg_id already exists: " + std::to_string(msg_id);

eosio_assert(false, error.c_str()); }

messages.emplace( from, [&](auto& msg){

msg.msg_id = msg_id;

msg.from = from;

msg.to = to;

msg.ciphertext = ciphertext;

msg.capsule = capsule;

}); } // @abi action

void deletemsg( account_name to, uint64_t msg_id) {

require_auth( to );

messages_index messages(_self, _self);

auto itr = messages.find(msg_id);

if ( itr == messages.end() ) {

std::string error = "msg_id does not exist: " + std::to_string(msg_id);

eosio_assert(false, error.c_str());

}



if ( itr->to != to ) {

std::string error = "Receipient not correct: " + eosio::name{itr->to}.to_string();

eosio_assert( false, error.c_str());

}



messages.erase(itr);

} private:

//@abi table messages i64

struct messages {

uint64_t msg_id;

account_name from;

account_name to;

std::string ciphertext;

std::string capsule; uint64_t primary_key() const { return msg_id;}

};



typedef eosio::multi_index<N(messages), messages> messages_index; }; EOSIO_ABI( queue, (sendmsg)(deletemsg) )

Compile it:

eosiocpp -o queue.wast queue.cpp

eosiocpp -g queue.abi queue.cpp

Create an account to upload the smart contract:

$ cleos create account eosio queue EOS5aEqZf22dfThTR8GGMnD8oFvsyzssQnhawNwPzfPv4fwDWhf7H

executed transaction: a767af2c66857... 200 bytes 3309 us

# eosio <= eosio::newaccount {"creator":"eosio","name":"queue","owner":{"threshold":1,"keys":[{"key":"EOS5aEqZf22dfThTR8GGMnD8oFv... $ cleos set contract queue ../queue

Reading WAST/WASM from ../queue/queue.wasm...

Using already assembled WASM...

Publishing contract...

executed transaction: 38e94741c... 13824 bytes 9561 us

# eosio <= eosio::setcode {"account":"queue","vmtype":0,"vmversion":0,"code":"00617ee7e...

# eosio <= eosio::setabi {"account":"queue","abi":"0e656f73696f3a3a6162692f9640675...

Create test accounts alice and bob: