Как в node js прочитать опеределенное количество байт из потока?

Пытаюсь зашифровать картинку.

Вкладываю iv вектор в файл

const iv = "Тут рандомные байты"
const read = fs.createReadStream(fileRead);
const write = fs.createWriteStream(fileWrite);

write.write(iv)
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);

await stream.pipeline(read, cipher, write);

Все записывает хорошо.

Для расшифровки нужно считать iv (его длинну я знаю) и продолжить расшифровку потока без iv.

Как считать только iv?

stream.read(10) не читает 10 байт, возвращая null;


Ответы (3 шт):

Автор решения: vsemozhebuty

У меня когда-то была похожая задача: удаление BOM из потока перед чтением, и я даже написал тест для этого алгоритма для Node.js. Возможно, он вам поможет:

https://github.com/nodejs/node/commit/ea725eda426add1d684c80f2c2c585cd2ca797c9

→ Ссылка
Автор решения: nörbörnën
  • Создаём первый readable stream и одним махом читаем первые 100 байт.

  • Создаём второй readable stream, указывая позицией начала чтения следующий байт.

const fs = require('fs');
const path = require('path');
const { pipeline } = require('stream');

(async () => {

  const filepath = path.join(process.cwd(), 'large-file.json');

  const stream1 = fs.createReadStream(
    filepath,
    {
      start: 0,
      end: 99,
      highWaterMark: 100
    }
  );
  const firstByte = await stream1[Symbol.asyncIterator]().next();
  console.log(`${filepath} >>> ${firstByte.value}`);

  const stream2 = fs.createReadStream(
    filepath,
    {
      start: 100
    }
  );

  await pipeline(stream2, cipher, write);

})();

UPD1: Допустим stream приходит из сторонней библиотеки, как можно считать первые байты, а следующие данные как-то использовать/трансформировать?

const fs = require('fs');
const path = require('path');

(async () => {

  const inputfile = path.join(__dirname, 'input.txt');

  let iv;
  const readStream = fs.createReadStream(inputfile);
  readStream.once('readable', () => {
    iv = readStream.read(6);

    // may be your code here 1
    // await pipeline(stream2, cipher, write);
  });

  // my example
  for await (const chunk of readStream) {
    console.log(`iv=${iv}, chunk=${chunk}`);
  }

  // may be your code here 2


})();
iv=123456, chunk=aaaa
iv=123456, chunk=aaaaaaaaaa
iv=123456, chunk=aaafffffff
iv=123456, chunk=gyrtgejeji
iv=123456, chunk=eejiwriuwe
iv=123456, chunk=iweuri'
→ Ссылка
Автор решения: Lasna1

Решил так:

async _decryptStream(data) {
    let writeStream = fs.createWriteStream("test.png");
    let iv = "";
    ALGORITHM= "aes-256-cbc";
    let key = "key";
    let decipher;

    const test = new stream.Transform({
        transform: (chunk, encoding, done) => {
            if (!iv) {
                iv = chunk.slice(0, 16);
                chunk = chunk.slice(16, chunk.length);
                decipher = this._getAesDecipher(ALGORITHM, key, iv);
            }
            done(null, decipher.update(chunk));
        },
    });

    await stream.pipeline(data, test, writeStream);
};
→ Ссылка