node.js - დაუჭერელი სიტუაცია ან შეუძლებელია მონაცემების აუთენტიფიკაცია, როდესაც გამოიყენება NodeJS (Typescript-ით) სტრიმები და aes-gcm ალგორითმი


ფაილის დაპატარავებისა და გახსნისას Cipher/Decipher სტრიმის გამოყენებით, ყოველთვის მივყავარ შემდეგ შეცდომას: Unsupported state or unable to authenticate data.

ეს არის კოდი (პაირია ნაკადის და არა-ნაკადის ვერსიებს შორის):

არასტრიმ ვერსია

const key = Buffer.alloc(256 / 8);

const text = 'my secret message';
const encrypter = crypto.createCipheriv('aes-256-gcm', key, Buffer.alloc(16));

let encrypted = encrypter.update(text, 'utf8', 'hex');
encrypted += encrypter.final('hex');
const tag = encrypter.getAuthTag();

console.log('Encrypted!', encrypted);

const decrypter = crypto.createDecipheriv('aes-256-gcm', key, Buffer.alloc(16));
decrypter.setAuthTag(tag);
let decrypted = decrypter.update(encrypted, 'hex', 'utf8');
decrypted += decrypter.final('utf8');

console.log('Decrypted', decrypted);

რომელიც სრულყოფილად იბეჭდება Decrypted my secret message სხვანაირად...

სტრიმის ვერსია

const key = Buffer.alloc(256 / 8);
const text = 'my secret message';

const cipher = crypto.createCipheriv('aes-256-gcm', key, Buffer.alloc(16));
let encrypted = '';
cipher.on('data', (data: Buffer) => 
{
    encrypted += data.toString('hex');
});

cipher.on('end', () => 
{
    const tag = cipher.getAuthTag();

    const decipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.alloc(16));
    decipher.setAuthTag(tag);

    let decrypted = '';
    decipher.on('readable', () => 
    {
        const data = decipher.read() as Buffer;
        if(data)
            decrypted += data.toString('utf8');
    });

    decipher.on('end', () => 
    {
        console.log(decrypted);
    });

    fromString(encrypted).pipe(decipher);
});

ვივარაუდებ, რომ უნარიანი ფუნქცია fromString არჩევილია from2 პაკეტის მაგალითებიდან

import * as from from 'from2';

function fromString(text: string) 
{
    return from((size, next) => 
    {
        if (text.length <= 0) 
            return next(null, null);

        const chunk = text.slice(0, size);
        text = text.slice(size);

        next(null, chunk);
    });
}

არის რაიმე მინიშნება, რატომ არ მუშაობს ეს სწორად? დიდი მადლობა. ამაზე ძალიან შემომდაჩნდა.

პასუხი #1

სინამდვილეში, შემდეგი კოდი ფაილებზე კარგად მუშაობს. არ ვიცი, რა განსხვავებაა ამას და იმაზე, რასაც მე დავდებდი...

const algorithm = 'aes-256-gcm';
const iv = Buffer.alloc(16);
const key = Buffer.alloc(256/8);

const cipher = crypto.createCipheriv(algorithm, key, iv);
const read_stream = fs.createReadStream(path.resolve(os.homedir(), 'Desktop', 'abstract.pdf'));
const encrypted_write_stream = fs.createWriteStream(path.resolve(os.homedir(), 'Desktop', 'abstract.enc.pdf'));

cipher.on('finish', () => 
{
    const tag = cipher.getAuthTag();
    console.log('File encrypted. Tag is', tag.toString('hex'));

    const decipher = crypto.createDecipheriv(algorithm, key, iv);
    decipher.setAuthTag(tag);

    const encrypted_read_stream = fs.createReadStream(path.resolve(os.homedir(), 'Desktop', 'abstract.enc.pdf'));
    const write_stream = fs.createWriteStream(path.resolve(os.homedir(), 'Desktop', 'abstract.decrypted.pdf'));

    decipher.on('error', console.error);
    decipher.on('finish', () => 
    {
        console.log('Decrypted successfully');
    });

    encrypted_read_stream.pipe(decipher).pipe(write_stream);
});

read_stream.pipe(cipher).pipe(encrypted_write_stream);