Skip to content

Commit

Permalink
#30 fixes for ZIp64 handling (completely overridden _writeCentralDire…
Browse files Browse the repository at this point in the history
…ctory until fix is introduced to archive)
  • Loading branch information
artem-karpenko committed Jan 16, 2022
1 parent 7f53e37 commit e833e5d
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 2 deletions.
96 changes: 95 additions & 1 deletion lib/aes/zip-aes-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const AesHmacEtmStream = require('./aes-hmac-etm-stream');
const ZipStream = require('zip-stream');
const {DeflateCRC32Stream, CRC32Stream} = require('crc32-stream');
var crc32 = require('buffer-crc32');
const constants = require("compress-commons/lib/archivers/zip/constants");
const zipUtil = require("compress-commons/lib/archivers/zip/util");

const ZIP_AES_METHOD = 99;

Expand Down Expand Up @@ -42,13 +44,105 @@ ZipAesStream.prototype._writeLocalFileHeader = function (ae) {

// set AES-specific fields
gpb.useEncryption(true);
ae.setExtra(_buildAesExtraField(ae));
ae.setExtra(Buffer.concat([ae.getExtra(), _buildAesExtraField(ae)]));
ae.setMethod(ZIP_AES_METHOD);
ae.setVersionNeededToExtract(51);

ZipStream.prototype._writeLocalFileHeader.call(this, ae);
};

ZipAesStream.prototype._writeCentralFileHeader = function(ae) {
var gpb = ae.getGeneralPurposeBit();
var method = ae.getMethod();
var offsets = ae._offsets;

var size = ae.getSize();
var compressedSize = ae.getCompressedSize();

if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) {
size = constants.ZIP64_MAGIC;
compressedSize = constants.ZIP64_MAGIC;

ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64);

var extraBuf = Buffer.concat([
zipUtil.getShortBytes(constants.ZIP64_EXTRA_ID),
zipUtil.getShortBytes(24),
zipUtil.getEightBytes(ae.getSize()),
zipUtil.getEightBytes(ae.getCompressedSize()),
zipUtil.getEightBytes(offsets.file)
], 28);

ae.setExtra(Buffer.concat([ae.getExtra(), extraBuf]));
}

// signature
this.write(zipUtil.getLongBytes(constants.SIG_CFH));

// version made by
this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));

// version to extract and general bit flag
this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
this.write(gpb.encode());

// compression method
this.write(zipUtil.getShortBytes(method));

// datetime
this.write(zipUtil.getLongBytes(ae.getTimeDos()));

// crc32 checksum
this.write(zipUtil.getLongBytes(ae.getCrc()));

// sizes
this.write(zipUtil.getLongBytes(compressedSize));
this.write(zipUtil.getLongBytes(size));

var name = ae.getName();
var comment = ae.getComment();
var extra = ae.getCentralDirectoryExtra();

if (gpb.usesUTF8ForNames()) {
name = Buffer.from(name);
comment = Buffer.from(comment);
}

// name length
this.write(zipUtil.getShortBytes(name.length));

// extra length
this.write(zipUtil.getShortBytes(extra.length));

// comments length
this.write(zipUtil.getShortBytes(comment.length));

// disk number start
this.write(constants.SHORT_ZERO);

// internal attributes
this.write(zipUtil.getShortBytes(ae.getInternalAttributes()));

// external attributes
this.write(zipUtil.getLongBytes(ae.getExternalAttributes()));

// relative offset of LFH
if (offsets.file > constants.ZIP64_MAGIC) {
this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC));
} else {
this.write(zipUtil.getLongBytes(offsets.file));
}

// name
this.write(name);

// extra
this.write(extra);

// comment
this.write(comment);
};

ZipAesStream.prototype._appendBuffer = function(ae, source, callback) {
ae.setSize(source.length);
ae.setCompressedSize(source.length + 28);
Expand Down
4 changes: 3 additions & 1 deletion support/issue-16.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ const archiver = require('archiver');
const fs = require('fs');

archiver.registerFormat('zip-encrypted', require('../'));
let archive = archiver.create('zip-encrypted', {zlib: {level: 0}, encryptionMethod: 'aes256', password: '123'});
let archive = archiver.create('zip-encrypted', {
zlib: {level: 4}, encryptionMethod: 'aes256', password: '123'
});
archive.append(fs.readFileSync('C:\\ffmpeg-20190428-45048ec-win64-static.zip'), {name: 'backupZip.zip'});
archive.finalize();
let out = fs.createWriteStream('aes123.zip');
Expand Down
29 changes: 29 additions & 0 deletions support/issue-30.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const archiver = require('archiver');
const fs = require('fs');

const LARGE_FILE = 'C:\\Users\\gooyo\\Downloads\\Blade Runner 2049 (2017) BDRip 720p.mkv';

// register format for archiver
archiver.registerFormat(
'zip-encrypted',
require('../')
);

// create archive and specify method of encryption and password
const archive = archiver.create('zip-encrypted', {
zlib: { level: 4, chunkSize: 10 * 1024 * 1024 },
encryptionMethod: 'aes256',
password: Buffer.from('123')
});

archive.on('error', err => {
console.log(err);
});

archive.append(fs.createReadStream(LARGE_FILE), { name: 'data.mkv' });
// archive.append(fs.createReadStream(LARGE_FILE), { name: 'data.mkv' });
// archive.append(fs.createReadStream('./issue-30.js'), { name: 'data.txt' });
archive.finalize();

let out = fs.createWriteStream('aes-large-orig.zip');
archive.pipe(out);

0 comments on commit e833e5d

Please sign in to comment.