--- old/src/java.base/share/classes/java/util/zip/ZipFile.java 2016-02-10 23:24:08.294786014 +0900 +++ new/src/java.base/share/classes/java/util/zip/ZipFile.java 2016-02-10 23:24:08.050786735 +0900 @@ -325,6 +325,13 @@ */ public InputStream getInputStream(ZipEntry entry) throws IOException { Objects.requireNonNull(entry, "entry"); + ZipCryption zipCryption = null; + + if (entry.isPassphraseRequired()) { + zipCryption = entry.zipCryption; + Objects.requireNonNull(zipCryption, "Passphrase is required."); + } + int pos = -1; ZipFileInputStream in = null; synchronized (this) { @@ -337,9 +344,19 @@ if (pos == -1) { return null; } - in = new ZipFileInputStream(zsrc.cen, pos); + in = new ZipFileInputStream(zsrc.cen, pos, zipCryption); switch (CENHOW(zsrc.cen, pos)) { case STORED: + if (entry.isPassphraseRequired()) { + entry.encryptionHeader = + new byte[TraditionalZipCryption.ENCRYPTION_HEADER_SIZE]; + in.readRaw(entry.encryptionHeader, 0, + entry.encryptionHeader.length); + if (!entry.isValidPassphrase()) { + throw new ZipException("possibly incorrect passphrase"); + } + } + synchronized (streams) { streams.put(in, null); } @@ -355,6 +372,17 @@ size = 4096; } Inflater inf = getInflater(); + + if (entry.isPassphraseRequired()) { + entry.encryptionHeader = + new byte[TraditionalZipCryption.ENCRYPTION_HEADER_SIZE]; + in.readRaw(entry.encryptionHeader, 0, + entry.encryptionHeader.length); + if (!entry.isValidPassphrase()) { + throw new ZipException("possibly incorrect passphrase"); + } + } + InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size); synchronized (streams) { streams.put(is, inf); @@ -658,8 +686,10 @@ private long pos; // current position within entry data protected long rem; // number of remaining bytes within entry protected long size; // uncompressed size of this entry + private ZipCryption zipCryption; // ZIP encrypt/decrypt engine - ZipFileInputStream(byte[] cen, int cenpos) throws IOException { + ZipFileInputStream(byte[] cen, int cenpos, ZipCryption zipCryption) + throws IOException { rem = CENSIZ(cen, cenpos); size = CENLEN(cen, cenpos); pos = CENOFF(cen, cenpos); @@ -670,6 +700,7 @@ } // negative for lazy initialization, see getDataOffset(); pos = - (pos + ZipFile.this.zsrc.locpos); + this.zipCryption = zipCryption; } private void checkZIP64(byte[] cen, int cenpos) throws IOException { @@ -731,6 +762,16 @@ } public int read(byte b[], int off, int len) throws IOException { + len = readRaw(b, off, len); + + if (zipCryption != null) { + zipCryption.decryptBytes(b, off, len); + } + + return len; + } + + public int readRaw(byte b[], int off, int len) throws IOException { synchronized (ZipFile.this) { ensureOpenOrZipException(); initDataOffset(); @@ -1180,8 +1221,6 @@ int nlen = CENNAM(cen, pos); int elen = CENEXT(cen, pos); int clen = CENCOM(cen, pos); - if ((CENFLG(cen, pos) & 1) != 0) - zerror("invalid CEN header (encrypted entry)"); if (method != STORED && method != DEFLATED) zerror("invalid CEN header (bad compression method: " + method + ")"); if (pos + CENHDR + nlen > limit)