Daser David
5 min readJul 8, 2018

A lazy man’s introduction to Multi-Party encryption and decryption

Disclaimer: This is a note to self, a usual way of how i restore forgotten memories when encountered with familiar challenges. However if this makes sense or helped you in anyway then it means i had you in mind all along.

Security of data are usually of concerned to everyone in this era as the repercussions of data security breach cannot be over-emphasized. As developers and programmers alike we are always faced with questions of securities in every our daily implementations. Just about some days ago i was faced with one. What was the question?

In a Multi-User systems, Is it possible to send an encrypted message to multiple users so that the users receiving the message can decrypt this message with their own keys? Is it possible for users to use their keys to decrypt encrypted messages from different sources given access or permissions to by the information owners?

If you find yourself in this dilemma then this is for you.

Before going into detail i would love to define some terms i would be using in this article.

Symmetrical Encryption: This is the simplest kind of encryption that involves only one secret key to cipher and decipher information. Symmetrical encryption is an old and best-known technique. It uses a secret key that can either be a number, a word or a string of random letters. It is a blended with the plain text of a message to change the content in a particular way. The sender and the recipient should know the secret key that is used to encrypt and decrypt all the messages. Blowfish, AES, RC4, DES, RC5, and RC6 are examples of symmetric encryption. The most widely used symmetric algorithm is AES-128, AES-192, and AES-256.

Asymmetrical Encryption: Asymmetrical encryption is also known as public key cryptography, which is a relatively new method, compared to symmetric encryption. Asymmetric encryption uses two keys to encrypt a plain text. Secret keys are exchanged over the Internet or a large network. It ensures that malicious persons do not misuse the keys. It is important to note that anyone with a secret key can decrypt the message and this is why asymmetrical encryption uses two related keys to boosting security. A public key is made freely available to anyone who might want to send you a message. The second private key is kept a secret so that you can only know.

Let’s look at a simple scenario. Say a user A creates a very sensitive information and decides to encrypt it, user A intends users B and D to be able to view this encrypted data. This will also mean that in a multi-user system, other users should not be able to view or decrypt this sensitive information.

Workflow below:

Every created user in this multi-user system would each have own public and private keys. Data will be encrypted by user (A) with a randomly generated key (K) using a symmetric encryption algorithm most preferably (AES) . What this implies is that during decryption this randomly generated key must again be used (see definition of symmetrical encryption above). How then do we transport (K) to users (B) and (D) who would need to decrypt this information? Transporting (K) over the internet as a plain text would be disastrous as man in the middle or other forms of attack would cause disaster.

If you need this data to be accessible to users B and D then you will need to encrypt the key (K) differently with their respective public keys. Note that these “encrypted keys” have a small size so this scales up.

Let me be more practical:

User A creates a text let’s call it “Hello World”, he then randomly generates a string to be used to encrypt “Hello World”. See codes below:

const keygen = require(“keygenerator”);let key = keygen._();let text = “Hello World”

Encryption of key using the owner’s public key can then be carried our. Albeit for storage purpose:

const NodeRSA = require(‘node-rsa’);let RSAkey = new NodeRSA(‘ — — -BEGIN RSA PUBLIC KEY — — -\nMIIBCgKCAQEAnKtm2cyc2DQDSdciz8A/Dy6MB7ufiprNEgEA43AwMuPs+7cZ68kTxHH/Vo/t\nGsatfP7Z7YTwOpP8J47kHJUsSkPQKkoy4KCOaMlLl6BR56HN7Od+OaZdg4vDpVhDWEgJwpuN\nfckX3UgKWlJQlCfCc3mYCiwUo9XA2/DEnrtDNuKnXpBH/bDE8b8q8R/UR5jYbyfDpZFKDaF0\n4qNpjbzpYkAzcTi70wXnrC0arq2LplP3YoBN0FI2JbZZkCfBjyPe9qm3kihqpCFa8aN4yEQ9\nAy6vGNAePcz9XaEcVvSjR4zdnvM8ebDPyFVO10cUbvmPXOnxflmdOyZwaKVY9iVPfQIDAQAB\n — — -END RSA PUBLIC KEY — — -’);let encryptedKey = RSAkey.encrypt(key, ‘base64’);Let’s encrypt the text:const crypto = require(‘crypto’);
const iv = ‘60iP0h6vJoEa’;
var cipher = crypto.createCipher(‘aes-256-cbc’, key, iv);
var crypted = cipher.update(text,’utf8',’binary’);
crypted += cipher.final(‘binary’);
crypted = new Buffer(crypted, ‘binary’).toString(‘base64’);

For the sake of convenience, you can store both crypted and encryptedKey in any secure backend. I am assuming that in this system, each time a user is created, a public-private key pair is generated for the user. In my implementation i had the private key stored in amazon S3 while the public key is stored in the db.

What this implies is that before access is granted to a third party say Mr. B to decrypt the message, the public key of Mr. B would be required. The information owner would use own private key to decrypt the stored encrypted key which was initially encrypted with the owner’s public key. Asymmetrical Encryption. Use Mr. B’s public key to now encrypt the plain key and then sends the cipher key to Mr. B who now in turn uses own private key to decrypt the cipher key into a plain text and now uses the plain text to decrypt the information. Symmetrical Encryption.

const crypto = require(‘crypto’);
const iv = ‘60iP0h6vJoEa’;
ntext = new Buffer(text, ‘base64’).toString(‘binary’);
var decipher = crypto.createDecipher(‘aes-256-cbc’, cryptKey, iv);
var dec = decipher.update(ntext,’binary’,’utf8');
dec += decipher.final(‘utf8’);

Two things of note is that, access to information by a user is an on-demand base, and the contract for having access to any secured information is that you make your public key available and then Asymmetrical encryption offers a good transport function in this workflow. It helps us envelop the random key K that is needed to decrypt an information over the transport protocol.

For production purpose, i wouldn’t use a local db to store users public keys and other user sensitive encrypted data. It is vital to note that we utilize PCI compliant services like https://www.auricsystems.com for these storage.