(NODEJS) AES-256-GCM解密后破解pdf,gzip,png编码

(NODEJS) AES-256-GCM break pdf,gzip,png encoding after decryption

我希望能得到帮助,因为我不知道为什么我的 AES-GCM 实现会破坏文件编码。
我有一个 API,它使用 1 个函数来 encrypt/decrypt 和 AES-256-GCM。 (使用 KEY=32 个随机字节的缓冲区)

函数如下:

const aes256gcm = (key) => {
    const ALGO = 'aes-256-gcm';

    const encrypt = (str) => {
        try {
            const salt = crypto.randomBytes(64);
            const iv =  crypto.randomBytes(32);
            let derivedkey = crypto.pbkdf2Sync(key, salt, 55000, 32, 'sha512');
            const cipher = crypto.createCipheriv(ALGO, derivedkey, iv);
            let encrypted = Buffer.concat([cipher.update(str), cipher.final()]);
            const tag = cipher.getAuthTag();
            let buffer = Buffer.concat([salt, iv, encrypted]);
            encrypted = {
                tag: tag,
                buffer: buffer
            }
            return encrypted;
        } catch (e) {
            console.log(e);
        }
    };

    const decrypt = (data, authTag) => {
        try {
            const salt = data.slice(0, 64);
            const iv = data.slice(64, 96);
            const text = data.slice(96, data.length);
            authTag = new Buffer.from(authTag, 'base64');
            let derivedkey = crypto.pbkdf2Sync(key, salt, 55000, 32, 'sha512');
            let decipher = crypto.createDecipheriv(ALGO, derivedkey, iv);
            decipher.setAuthTag(authTag);
            let decrypted = decipher.update(text, 'binary') + decipher.final();
            return decrypted;
        } catch (e) {
            console.log(e);
        }
    };

    return {
        encrypt,
        decrypt
    };
};

我用这段代码加密并写入文件结果:

const aesCipher = aes.aes256gcm(aes.loadKey(path.resolve(__dirname, `key`)));
            const encrypted = aesCipher.encrypt(file.data);
            if (encrypted !== undefined) {
                fs.writeFile(`${file.name}.enc`, encrypted.buffer, function (err) {
                    if (err) return console.log(err);
                    console.log(`${file.name}.enc successfully created`);
                });
            }

最后我解密并将内容写入文件:

const aesCipher = aes.aes256gcm(aes.loadKey(path.resolve(__dirname, `key`)));
        let filename = 'test1.gz';
        let authTag = 'puI0FfV4Btiy7iPiZFbwew==';
        let encrypted = fs.readFileSync(path.resolve(__dirname, `test1.gz.enc`));
        const decrypted = aesCipher.decrypt(encrypted, authTag);
        if (decrypted !== undefined) {
            const file = fs.createWriteStream(filename);
            file.write(new Buffer.from(decrypted, 'ascii'), function (err) {
                if (err) return console.log(err);
                console.log(`Successfully decrypted`);
                file.close();
            });
            res.send({
                status: true,
                message: 'File is decrypted',
            });
        }

我的 input/output 文件的差异: Diff

所以,我做错了什么?我的加密过程好吗?为什么这只适用于 .txt 文件?

谢谢!

我认为对你的解密函数做一个相当小的改动应该可以解决这个问题,如果你只是将它更新为:

const decrypt = (data, authTag) => {
    try {
        const salt = data.slice(0, 64);
        const iv = data.slice(64, 96);
        const text = data.slice(96, data.length);
        authTag = new Buffer.from(authTag, 'base64');
        let derivedkey = crypto.pbkdf2Sync(key, salt, 55000, 32, 'sha512');
        let decipher = crypto.createDecipheriv(ALGO, derivedkey, iv);
        decipher.setAuthTag(authTag);
        let decrypted = Buffer.concat([decipher.update(text), decipher.final()]);
        return decrypted;
    } catch (e) {
        console.log(e);
    }
};

我认为之前的实现没有正确连接 non-text 个文件的结果。