--- old/src/java.base/share/classes/java/util/zip/ZipInputStream.java 2016-02-10 23:24:09.004783915 +0900 +++ new/src/java.base/share/classes/java/util/zip/ZipInputStream.java 2016-02-10 23:24:08.752784660 +0900 @@ -31,6 +31,7 @@ import java.io.PushbackInputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Objects; import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipUtils.*; @@ -59,6 +60,8 @@ private ZipCoder zc; + private ZipCryption zipCryption; + /** * Check to make sure that this stream has not been closed */ @@ -189,6 +192,18 @@ if (entry == null) { return -1; } + + if (entry.isPassphraseRequired()) { + if (!entry.isValidPassphrase()) { + throw new ZipException("possibly incorrect passphrase"); + } + + zipCryption = entry.zipCryption; + super.setZipCryption(zipCryption); + } else { + zipCryption = null; + } + switch (entry.method) { case DEFLATED: len = super.read(b, off, len); @@ -213,6 +228,9 @@ if (len == -1) { throw new ZipException("unexpected EOF"); } + if (zipCryption != null) { + zipCryption.decryptBytes(b, off, len); + } crc.update(b, off, len); remaining -= len; if (remaining == 0 && entry.crc != crc.getValue()) { @@ -282,7 +300,7 @@ if (get32(tmpbuf, 0) != LOCSIG) { return null; } - // get flag first, we need check EFS. + // get flag first, we need check EFS and encryption. flag = get16(tmpbuf, LOCFLG); // get the entry name and create the ZipEntry first int len = get16(tmpbuf, LOCNAM); @@ -298,10 +316,8 @@ ZipEntry e = createZipEntry(((flag & EFS) != 0) ? zc.toStringUTF8(b, len) : zc.toString(b, len)); + e.flag = flag; // now get the remaining fields for the entry - if ((flag & 1) == 1) { - throw new ZipException("encrypted ZIP entry not supported"); - } e.method = get16(tmpbuf, LOCHOW); e.xdostime = get32(tmpbuf, LOCTIM); if ((flag & 8) == 8) { @@ -322,6 +338,13 @@ e.setExtra0(extra, e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL); } + + if (e.isPassphraseRequired()) { + e.encryptionHeader = + new byte[TraditionalZipCryption.ENCRYPTION_HEADER_SIZE]; + readFully(e.encryptionHeader, 0, e.encryptionHeader.length); + } + return e; } @@ -355,7 +378,8 @@ private void readEnd(ZipEntry e) throws IOException { int n = inf.getRemaining(); if (n > 0) { - ((PushbackInputStream)in).unread(buf, len - n, n); + ((PushbackInputStream)in).unread( + (zipCryption == null) ? buf : originBuf, len - n, n); } if ((flag & 8) == 8) { /* "Data Descriptor" present */ @@ -396,6 +420,9 @@ "invalid entry size (expected " + e.size + " but got " + inf.getBytesWritten() + " bytes)"); } + if (zipCryption != null) { + e.csize -= zipCryption.getEncryptionHeaderSize(); + } if (e.csize != inf.getBytesRead()) { throw new ZipException( "invalid entry compressed size (expected " + e.csize +