Learn how to secure P2P file transfers within clients using IPFS (InterPlanetary File System) and blockchain private messaging.
This article takes you through the process of securing P2P communication within clients using a medium such as IPFS (InterPlanetary File System) and blockchain private messaging. Let’s try to develop an understanding of how this works.
Peer to Peer (or P2P) networks have distributed architecture at their core. A group of peers is working with each other instead of a centralized server. So, considering the specific scenario of data or file transfer in a P2P setup, each peer (or participant) can act both as the source of data and the consumer of data.
We primarily use IPFS as the underlying transport for connectivity and transfer of data between peers.
Now, as discussed, multiple peers have access to a file in a P2P setup – the question that arises is, will we be able to make a targeted file transfer to a particular peer securely without missing out on the advantages offered by this architecture?? The answer we get is yes, by using encryption techniques on our files.
The encryption technique that we use is PGP.
Pretty Good Privacy (PGP) is an encryption program that provides us a way to encrypt any sensitive information.
PGP is a good encryption technique to go with primarily due to 2 reasons. First, it uses a mix of both symmetric and asymmetric encryption. One only needs to share their cryptographic publicKey (from their cryptographic public/private pair generated by respective peers) and keep their privateKey secure without incurring enormous costs in terms of speed, which generally comes in such publicKey encryption. Second, it is an implementation by design that allows us to encrypt the same information, if required, to be targeted to multiple clients or peers at a time. This implementation lets us share a single encrypted message to be broadcasted across the network, and only the targeted ones can decrypt and make sense out of that data.
For demonstration purposes, we will be proceeding with IPFS upload and download cli calls. (Find more information here – <https://docs.ipfs.io/>)
We have divided the process into the following steps:
It can be generated using some information that uniquely identifies a client. It is a one-time process and is also a simple one:
The publicKey generated is the one that can be shared openly with others. And the privateKey needs to be kept safe and not shared with anyone. This one is used to decrypt the messages.
const openpgp = require('openpgp'); // Importing openpgp module.
(async () => {
const { privateKeyArmored, publicKeyArmored } = await openpgp.generateKey({
userIds: [{ name: 'Cristopher', email: 'real.cristopher@hmail.com' }],
curve: 'ed25519', // ECC curve name
passphrase: 'verySecurePassword'
});
console.log(privateKeyArmored); // PGP privateKey
console.log(publicKeyArmored); // PGP publicKey
})();
const openpgp = require('openpgp'); // Importing openpgp module.
const fs = require('fs');
(async () => {
const publicKeysArmored = [
`-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----`
]; // An Array consisting of Target(s) PGP publicKey(s)
const data = "This data needs to be securely transported."; // Data to be encrypted.
let publicKeys = [];
for (let index = 0; index < publicKeysArmored.length; index += 1) {
[publicKeys[index]] = (await openpgp.key.readArmored(publicKeysArmored[index])).keys;
}
const { data: encrypted } = await openpgp.encrypt({ // getting the encrypted data.
message: openpgp.message.fromText(message),
publicKeys,
});
const encryptedData = Buffer.from(encrypted).toString('base64'); // converting encrypted data to base64
fs.writeFile('encryptedFile.txt', encryptedData, 'base64' , (err)=> { // writing enrypted data to a file
if(err) console.log(err);
console.log('Encrypted file is ready.');
});
})();
// Considering an IPFS network is up and running at IPFS_URL.
ipfs add encryptedFile.txt
// This would return a hash say, QmWNj1pTSjbauDHpdyg5HQ26vYcNWnubg1JehmwAE9NnS9 for example.
This hash can be sent over to the target nodes using blockchain private messaging.
/* The hash obtained in step 2 has to used to download the file from ipfs. */
ipfs cat [[IPFS_HASH]] > encryptedMessage.txt"
const openpgp = require('openpgp');
const fs = require('fs');
(async () => {
const privateKeyArmored = `-----BEGIN PGP PRIVATE KEY BLOCK-----
...
-----END PGP PRIVATE KEY BLOCK-----`; // PGP privateKey of client.
const passPhrase = `verySecurePassword`; // passPhrase with which the PGP privateKey of client is encrypted with.
fs.readFile('encryptedMessage.txt', 'base64', (err, data)=>{
if(err) console.log(err);
else {
const { keys: [privateKey] } = await openpgp.key.readArmored(privateKeyArmored);
await privateKey.decrypt(passPhrase);
const encryptedDataInAscii = Buffer.from(data, 'base64').toString('ascii');
const { data: decrypted } = await openpgp.decrypt({
message: await openpgp.message.readArmored(encryptedDataInAscii),
privateKeys: (await openpgp.key.readArmored(privateKeyArmored)).keys,
});
console.log(decrypted); // The decrypted message.
}
})
})();
We care about each bit of critical data flowing across our and our partners’ infrastructure. So, to become a secure haven, we have also identified and unleashed the benefits of blockchain private messaging, which allows us to share information with a specific target(s) without broadcasting it throughout our network, ensuring encrypted data reaches only rightful stakeholders.
So, at Skeps, for sensitive information, we transmit encrypted content over the blockchain as private messages and for, non-sensitive information, we use the approach that has been discussed earlier, which is encrypted messages via IPFS.
We also ensure that the passPhrases and privateKeys of each participant of our network are created and maintained with the latest and most secure algorithms/technologies.