Skip to content

Latest commit

 

History

History
109 lines (85 loc) · 3.32 KB

encrypted-message.md

File metadata and controls

109 lines (85 loc) · 3.32 KB

Tutorial: Encrypt and sign a message

With ethereum-keys you cannot only interact with the blockchain, but also use them to send messages over mutual untrusted channels in a secure way. In this tutorial we will use ethereum-identities to send messages like you would do in a decentralized chat-app.

Prerequisites

First we create two identities, Alice and Bob. In our case Alice wants to send the message My name is Satoshi Buterin to Bob.

const EthCrypto = require('eth-crypto');

const alice = EthCrypto.createIdentity();
const bob = EthCrypto.createIdentity();
const secretMessage = 'My name is Satoshi Buterin';

Encrypt and sign the message

Before we send the message from Alice to Bob, we want to ensure that

  • Only Bob can read the message
  • Bob can be sure that the message really comes from Alice

To do this, we first sign the message with alice's privateKey and then encrypt the message and the signature with bob's publicKey.

const signature = EthCrypto.sign(
    alice.privateKey,
    EthCrypto.hash.keccak256(secretMessage)
);
const payload = {
    message: secretMessage,
    signature
};
const encrypted = await EthCrypto.encryptWithPublicKey(
    bob.publicKey, // by encrypting with bobs publicKey, only bob can decrypt the payload with his privateKey
    JSON.stringify(payload) // we have to stringify the payload before we can encrypt it
);
/*  { iv: 'c66fbc24cc7ef520a7...',
  ephemPublicKey: '048e34ce5cca0b69d4e1f5...',
  ciphertext: '27b91fe986e3ab030...',
  mac: 'dd7b78c16e462c42876745c7...'
    }
*/

// we convert the object into a smaller string-representation
const encryptedString = EthCrypto.cipher.stringify(encrypted);
// > '812ee676cf06ba72316862fd3dabe7e403c7395bda62243b7b0eea5eb..'

// now we send the encrypted string to bob over the internet.. *bieb, bieb, blob*

Decrypt and verify the payload

When bob receives the message, he starts with decrypting it with his privateKey and then verifies the signature.

// we parse the string into the object again
const encryptedObject = EthCrypto.cipher.parse(encryptedString);

const decrypted = await EthCrypto.decryptWithPrivateKey(
    bob.privateKey,
    encryptedObject
);
const decryptedPayload = JSON.parse(decrypted);

// check signature
const senderAddress = EthCrypto.recover(
    decryptedPayload.signature,
    EthCrypto.hash.keccak256(decryptedPayload.message)
);

console.log(
    'Got message from ' +
    senderAddress +
    ': ' +
    decryptedPayload.message
);
// > 'Got message from 0x19C24B2d99FB91C5...: "My name is Satoshi Buterin" Buterin'

Creating an answer

Now that Bob got the message, he can also answer back to alice. To do this he has to recover the publicKey of alice with recoverPublicKey().

const answerMessage = 'And I am Bob Kelso';
const answerSignature = EthCrypto.sign(
    bob.privateKey,
    EthCrypto.hash.keccak256(answerMessage)
);
const answerPayload = {
    message: answerMessage,
    signature: answerSignature
};

const alicePublicKey = EthCrypto.recoverPublicKey(
    decryptedPayload.signature,
    EthCrypto.hash.keccak256(payload.message)
);

const encryptedAnswer = await EthCrypto.encryptWithPublicKey(
    alicePublicKey,
    JSON.stringify(answerPayload)
);
// now we send the encryptedAnswer to alice over the internet.. *bieb, bieb, blob*