feat: Add support for Zlib compression/decompression #417
feat: Add support for Zlib compression/decompression #417oskardanielsson-yubico wants to merge 4 commits intodevelopfrom
Conversation
…irs, add Zlib compression unit tests
Test Results: Windows 2 files 2 suites 16s ⏱️ Results for commit ee2a19f. ♻️ This comment has been updated with latest results. |
Test Results: Ubuntu 2 files 2 suites 48s ⏱️ Results for commit ee2a19f. ♻️ This comment has been updated with latest results. |
Test Results: MacOS 4 files 4 suites 40s ⏱️ Results for commit ee2a19f. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Pull request overview
This pull request adds support for Zlib compression/decompression to enable the PIV application to handle certificates compressed with zlib format. The implementation includes a new internal ZLibStream class that provides RFC 1950-compliant zlib compression/decompression, along with format auto-detection in the certificate retrieval logic to support both the standard GZip format and a custom Zlib format used by some third-party PIV middleware.
Changes:
- Added a new
ZLibStreamclass implementing RFC 1950 zlib compression/decompression with Adler-32 checksum validation - Enhanced certificate decompression in
PivSessionto auto-detect and support both GZip and Zlib formats - Added comprehensive unit tests for the
ZLibStreamclass covering compression, decompression, edge cases, and error conditions
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 9 comments.
| File | Description |
|---|---|
| Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/ZLibStream.cs | New internal class implementing zlib compression/decompression with header validation and Adler-32 checksum |
| Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.KeyPairs.cs | Updated certificate decompression to detect and handle both GZip and Zlib formats, improved exception handling with inner exception |
| Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/ZLibStreamTests.cs | Comprehensive unit tests for ZLibStream including compression levels, error conditions, Adler-32 validation, and format compatibility |
| if (!buffer.IsEmpty) | ||
| { | ||
| byte[] temp = buffer.ToArray(); | ||
| UpdateAdler32(temp, 0, temp.Length); | ||
| } |
There was a problem hiding this comment.
The async WriteAsync method creates a temporary array copy (line 299) to update the Adler-32 checksum. This allocation and copy operation happens on every async write, which could impact performance. For ReadOnlyMemory<byte>, consider using MemoryMarshal.TryGetArray to access the underlying array when possible, or use the Span property to avoid the allocation. Alternatively, if the buffer is backed by an array, you can avoid the copy by checking if it's contiguous memory.
There was a problem hiding this comment.
AI vs AI difference of opinion
| private void UpdateAdler32(byte[] buffer, int offset, int count) | ||
| { | ||
| const uint modAdler = 65521; | ||
|
|
||
| for (int i = offset; i < offset + count; i++) | ||
| { | ||
| _adlerA = (_adlerA + buffer[i]) % modAdler; | ||
| _adlerB = (_adlerB + _adlerA) % modAdler; | ||
| } | ||
| } |
There was a problem hiding this comment.
The Adler-32 implementation performs modulo operation on every byte, which can be inefficient for large data. The standard optimization is to defer the modulo operation and only apply it after processing a certain number of bytes (typically 5550 bytes, which is the largest value where overflow won't occur). This optimization is commonly used in production zlib implementations and can significantly improve performance when compressing large data. Consider optimizing UpdateAdler32 to batch the modulo operations.
There was a problem hiding this comment.
AI vs AI difference of opinion
|
@claude can you take a good look at this? Code review, correctness, quality, maintainability, codebase alignment, security, etc. |
|
Claude finished @DennisDyallo's task in 4m 19s —— View job Code Review
|

Description
Certificates compressed with zlib can now be decompressed in the Piv application
Fixes: # <link to issue(s)>
Type of change
How has this been tested?
Unit tests that test the compression and decompression have been added and run.
Test configuration:
Checklist: