Whisper — Shh!

David Tomu
Caelum Labs
Published in
5 min readSep 26, 2018

What if we could send an encrypted message through the Ethereum blockchain, decrypted only with the corresponding key?

That’s exactly what Whisper does as a peer-to-peer communication protocol for DAPPS built on top of the Ethereum network. It’s designed to rely on identity-based data and enable users to send messages within the network.

Before getting to the point, let’s put it into context. When imagining Ethereum as a shared computer it should be noted that computation alone isn’t enough. To be fully useful, a computer needs to storage and “remember” things and also bandwidth to connect both.

This could be summarized as so:

  • Contracts: decentralized logic
  • Swarm: decentralized storage
  • Whisper: decentralized messaging

Whisper is being built as a protocol, meaning that it lays the foundation for higher-level implementations. For example DApps built on it, with different variations, features of the protocol and settings. It’s currently at POC 2 stage and usable on Geth and Parity.

Whisper works sending messages with a respective topic. Those messages give a probabilistic hint about an encryption key and could be decrypted using their corresponding key.

Every node may have multiple symmetric and asymmetric keys to decrypt the message received. Since the signature is a part of the message, those unable to decrypt it, won’t have access to the signature either.

The signature, if provided, is the ECDSA signature of the Keccak-256 hash of the unencrypted data using the secret key of the originator identity.

So let’s delve into this protocol and the basic elements that are implemented

Message

When a message is sent, this is accompanied by a unique process of message sealing, compression and encryption that require the following parameters:

  • Payload = message content
  • PublicKey = key used for encryption
  • TTL = time-to-live in seconds for the message
  • PowTime = max time in seconds to be spent on Proof of Work
  • PowTarget = min PoW target required for the message

Basically, all the Whisper messages are sent to every Whisper node using a proof-of-work (PoW) to prevent DDoS attacks.

Here is an example of the message structure containing a lifespan (2 day max.), a recipient (recognized by a public key) and a group of message topics.

message := whisperv6.NewMessage{
Payload: []byte(“Hello”),
PublicKey: publicKey,
TTL: 60,
PowTime: 2,
PowTarget: 2.5,
}

Topics

Through the use of topics, we can know if a message is encrypted to a specific recipient (in which case uses the private key to decrypt) or to a general multicast audience.

Message topics are hashed automatically, and only the initial 4 bytes of the resultant SHA3–256 hash function is utilized throughout the process of message data transfer, thus, message topics are unreliable, so filtering is worth considering as a probabilistic approach to topics distribution.

Encryption

Sending messages via Whisper requires encryption using a specific structure. Listening to message channels is possible via the watch/subscribe methods (Whisper v5). Accordingly, users can listen to messages of specific recipients, specific topics or just messages sent to you.

Payloads are encrypted via the following two ways:

1- Messages intended only to one recipient will be encrypted via ECIES and the recipient’s public key via SECP-256k1.

2- Messages with no intended recipients will be encrypted via AES-256 using a randomly formulated key. This key will further shape the topic of the message. Such topics are stored along with the same order of the matching topics within the header of the envelope.

Decryption

Decryption takes place using a private key if the message’s envelope is encrypted by no more than one sender. In such case, the known full message topic is matched to one of the envelope’s abridged topics; the index is determined and the section of the encryption key is decrypted at the beginning of the data segment so that the final key is retrieved.

Example

The usage on the Ethereum mainnet is restricted by the number of running nodes that have the Whisper protocol enabled. In the following example, we are going to use a private blockchain testing Whisper with Geth.

Let’s do an example using whisper between two nodes in a private network. In case you need to set up one, try the following tutorial [1].

Once we have a private blockchain, run two Geth nodes with the Whisper flag activated ( — shh).

Then create the following scripts and run them in the Geth console.

#NODE 1
kId = web3.shh.newKeyPair() //create new key-pair
var a = shh.getPrivateKey(kId) //Store this, it will be used on Geth’s new session
var b = shh.getPublicKey(kId);
web3.shh.hasKeyPair(kId) //true
web3.shh.newMessageFilter(
{privateKeyID:kId},
function(err, res) {console.log(web3.toUtf8(res.payload))});

It’s a simple example between two nodes using an asymmetric encryption of the message sent.

Now, before we are able to create a message, we must first have a key to encrypt it.

#NODE 2
privateKey = ‘0xda805d8a800e689a1d0c25a084e752812ad9b45d3b6d6fb1477ddd440d0e08c1’;//From previous Geth session
kId=shh.addPrivateKey(privateKey) //Loads the key-pair
shh.hasKeyPair(kId); //true
var a = shh.getPublicKey(kId); //Same public key is received that is also obtained before Geth is closed
shh.newMessageFilter(
{‘privateKeyID’:kId},
function(err, res) {console.log(web3.toUtf8(res.payload))});

In the second node, we need to put the private key generated in the other Geth session, to filter and read the message.

#NODE 1
web3.shh.post({
pubKey: ‘0x0430193b1dd274370c1a6f1244cc159b4969b5aeb3ed5327d02aa3c54b31436ec1af5261bac37aa41f5d81ef4791ce7e729df4b4a20ec42a4e8e1c24dc4995a903’,
ttl: 7,
topic: web3.toHex(“topic”),
powTarget: 2.01,
powTime: 2,
payload: web3.fromAscii(“message to send”),
deniable: false
});

We introduce a topic and, after the key is generated, the message can be sent to the other node.

Follow these instructions If you want to test it with Parity

Now we can try the Parity implementation of this protocol. First of all create a private network [2].

Let’s run the Parity node with the whisper flag activated ( — whisper).

For a simple test, you can interact with Postman adding the POST functions. You can add all the Whisper protocol functions [3] and then connect to your running node.

Why Whisper?

Photo by Kristina Flour on Unsplash

The Whisper Protocol is useful for different ÐApps. For example, to send small amounts of information to each other. So it can be also useful for develop privacy-focused chat apps or to collaborate on a transaction.

Whisper can theoretically deliver 100% obfuscated communication. Allowing Dapps to send and receive information to other recipients only knowing their hash.

References

[1] Private blockchain (Geth): https://bigishdata.com/2017/12/15/how-to-write-deploy-and-interact-with-ethereum-smart-contracts-on-a-private-blockchain/

[2] Private blockchain (Parity): https://github.com/paritytech/wiki/blob/master/Demo-PoA-tutorial.md

[3] Whisper functions (RPC): https://wiki.parity.io/JSONRPC-shh-Module

--

--