Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java ZIP CRC32: detect corruption without claiming authenticity

Last updated: 5 Oct 20265 min read
tutorial
AdvancedBy AITrove Editorial

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.

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

Java
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
archive and compression boundaries
zip-entry-crc-boundary
Storage details