A ZIP entry's CRC32 can detect accidental byte changes when compared with the bytes actually read. It cannot prove who created the archive or prevent intentional alteration.
Java ZIP CRC32: detect corruption without claiming authenticity
Operational contract
The method opens one named entry, requires a declared CRC, and computes CRC32 over at most 47,000 inflated bytes. It drains to end before comparing, so the result is not based on a prefix. The name is chosen by a trusted caller after duplicate-name and path checks; this method does not extract to disk. An attacker can change data and recompute CRC32, so use an authenticated signature or trusted transport when origin matters. Closing both entry stream and ZipFile is part of the read boundary.
Failure case
A shipment ZIP entry is damaged during storage. The computed CRC differs from its header value, and the import stops before parsing XML. A malicious sender could deliberately supply matching data and CRC, so the same check must not be called a security signature.
Java code
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class ReceiptZipCrcGate {
public static long verifiedBytes(Path archive, String approvedName) throws IOException {
try (ZipFile zip = new ZipFile(archive.toFile())) {
ZipEntry entry = zip.getEntry(approvedName);
if (entry == null || entry.getCrc() < 0) throw new IOException("Entry or CRC missing");
CRC32 checksum = new CRC32();
long total = 0;
try (InputStream input = zip.getInputStream(entry)) {
byte[] chunk = new byte[8_192];
int count;
while ((count = input.read(chunk)) != -1) {
if (count > 47_000 - total) throw new IOException("Entry exceeds cap");
checksum.update(chunk, 0, count);
total += count;
}
}
if (checksum.getValue() != entry.getCrc()) throw new IOException("ZIP CRC mismatch");
return total;
}
}
}Performance and ownership cost
Decompressing and checksumming B bytes costs O(B) time and O(1) application memory beyond an 8,192-byte buffer. The cap bounds output bytes, not all decompression CPU or archive metadata work.
Common Mistakes
- Do not call CRC32 an authentication mechanism.
- Do not compare a checksum before consuming the full entry.
- Do not select ambiguous duplicate names without an earlier policy.
Connected lessons
- Java ZIP entry extraction: cap expanded bytes while reading
- Java ZipFile entries: reject duplicate names before selection
- Java HmacSHA256 verification: reject a changed message
- Java GZIPInputStream: cap bytes after decompression
- Java GZIPOutputStream: close before using the compressed bytes
- Java ZipOutputStream: close each entry and the archive before publication
- Java XML and archive boundaries quiz
- Advanced Java
