brendan-duncan/archive

Unzip protected file failed, Please help me. Thanks a lot

Closed this issue · 12 comments

comk commented

Firstly, I use below method to zip a file.

// this works fine, and can ben extract by zip tool
ZipEncoder(password: unzipPwd).encode(archive, output: ofs);

And, when I use below method to unzip the file:

//this throws a exception "Exception: macs don't match"
ZipDecoder().decodeBuffer(InputFileStream(zipFilePath), verify:false, password: unzipPwd);

It seems like ZipDecoder can't work with file that zipped by ZipEncoder when using password.

Are you using the latest 3.4.10 version? There was an error with password decoding that was fixed in that version.

comk commented

Are you using the latest 3.4.10 version? There was an error with password decoding that was fixed in that version.

Yes, I am using 3.4.10 version. This happened with 3.4.10 .

comk commented

I can unzip file with password successfully, and the file was zip by a tool.
but failed if the file was zip by 3.4.10 version.

I encountered the same issue with version 3.4.10.

I using the 'encode password' test case from the archive library and found that it passed the test. However, when I modified the test case from:

final arc = ZipDecoder().decodeBytes(zipData, password: 'abc123');
expect(arc.numberOfFiles(), equals(1));
var arcData = arc.fileData(0);
expect(arcData.length, equals(bdata.length));
for (var i = 0; i < arcData.length; ++i) {
  expect(arcData[i], equals(bdata.codeUnits[i]));
}

to:

final outputPath = p.join(testDirPath, 'out/test');
await extractFileToDisk(
  zipPath,
  outputPath,
  password: 'abc123',
  asyncWrite: true,
);

I was able to reproduce the "macs don't match" issue.

I suspect it's related to the decodeBuffer method inside the extractFileToDisk function.

So I copied the extractFileToDisk method into my own code, and by changing:

final input = InputFileStream(archivePath);
archive = ZipDecoder().decodeBuffer(input, password: password);

to:

final file = File(archivePath);
final bytes = await file.readAsBytes();
archive = ZipDecoder().decodeBytes(bytes, password: password);

I could successfully unzip the archive without errors.

Keeping extractArchiveToDisk unchanged, if I comment out the following section in the ZipFile class:

if (!Uint8ListEquality.equals(dataMac.toUint8List(), aes.mac)) {
  throw Exception('macs don\'t match');
}

The modified 'encode password' test case mentioned earlier can unzip the abc.txt file without errors. However, upon opening the abc.txt file, I noticed that its content has changed to:

hello worldׇ�H±Ã6ˆ`o

I hope this information helps.

I encountered the same problem with version 3.4.10 on linux 5.4.0-150-generic

$ cat pubspec.yaml |egrep archive
  archive: ^3.4.10
$ cat /etc/issue && uname -r
Ubuntu 22.04.1 LTS \n \l

5.4.0-150-generic
$ dart --version
Dart SDK version: 3.3.0 (stable) (Tue Feb 13 10:25:19 2024 +0000) on "linux_x64"
comk commented

I encountered the same issue with version 3.4.10.

I using the 'encode password' test case from the archive library and found that it passed the test. However, when I modified the test case from:

final arc = ZipDecoder().decodeBytes(zipData, password: 'abc123');
expect(arc.numberOfFiles(), equals(1));
var arcData = arc.fileData(0);
expect(arcData.length, equals(bdata.length));
for (var i = 0; i < arcData.length; ++i) {
  expect(arcData[i], equals(bdata.codeUnits[i]));
}

to:

final outputPath = p.join(testDirPath, 'out/test');
await extractFileToDisk(
  zipPath,
  outputPath,
  password: 'abc123',
  asyncWrite: true,
);

I was able to reproduce the "macs don't match" issue.

I suspect it's related to the decodeBuffer method inside the extractFileToDisk function.

So I copied the extractFileToDisk method into my own code, and by changing:

final input = InputFileStream(archivePath);
archive = ZipDecoder().decodeBuffer(input, password: password);

to:

final file = File(archivePath);
final bytes = await file.readAsBytes();
archive = ZipDecoder().decodeBytes(bytes, password: password);

I could successfully unzip the archive without errors.

Thank you, this works fine.

I encountered the same issue with version 3.4.10.
I using the 'encode password' test case from the archive library and found that it passed the test. However, when I modified the test case from:

final arc = ZipDecoder().decodeBytes(zipData, password: 'abc123');
expect(arc.numberOfFiles(), equals(1));
var arcData = arc.fileData(0);
expect(arcData.length, equals(bdata.length));
for (var i = 0; i < arcData.length; ++i) {
  expect(arcData[i], equals(bdata.codeUnits[i]));
}

to:

final outputPath = p.join(testDirPath, 'out/test');
await extractFileToDisk(
  zipPath,
  outputPath,
  password: 'abc123',
  asyncWrite: true,
);

I was able to reproduce the "macs don't match" issue.
I suspect it's related to the decodeBuffer method inside the extractFileToDisk function.
So I copied the extractFileToDisk method into my own code, and by changing:

final input = InputFileStream(archivePath);
archive = ZipDecoder().decodeBuffer(input, password: password);

to:

final file = File(archivePath);
final bytes = await file.readAsBytes();
archive = ZipDecoder().decodeBytes(bytes, password: password);

I could successfully unzip the archive without errors.

Thank you, this works fine.

Unfortunately, it is difficult to say the same about memory management. With the current working method, data is written to memory, leading to significant memory usage. I am also encountering the same problem. My archive version is 3.5.1. According to the release notes, the bug has been fixed, but the same issue persists. This error only occurs when running stream-based processes. This is a critical issue for us.

Sorry I haven't gotten back to this issue sooner. I'll get it fixed.

Fix is in git. I'll publish the fix soon. Sorry it took so long.

Fix is in git. I'll publish the fix soon. Sorry it took so long.

I wanted to extend my sincere thanks for addressing the password issue with stream-based archive processing. The problem has been resolved with the commit 4a21eaecd5e696f6fe85f19ea74745eaaca0910a. I have tested the fix, and it works perfectly. This fix is very important to us and we truly appreciate your prompt response and efforts.
Thank you again for your excellent support.

comk commented

Thank you for your excellent support.