fix: unwrap data.bin from zip in Opened.decrypt uuid mode#67
Merged
Conversation
Restores symmetry with Sealed.upload() data: mode, which wraps raw bytes
as a single-entry zip named data.bin. When Opened.decrypt() sees a uuid
result whose central directory is exactly ['data.bin'], it now returns
DecryptDataResult { plaintext, sender } instead of forcing consumers to
walk the zip themselves.
Adds extractZipEntry in util/zip — CDR-driven (conflux's streaming
writer leaves compressedSize=0 in the LFH, so LFH-only walking fails)
and supports stored (method 0) and deflate (method 8) via
DecompressionStream('deflate-raw').
Closes #39
rubenhensen
approved these changes
May 13, 2026
|
🎉 This PR is included in version 1.7.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Contributor
Author
There was a problem hiding this comment.
Reviewed post-merge for the record. Looks good — the fix correctly restores the encrypt/decrypt round-trip symmetry for the data: mode (see #39).
Verified in the diff:
- src/opened.ts:104-114 — unwrap only triggers on the exact single-entry ['data.bin'] shape, so multi-file uploads still return DecryptFileResult unchanged.
- src/util/zip.ts extractZipEntry — CDR-driven, correct for conflux's streaming writer (LFH has compressedSize=0). Re-reading filename/extra lengths from the LFH (not reusing the CDR's) is also correct per spec.
- DecompressionStream('deflate-raw') is the right primitive for method 8 raw deflate.
- Tests cover stored (method 0), streaming-mode deflate with sizes-only-in-CDR, and missing-entry. Tight coverage for the bug class.
Minor nits (non-blocking, already merged):
- extractZipEntry validates the LFH signature but doesn't verify the LFH filename matches the requested name. A malformed/adversarial zip with mismatched LFH-vs-CDR filenames would silently extract the wrong bytes. Low-risk since the source is our own Sealed.upload.
- Method 8 path doesn't verify uncompressed size against entry.uncompressedSize or check CRC. Low-risk for trusted inputs.
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.
Closes #39
Summary
Sealed.upload()fordata:mode wraps raw bytes as a single-entry zip (data.bin), butOpened.decrypt({ uuid })always returned the raw zip blob — so the round-trippg.encrypt({ data }).upload()→pg.open({ uuid }).decrypt()did not return{ plaintext, ... }as the encrypt-side API implies.Opened.decryptnow checks the central directory: if the entries are exactly['data.bin'], it unwraps the entry and returnsDecryptDataResult { plaintext, sender }. Otherwise it returnsDecryptFileResultunchanged.extractZipEntryinutil/zip: CDR-driven (conflux's streaming writer leavescompressedSize: 0in the LFH, so LFH-only walking won't work) and supports stored (method 0) and deflate (method 8) viaDecompressionStream('deflate-raw').Tests
Verified:
npm run typecheck,npm test,npm run buildall clean.Reviewer quickstart