Medipedia is a decentralized platform based on Ethereum blockchain where patients can search complete and accurate information about various healthcare service providers. This platform can also help medical institutions and hospitals to connect with patients. Medipedia platform stores medical and health related information in IPFS (Interplanetary File System), which is created at Protocol Labs.

Searching a right medical service provider at Medipedia platform involves creating a message request and platform will send the request to all the matching service providers. Service providers may later reply to message request. Every message request and it’s replies are stored in IPFS and IPFS generates a hash that is finally updated in Ethereum blockchain.

However, this approach has a security and privacy loophole that can be easily breached. If information is stored without encryption to IPFS and the generated hash value is updated directly to blockchain then someone with the same IPFS hash can easily retrieve all the information from IFPS. Hence, we need Medipedia to provide decentralized end-to-end encrypted messaging platform so that only authorized and designated person can have access to information.

How to secure messages before storing to IPFS?

Most important thing is to maintain the privacy of the message by making it unreadable by the malicious users. Hence, we will use Asymmetric encryption to encrypt the message with the public key of the message recipient at the client side itself. When the encrypted message will be relayed over the network to be stored in IPFS, it will be impossible by the intruders to intercept as to what kind of data it is.

We will have an implementation that is simple enough to understand as to how information can be encrypted before being sent to IPFS. Implementation will also mention as to how only the authorized person can decrypt the information. We will use an open source library OpenPGP.js for this implementation.

Make sure to install OpenPGP and nano-ipfs-store libraries to your project by running following commands.

npm install — save openpgp
npm install - save nano-ipfs-store

How PGP encryption and decryption works?

How PGP Encryption/Decryption works?

Generate public keys and private keys

Private and public keys are to be generated for patient and medical provider respectively. These keys will be used to encrypt and decrypt the messages communicated between patient and medical provider.

Below code snippet creates option data for both type of users where in we need to add userIds details such as user name and email id, curve as “ed25519” that configures the approach to public-key cryptography strength based on the algebraic structure of elliptic curves over finite fields. And passphrase specified by user to lock the private key.

let optionsPatient = {
userIds: [{ username:'patient0001', email:'johndoe@medipedia.com' }],
curve: "ed25519",
passphrase: 'super long and hard to guess secret'
};
let optionsProvider = {
userIds: [{ username:'medicalProvider', email:'medicalprovider@medipedia.com' }],
curve: "ed25519",
passphrase: 'super long and hard to guess secret of provider'
};

Next step generates the public keys and private keys.

let patient = {
    privateKey: '',
    publicKey: ''
};
let medicalProvider = {
    privateKey: '',
    publicKey: ''
};
let patientKeys = openpgp.generateKey(optionsPatient).then(function(key) {
    patient.privateKey = key.privateKeyArmored; 
    patient.publicKey = key.publicKeyArmored;   
});
let medicalProviderKeys = openpgp.generateKey(optionsProvider).then(function(key) {
    medicalProvider.privateKey = key.privateKeyArmored; 
    medicalProvider.publicKey = key.publicKeyArmored;   
});

Below is the message in JSON format that needs to be encrypted and passed to medical service provider.

let msgRequest = {
    "patient_id":"0005",
    "gender":"female",
    "age_group":"25-30",
    "subject":"Enquiry on Lasek treatment",
    "arrival_from_date":"01-June-2018",
    "arrival_to_date":"10-June-2018",
    "estimated_budget":"100000",
    "currency":"KWR",
    "sentDate":"31-05-2018",
    "message_body":"I would like to visit for a treatment on Lasek."
};

Encrypt the Message

Once the public keys and privates keys are generated encrypt the message with public key of Medical provider as mentioned in the below code snippet.

const optionsPatient = {
    data: JSON.stringify(msgRequest),                             
    publicKeys: openpgp.key.readArmored(medicalProviderPublicKey).keys,  
    privateKeys: [privKeyObj] 
}
openpgp.encrypt(optionsPatient).then(ciphertext => {
    encrypted = ciphertext.data 
    return encrypted
})

Output of the Encrypted Message

-----BEGIN PGP MESSAGE-----
Version: OpenPGP.js v3.0.11
Comment: https://openpgpjs.org
wV4DbtWUcN6/VG0SAQdAlbkhxk6SWTObXMaLXBozrR7dfbz67otsFepd22x3
vW0wcmukCqPlkYuzPVnQlXGvEmHQOXI7sYxZQamPVw1mwdEkBWt48jOiV4tc
F3j2GiNF0sEUAdQ+uYy/971E2MPEFrmhAQWq3XeQi/vPky8xozncps2lmknV
hTgMty5Rb9v2wT7Z+SX2+YB5WiXSZHCUa4f5SRac6gqG/HVrKKN47lFy61zP
NN246QoKxIg+cxj7jW5oxuolUfVTEZ5J2GNF2MWStzOICjS9qqaneBrlgIw5
mQtumG4vR0M32NvPs9gWIJSSN1N8hPnttSjv/WJgy1SGy8qhQJxks6QmfyEl
h0rKOcGPiXFqbNaWzXwDwfe/OKFX+duO/psPSOGSPN/TxpQCBzR5X50ko5m+
xOb0AnVYK/YT7c1Z8IW82goqCdotXSBOQXC3uVai00JOMUpZztxOg0lq22Fb
+liMaSjYtvYZJLb14HbBxdfWwSeuHS5u4LfJUzXtESvPCZ7l/3VfTYuf4UlO
zO3ezGwmlUaMwRJk4Hpd/D5JYHuXQJ/aslKoOL/woo7UgadE5N3L1vpfduGU
1xsWTBtDDNuTp5vGsG75on1Gy/WT9YuxucE4gYAwOuGgNHrdHrFl9+uNqWkf
R4psFARuXNhmcU23AX+s7zawia8rVHJIFsMUEKyem/p06Mjh++ONmvCURjff
k7wJnTOBNH2ZEdkxxcwfSBe3HHoC3z/+mto4
=EoJe
-----END PGP MESSAGE-----

Decrypt the Message

And finally Medical provider can decrypt the message using his private key as mentioned in the below code snippet. Before Medical provider can decrypt the message, he needs to unlock the private key using his passphrase.

// Unlock the private key using passphrase
const providerPrivKeyObj = openpgp.key.readArmored(medicalProviderPrivateKey).keys[0]
await providerPrivKeyObj.decrypt(providerPassphrase)
// encrypted : It is the encrypted message
const optionsProvider = {
    message: openpgp.message.readArmored(encrypted),
    publicKeys: openpgp.key.readArmored(medicalProviderPublicKey).keys,
    privateKeys: [providerPrivKeyObj] 
}
openpgp.decrypt(optionsProvider).then(decryptedMessage => {
    console.log(JSON.parse(decryptedMessage.data))
    return decryptedMessage.data
})

Message Output after decryption

If medical provider has successfully decrypted the message it will be displayed as mentioned below.

{  
   "patient_id":"0005",
   "gender":"female",
   "age_group":"25-30",
   "subject":"Enquiry on Lasek treatment",
   "arrival_from_date":"01-June-2018",
   "arrival_to_date":"10-June-2018",
   "estimated_budget":"100000",
   "currency":"KWR",
   "sentDate":"31-05-2018",
   "message_body":"I would like to visit for a treatment on Lasek."
}

Full Code Example

Below is the full code example.

Conclusion

Before any information is stored in IPFS, encrypting it with the recipient’s public key plays a major role in securing it. Once the information is encrypted and stored in IPFS then hash is generated. This hash will further be used to retrieve the encrypted message. And recipient can use it’s private key to decrypt the encrypted message. Hence, only those can see the message content who are actually assigned to view the message.

There are numerous ways and libraries available to encrypt and decrypt information. One of the way is mentioned in the above example.

Care must be taken while persisting public key and private key of the users.

Note: Edits and suggestions are most welcome.