I'm trying to encrypt each row within a text file, not the text file itself. Here is the code I have for encrypting a single row of text.
crypto.pbkdf2(password, salt, iteration, keylen, digest, (error, derivedKey) => {
const iv = Buffer.from('myiv', 'hex');
const cipher = crypto.createCipheriv(algorithm, derivedKey, iv);
let encryptThis = `Encrypt me`;
let encrypted = '';
cipher.on('readable', () => {
let chunk;
while (null !== (chunk = cipher.read())) {
encrypted += chunk.toString('base64');
}
});
cipher.on('end', () => {
console.log(`Example string: ${encryptThis}`);
});
cipher.write(encryptThis);
cipher.end();
});
I know I can also encrypt using cipher.update(text)
and cipher.final()
and have tried this method too with no luck. The issue is how do I read a file line by line and encrypt each row. I've tried both methods, but it always results in only one line being encrypted or errors. I'd like to be able to do this with a stream transform, something like.
readStream
.pipe(encryptLine)
.pipe(writeStream)
.on('finish', err => {
if (err) console.log(err);
});
I would start by first implementing a transform stream (or utilize an existing library) to read the file line-by-line.
function toLines() {
let line = '';
return new Transform({
decodeStrings: false,
readableObjectMode: true,
transform(chunk, encoding, callback) {
const lines = chunk.split(/\r?\n/g);
line += lines.shift();
while (lines.length) {
this.push(line);
line = lines.shift();
}
callback();
},
flush(callback) {
if (line) {
this.push(line);
}
callback();
}
});
}
Then I would implement a transform stream for encrypting each line.
function encryptLines(algorithm, derivedKey, iv) {
return new Transform({
readableObjectMode: false,
writableObjectMode: true,
transform(line, encoding, callback) {
const cipher = crypto.createCipheriv(algorithm, derivedKey, iv);
this.push(cipher.update(line, encoding, 'base64'));
this.push(cipher.final('base64'));
this.push('\n');
callback();
}
});
}
Then then you can simply pipe
everything to the output stream (as desired).
fs.createReadStream('input.txt', {encoding: 'utf8'})
.pipe(toLines())
.pipe(encryptLines(algorithm, derivedKey, iv))
.pipe(fs.createWriteStream('output.txt'))
.on('finish', () => console.log('done'));