Home > Software design >  How to encrypt and decrypt a large file using the AES-CBC algorithm with encryption progress/status
How to encrypt and decrypt a large file using the AES-CBC algorithm with encryption progress/status

Time:10-17

I'm using nodejs built-in crypto, zlib and fs package to encrypt a large file using these codes.

import fs from 'fs';
import zlib from 'zlib';
import crypto from 'crypto';

const initVect = crypto.randomBytes(16);
const fread = fs.createReadStream('X:/File.mp4');
const fwrite = fs.createWriteStream('X:/File.mp4.enc');
const gzipStream = zlib.createGzip();
const hashedPassword = crypto.createHash('sha256').update('SomePassword').digest();
const cipher = crypto.createCipheriv(
    'aes-256-cbc',
    hashedPassword,
    initVect
);

fread.pipe(gzipStream).pipe(cipher).pipe(fwrite);

But I don't know how to add an encryption progress/status indicator, since a large file will take a lot of time to encrypt I want to show encryption progress to the user in the console.

Can you guys tell me how to achieve this?

CodePudding user response:

You can achieve this using stream Transform(). Create a new stream Transform(), get the processed chunk length in it, then simply calculate progress with chunk length and file size, then add this new transform to your existing pipe.

Like this:-

import fs from 'fs';
import zlib from 'zlib';
import crypto from 'crypto';
import { TransformCallback, Transform } from 'stream';

const initVect = crypto.randomBytes(16);
const fread = fs.createReadStream('X:/File.mp4');
const fwrite = fs.createWriteStream('X:/File.mp4.enc');
const gzipStream = zlib.createGzip();
const hashedPassword = crypto.createHash('sha256').update('SomePassword').digest();
const cipher = crypto.createCipheriv(
    'aes-256-cbc',
    hashedPassword,
    initVect
);

const fileSize = fs.statSync(fread.path).size;
let processedBytes = 0;
const progressPipe = new Transform({
    transform(
        chunk: Buffer,
        _encoding: BufferEncoding,
        callback: TransformCallback
    ) {
        processedBytes  = chunk.length;
        console.log(
            `${Math.floor((processedBytes / fileSize) * 100)}%`
        );
        this.push(chunk);
        callback();
    },
});

fread.pipe(progressPipe).pipe(gzipStream).pipe(cipher).pipe(fwrite);
  • Related