Encrypted messaging on the NEO blockchain

Apisit Toompakdee
Proof of Working
Published in
6 min readDec 29, 2017

As you may know, transactions made on most blockchains are publicly available to everyone. Either by querying a NEO node directly via RPC, or by using a user friendly block explorer like NEOTracker or NEOScan allow you to browse transactions, balances, smart contracts and any other piece of data on the blockchain. However, sometimes privacy is a must have feature in certain applications. One example of this is messaging. If you want to send a message to someone then you would obviously not want someone else to be able to read your message log which could expose sensitive information. In this article I’ll show you the basics of how to perform encrypted messaging on the NEO blockchain.

First lets look again at the anatomy of a transaction on the NEO blockchain.

NEO Transaction

This is the basic memory structure of a transaction. When you send GAS or NEO on chain your wallet client will create this data packet and broadcast it to the network. If you are interested in reading more detail about creating a light client or transaction structure in general. Check out Andrei’s post. Creating a Light Client for Neo, a Blockchain Developer’s Gateway Drug — Steemit

For messaging we only care about the metadata following immediately after the input data. A relatively unknown feature of NEO transactions is that you can attach transaction attributes to any transaction. A transaction attribute is broad term that basically means additional data. So when you send any amount of NEO or any amount of GAS you can attach a message in the transaction attribute.

So I can send 0.0000001 GAS to my friend and attach the message “Hello”. Although this seems like a trivial example, this message is something permanently store on the blockchain and will never be deleted. However as mentioned before, it’s not very useful if everybody can read it. So how do we prevent this?

So to recap we want to accomplish this.

In theory this seems pretty simple. I could create a secret password to encrypt a message and tell my firiend that secret password so you can use it to decrypt a message.

However, what If I want to send to 10 other friends or even a 100? I would have to keep track of all the secret passwords that I created because if I used the same password then everyone would be able to decrypt each others secret messages. Furthermore, how do I securely send a secret password I created for you in the first place?

So to recap in order to send an encrypted message on the blockchain we need to of the following

1. Generate a secret password
2. Share the secret with our friend so that they can decrypt the password
3. Encrypt a message using the secret password
4. Send the encrypted message in the transaction attribute field of a NEO transaction

Whenever you create a new wallet you are given four key elements, a public key, private key, NEO address and a WIF.

With the WIF or private key, you can generate the other elements but not vice versa. We will see how we can use these elements in order to generate our password.

Here comes classic actors in cryptographic examples: Alice and Bob
Alice wants to send Bob an encrypted message that only both of them can read. What we need is a shared secret between Alice and Bob. This will perform steps 1 and 2 at the same time.

First, We get Alice and Bob a pair of keys.

Alice and Bob exchanged their public keys.

Alice and Bob exchanging public key

After this exchange the shared secret can be generating using a common technique called Elliptic-curve Diffie–Hellman — Wikipedia

ECDH for short, is an anonymous key agreement protocol which is used to generate a shared secret from a key pair suitable for elliptic curve cryptography.

Now we have all the things we need.

Generating shared secret with public key and private key.

I won’t go into all the math about how the shared secret is generated, but please read more about ECDH from the link above.

I wrote a small Go program to demonstrate the result. The output is below (private key is redacted)

Alice’s NEO adress = AQpkhLEdcvmBbBb1TAb7BeVyLTweHSfTe5
Bob’s NEO address = AH6Wd2j3d6BQhSDSSyGPjDKTgii2gxHLPW
Alice’s public key = 03c8cbdc902fc302329132c56a8c9535f9c86952ddf539679fc1ba29091aaaf2da
Bob’s public key = 03c075742edf955c47700586a849b453b21ee5a50129546576b673579600aef557
Alice’s shared secret (Bob’s public key + Alice’s private key) = 2e29b2afffecec017e3dd11e2061cae2a77957d9cc364cf7c837c8efc95f94d5
Bob’s shared secret (Alice’s public key + Bob’s private key) = 2e29b2afffecec017e3dd11e2061cae2a77957d9cc364cf7c837c8efc95f94d5

As you can see from the result above. Alice and Bob shared secret are identical which is why it is called shared secret.

Now Alice and Bob can use derived shared secret to encrypt a message using Symmetric-key algorithm — Wikipedia like AES (Advanced Encryption Standard — Wikipedia)

Encrypting a message with shared secret

And here you go the secured message is ready to be sent, we insert the encrypted in the transaction attribute of the NEO transaction and get a result that looks like this.

Alice sent QcwFUOqIaUY1heZi3eutnTMQUMy4EwrLyA== to Bob
Bob sent pZWXtZeg6-pTHlk2deInSDcL9NaVzZm-xUEUA8d__g== to Alice

As you can see no one will able to know what the conversation between Alice and Bob is without first decrypting the message, and they won’t be able to do this without the shared secret.

Luckily Alice and Bob both have access to the shared secret because they shared public keys earlier. So using the shared secret they decrypt each others messages.

Decrypting a message with shared secret

That’s it. That’s how to encrypt/decrypt a message with ECDH.

So to recap Alice and Bob shared public keys, which allowed them to generate an identical shared secret. They used this shared secret to encrypt and decrypt their respective messages. This is a basic rundown of ECDH so how can we incorporate this into NEO, for encrypted blockchain messaging?

Bob can initiate a communication by sending Alice a fraction of gas 0.00000001GAS with his public key in transaction attribute field 0x02 or 0x03

Because Alice knows Bob’s address and there is a transaction coming from Bob. The application should be able to get Bob’s public key from the transaction attribute in the transaction data.

On Alice side, An application uses Bob’s public key and Alice’s private key to generate a shared secret. Encrypt a message with derived shared secret and then put an encrypted message into transaction attribute field 0xf0 and Alice’s public key into a 0x02 field.

After Bob received the transaction. The application can grab Alice’s public key and encrypted message from transaction attributes in received transaction data then begin the process or decrypting.

Check out NEO network protocol document for transaction attribute usage

Here is a visual diagram of the process described above.

Of course, This does not mean we can make a real-time messaging application on NEO blockchain but more about the idea of secure messaging.

One cool side effect of all of this is that it allows for an economic use case for GAS. The minimum unit of GAS is now the cost of sending an encrypted message on the blockchain.

That’s totally it. Hope you get a better understanding of what crypto in cryptocurrency actually is. If you have any question. you can ping me on twitter @imapisit or email apisit@o3.network

Big thanks to Andrei for proofreading and editing.

— a

--

--