--- old/src/java.base/share/classes/java/util/zip/ZipFile.java 2015-11-26 09:40:28.009601221 +0900 +++ new/src/java.base/share/classes/java/util/zip/ZipFile.java 2015-11-26 09:40:27.851018423 +0900 @@ -344,9 +344,38 @@ * @throws IllegalStateException if the zip file has been closed */ public InputStream getInputStream(ZipEntry entry) throws IOException { + return getInputStream(entry, null); + } + + /** + * Returns an input stream for reading the contents of the specified + * zip file entry. + * + *

Closing this ZIP file will, in turn, close all input + * streams that have been returned by invocations of this method. + * + * @param entry the zip file entry + * @param zipCryption instance of ZipCryption + * @return the input stream for reading the contents of the specified + * zip file entry. + * @throws ZipException if a ZIP format error has occurred + * @throws IOException if an I/O error has occurred + * @throws IllegalStateException if the zip file has been closed + */ + public InputStream getInputStream(ZipEntry entry, ZipCryption zipCryption) + throws IOException { if (entry == null) { throw new NullPointerException("entry"); } + + if ((entry.flag & 1) == 1) { + if (zipCryption == null) { + throw new ZipException("Passphrase is required."); + } else { + zipCryption.reset(); + } + } + long jzentry = 0; ZipFileInputStream in = null; synchronized (this) { @@ -359,10 +388,22 @@ if (jzentry == 0) { return null; } - in = new ZipFileInputStream(jzentry); + in = new ZipFileInputStream(jzentry, zipCryption); switch (getEntryMethod(jzentry)) { case STORED: + + if ((entry.flag & 1) == 1) { + byte[] encryptionHeader = + new byte[zipCryption.getEncryptionHeaderSize()]; + in.readRaw(encryptionHeader, 0, encryptionHeader.length); + zipCryption.decryptBytes(encryptionHeader); + + if (!zipCryption.isValid(entry, encryptionHeader)) { + throw new ZipException("possibly incorrect passphrase"); + } + } + synchronized (streams) { streams.put(in, null); } @@ -373,6 +414,18 @@ if (size > 65536) size = 8192; if (size <= 0) size = 4096; Inflater inf = getInflater(); + + if ((entry.flag & 1) == 1) { + byte[] encryptionHeader = + new byte[zipCryption.getEncryptionHeaderSize()]; + in.readRaw(encryptionHeader, 0, encryptionHeader.length); + zipCryption.decryptBytes(encryptionHeader); + + if (!zipCryption.isValid(entry, encryptionHeader)) { + throw new ZipException("possibly incorrect passphrase"); + } + } + InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size); synchronized (streams) { @@ -696,15 +749,27 @@ 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(long jzentry) { + ZipFileInputStream(long jzentry, ZipCryption zipCryption) { pos = 0; rem = getEntryCSize(jzentry); size = getEntrySize(jzentry); this.jzentry = jzentry; + this.zipCryption = zipCryption; } 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) { long rem = this.rem; long pos = this.pos;