I want to encrypt file before storing into IPFS network so that only person who is uploading a file should be able to decrypt.


You can use the public key to encrypt it so that only the private key can decrypt it.

I wrote this based on npmjs/eth-crypto, it takes the user's ethereum keypair. It's not super optimal but it will work. Ideally you'd want people to have a second key pair derived from the same seed but ECDH.


  • ECDSA is a digital signature algorithm
  • ECIES is an Integrated Encryption scheme
  • ECDH is a key secure key exchange algorithm

You could also have the user encrypt it on the client through AES.

import {publicKeyConvert} from 'secp256k1'
import {encrypt, decrypt} from 'eccrypto'

* @method encryptMessage - Encrypted a signed message
* @param {Object} payload - Stringified JSON object containing the message and optional signature
* @param {Object} wallet - Wallet (public Key) to encrypt message with
* @returns {Object} - Object with encrypted values as hex
const encryptMessage = async (payload, wallet) => {
  return await encryptWithPublicKey(wallet.publicKey, payload)

    * @method decryptMessage - Decrypt an encrypted credential/message
    * @param {Object} encryptedPayload - Object with the encrypted credentials
    * @param {wallet} wallet - Wallet containing the privatekey associated with the publickey the message was encrypted with
    * @returns {Object} - Object containing the decrypted values
    const decryptMessage = async (encryptedPayload, wallet) => await decryptWithPrivateKey(wallet.privateKey, encryptedPayload)

* @method encryptWithPublicKey
* @param {String} pubKey - Compressed 33byte public key starting with 03 or 02
* @param {Object} message - message object to encrypt
* @returns {String} - Stringified cipher
function encryptWithPublicKey(pubKey, message) {
    pubKey = pubKey.substring(2)
    pubKey = publicKeyConvert(new Buffer(pubKey, 'hex'), false).toString('hex')
    pubKey = new Buffer(pubKey, 'hex')
    return encrypt(
    ).then(encryptedBuffers => {
        const cipher = {
            iv: encryptedBuffers.iv.toString('hex'),
            ephemPublicKey: encryptedBuffers.ephemPublicKey.toString('hex'),
            ciphertext: encryptedBuffers.ciphertext.toString('hex'),
            mac: encryptedBuffers.mac.toString('hex')
        // use compressed key because it's smaller
        const compressedKey = publicKeyConvert(new Buffer(cipher.ephemPublicKey, 'hex'), true).toString('hex')

        const ret = Buffer.concat([
            new Buffer(cipher.iv, 'hex'), // 16bit
            new Buffer(compressedKey, 'hex'), // 33bit
            new Buffer(cipher.mac, 'hex'), // 32bit
            new Buffer(cipher.ciphertext, 'hex') // var bit

        return ret

* @method decryptWithPrivateKey decript an EC publicKey encrypted message with the associated private key
* @param {String} privateKey - the privatekey to decrypt with, including '0x' prefix
* @param {String} encrypted - the stringified cipher to decrypt
* @returns {Object} - the decrypted message

function decryptWithPrivateKey(privateKey, encrypted) {
    const buf = new Buffer(encrypted, 'hex');
    encrypted = {
        iv: buf.toString('hex', 0, 16),
        ephemPublicKey: buf.toString('hex', 16, 49),
        mac: buf.toString('hex', 49, 81),
        ciphertext: buf.toString('hex', 81, buf.length)
    // decompress publicKey
    encrypted.ephemPublicKey = publicKeyConvert(new Buffer(encrypted.ephemPublicKey, 'hex'), false).toString('hex')
    const twoStripped = privateKey.substring(2)
    const encryptedBuffer = {
        iv: new Buffer(encrypted.iv, 'hex'),
        ephemPublicKey: new Buffer(encrypted.ephemPublicKey, 'hex'),
        ciphertext: new Buffer(encrypted.ciphertext, 'hex'),
        mac: new Buffer(encrypted.mac, 'hex')
    return decrypt(
        new Buffer(twoStripped, 'hex'),
    ).then(decryptedBuffer => decryptedBuffer.toString());

Not the answer you're looking for? Browse other questions tagged or ask your own question.