Conversation
WinZip AES uses AES-CTR, which has no chaining dependency between blocks - decrypting block n only requires the counter value for that block, not any preceding ciphertext or plaintext. Add _zip_winzip_aes_seek() to jump the cipher's internal counter/keystream state directly to an arbitrary byte offset, and wire ZIP_SOURCE_SEEK/ ZIP_SOURCE_TELL into the WinZip AES decode source accordingly. The one real constraint is the mandatory HMAC-SHA1 authentication code, which is computed over the ciphertext sequentially from the start and can't be verified for a chunk read out of order. Handle this exactly like zip_source_crc.c already handles the same situation for the CRC of a stored, unencrypted entry: track how much of the ciphertext has been fed to the HMAC contiguously from position 0, and silently skip verification instead of failing if a seek ever leaves a gap that's never filled in. A full, contiguous read from the start still verifies the HMAC exactly as before, including still catching a tampered file - only reads that actually skip around lose that guarantee, the same tradeoff already made for CRC. Also update zip_fseek()'s man page: it previously said compressed or encrypted data always errors out, which is no longer accurate. Fixes nih-at#336.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
WinZip AES uses AES-CTR, which has no chaining dependency between blocks - decrypting block n only requires the counter value for that block, not any preceding ciphertext or plaintext. This adds
_zip_winzip_aes_seek()to jump the cipher's internal counter/keystream state directly to an arbitrary byte offset, and wiresZIP_SOURCE_SEEK/ZIP_SOURCE_TELLinto the WinZip AES decode source accordingly, sozip_fseek()/zip_file_is_seekable()now work forSTOREd (uncompressed) entries encrypted with WinZip AES.The one real constraint is the mandatory HMAC-SHA1 authentication code, which is computed over the ciphertext sequentially from the start and can't be verified for a chunk read out of order. This is handled exactly like
zip_source_crc.calready handles the same situation for the CRC of a stored, unencrypted entry: the amount of ciphertext fed to the HMAC contiguously from position 0 is tracked, and verification is silently skipped (not failed) if a seek ever leaves a gap that's never filled in. A full, contiguous read from the start still verifies the HMAC exactly as before, including still catching a tampered file - only reads that actually skip around lose that guarantee, the same tradeoff already made for CRC.Also updates
zip_fseek()'s man page: it previously said compressed or encrypted data always errors out, which is no longer accurate.Fixes #336.
Test plan
ctest(196/196 tests pass)winzip_aes_seek.test,winzip_aes_seek_bad_hmac_full_read.test,winzip_aes_seek_bad_hmac_partial_read.test7zclang-format --dry-run --Werrorclean on all touched C/H files.mdoc/.man/.html) for the touched page🤖 Generated with Claude Code