Encrypting files with Node.js and storing in IPFS

I’m extremely new to encryption and I’ve been following tutorials online. I’m trying to encrypt a file using crypto module of Node.js before uploading it to IPFS. Here’s my code:

const encrypt = (data) => {
    const crypto = require('crypto');
    
    //compute hash and iv
    const algorithm = 'aes-256-ctr';
    const iv = crypto.randomBytes(16);
    key = crypto.createHash('sha256').update(data).digest('base64').substring(0,32);

    const cipher = crypto.createCipheriv(algorithm, key, iv);
    const result = iv + cipher.update(data) + cipher.final('hex');

    return result;
}

uploadFile = async() => {    
    //encrypt file
    const data = credential.files[0];
    const encryptedFile = encrypt(data);

    //upload encrypted file in IPFS
    const file = new Moralis.File(data.name, encryptedFile);
    await file.saveIPFS();
    console.log(file.ipfs(), file.hash());
    return file.ipfs();
}

I got this error

TypeError: Cannot create a Parse.File with that data.

I know I’m not getting the right type of data in EncryptedFile but I have no idea have to fix it. I tried displaying EncryptedFile in console and it only shows the IV, but cipher.update(data) and cipher.final() is not returning anything.

const file = new Moralis.File(data.name, result);

result should be encryptedFile, no?

yes, I actually did edit that already. But i got the same result.

So data is valid and it works if you put in new Moralis.File directly?

1 Like

Yes, but it won’t work after encrypting it.

What is the tutorial you followed? Try this one or this one.

Hi! Following the this tutorial, I edited the code:

const encrypt = (data) => {
    const crypto = require('crypto');
    
    //compute hash and iv
    const algorithm = 'aes-256-ctr';
    const iv = crypto.randomBytes(16);
    key = crypto.createHash('sha256').update(data).digest('base64').substring(0,32);

    const cipher = crypto.createCipheriv(algorithm, key, iv);
    const result = Buffer.concat([iv, cipher.update(data), cipher.final()]);

    return result;
}

uploadFile = async() => {    
    //encrypt file
    const data = credential.files[0];
    const encryptedFile = encrypt(data);

    //upload encrypted file in IPFS
    const file = new Moralis.File(data.name, encryptedFile);
    await file.saveIPFS();
    console.log(file.ipfs(), file.hash());
    return file.ipfs();
}

However, I am still getting the same TypeError: Cannot create a Parse.File with that data. error

What’s the type of encryptedFile here ?
Also you can push to ipfs directly without storing the file on moralis

encryptedFile is an object

Can you drop an example of the object and also the type before encryption

1 Like

The type before encryption is also an object.
I tried to console.log(encryptedFile) and I got this:

Uint8Array(16) [188, 113, 72, 47, 45, 135, 235, 96, 210, 48, 168, 201, 175, 54, 22, 251, buffer: ArrayBuffer(16), byteLength: 16, byteOffset: 0, length: 16, Symbol(Symbol.toStringTag): 'Uint8Array']
0: 188
1: 113
2: 72
3: 47
4: 45
5: 135
6: 235
7: 96
8: 210
9: 48
10: 168
11: 201
12: 175
13: 54
14: 22
15: 251
offset: (...)
parent: (...)
buffer: 
ArrayBuffer(16)
byteLength: 16
byteOffset: 0
length: 16
Symbol(Symbol.toStringTag): "Uint8Array"
[[Prototype]]: Uint8Array

Where did you get your initial file from ?
Submitted through client or read from a directory ?

This looks like binary data, 16 bytes in particular. What you expect as encrypted data?

The initial file is submitted through client. I followed this tutorial.

this worked for me in the past, not sure if it helps:

I actually tried this before posting. I got the same error so I assumed that method is used for encrypting strings.

you could encode the data to base64, then encrypt it (not optimal), maybe it is easier

1 Like

thank you, i will try this.