Шифровать отдельные строки в текстовом файле с помощью Node.js - PullRequest
1 голос
/ 22 апреля 2019

Я пытаюсь зашифровать каждую строку в текстовом файле, а не сам текстовый файл. Вот код, который у меня есть для шифрования одной строки текста.

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();
});

Я знаю, что я также могу шифровать, используя cipher.update(text) и cipher.final(), и я тоже попробовал этот метод, но безуспешно. Вопрос в том, как мне прочитать файл построчно и зашифровать каждую строку. Я пробовал оба метода, но это всегда приводит к шифрованию только одной строки или ошибкам. Я хотел бы иметь возможность сделать это с помощью преобразования потока, что-то вроде.

readStream
    .pipe(encryptLine)
    .pipe(writeStream)
    .on('finish', err => {
        if (err) console.log(err);
    });

Ответы [ 2 ]

1 голос
/ 23 апреля 2019

Я бы начал с реализации потока преобразования (или использования существующей библиотеки), чтобы прочитать файл построчно.

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();
        }
    });
}

Тогда я бы реализовал поток преобразования для шифрования каждой строки.

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();
        }
    });
}

Тогда вы можете просто pipe все в поток вывода (по желанию).

fs.createReadStream('input.txt', {encoding: 'utf8'})
    .pipe(toLines())
    .pipe(encryptLines(algorithm, derivedKey, iv))
    .pipe(fs.createWriteStream('output.txt'))
    .on('finish', () => console.log('done'));
0 голосов
/ 23 апреля 2019

Разобрался с решением для этого.Я переместил всю логику шифрования в функцию, включая create и end, и я делаю это для каждой строки в файле.Моя проблема заключалась в попытке повторно использовать шифр.

const encrypt = (line, thisTransform) => {
    crypto.pbkdf2(password, salt, iteration, keylen, digest, (error, derivedKey) => {
        const cipher = crypto.createCipheriv(algorithm, derivedKey, iv);

        let encrypted = '';
        cipher.on('readable', () => {
            while (null !== (chunk = cipher.read())) {
                encrypted += chunk.toString('base64');
            }
        });

        cipher.on('end', () => {
            thisTransform.push(`${encrypted}\n`);
        });
        cipher.write(line);
        cipher.end();
    });
};

let encryptLine = new stream.Transform();
encryptLine._transform = function(chunk, encoding, callback) {
    let rows = chunk
        .toString()
        .split('\n')
        .map(line => line.replace(/[\n\r]/g, ''))
        .forEach(line => {
            encrypt(line, this);
        });
};

readStream
    .pipe(encryptLine)
    .pipe(writeStream)
    .on('finish', err => {
        if (err) console.log(err);
    });
...