<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Martin&#039;s Weekend Coding &#187; Java</title>
	<atom:link href="http://blog.alutam.com/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.alutam.com</link>
	<description>Sharing useful tips from my &#34;weekend projects&#34;</description>
	<lastBuildDate>Sat, 31 Oct 2009 13:14:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
   <image>
    <title>Martin&#039;s Weekend Coding</title>
    <url>http://www.gravatar.com/avatar/fe13f36272d010f4b3c09e477a620991?s=</url>
    <link>http://blog.alutam.com</link>
   </image>
		<item>
		<title>Reading Password-Protected ZIP Files in Java</title>
		<link>http://blog.alutam.com/2009/10/31/reading-password-protected-zip-files-in-java/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.alutam.com/2009/10/31/reading-password-protected-zip-files-in-java/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 12:13:34 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[ZIP]]></category>

		<guid isPermaLink="false">http://blog.alutam.com/?p=102</guid>
		<description><![CDATA[On a recent &#8220;fun&#8221; project, I needed my application to be able to access password-protected zip files of a particular format. It was one of these features I thought will take me no time to implement. Anyway, to my surprise, neither JDK supports password-protected ZIP files, nor I was able to find a suitable Java [...]]]></description>
			<content:encoded><![CDATA[<p>On a recent &#8220;fun&#8221; project, I needed my application to be able to access password-protected zip files of a particular format. It was one of these features I thought will take me no time to implement. Anyway, to my surprise, neither JDK supports password-protected ZIP files, nor I was able to find a suitable Java open source library I could use for that purpose. So, I ended up writing the utility class on my own. I wrote an implementation of <code>java.io.InputStream</code> that filters the ZIP file data and turns a password-protected ZIP into an unprotected one on the fly &#8211; so the stream can be nicely chained with <code>java.util.zip.ZipInputStream</code>. Although the class is specifically targeted at the particular type of ZIP files I had to deal with (see the limitations below), maybe other people have to deal with the same type of files, or this class can provide a good start for others to turn it into a utility that would work with any type of ZIP (maybe I will do it myself some day &#8211; for now I don&#8217;t have time).<br />
To implement this class I used the <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">ZIP File Format Specification</a> as the source of information. I also used the <a href="http://www.7-zip.org/">7-zip project</a> (C++) as a reference during the debugging to verify my understanding of the ZIP spec. and the CRC algorithm.<br />
So, here is the class:</p>
<div class="codebox">
<pre><span class="Include">import java.io.IOException;</span>
<span class="Include">import java.io.InputStream;</span>

<span class="ReservedWord">public</span> <span class="ReservedWord">class</span> <span class="Identifier">ZipDecryptInputStream</span> <span class="ReservedWord">extends</span> <span class="Identifier">InputStream</span> <span class="Braces">{</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">static</span> <span class="ReservedWord">final</span> <span class="ReservedWord">int</span><span class="Braces">[</span><span class="Braces">]</span> <span class="Identifier">CRC_TABLE</span> <span class="Symbol">=</span> <span class="ReservedWord">new</span> <span class="ReservedWord">int</span><span class="Braces">[</span><span class="Numeric">256</span><span class="Braces">]</span><span class="Symbol">;</span>
    <span class="Comment">// compute the table</span>
    <span class="Comment">// (could also have it pre-computed - see http://snippets.dzone.com/tag/crc32)</span>
    <span class="ReservedWord">static</span> <span class="Braces">{</span>
        <span class="ReservedWord">for</span> <span class="Braces">(</span><span class="ReservedWord">int</span> <span class="Identifier">i</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span> <span class="Identifier">i</span> <span class="Symbol">&lt;</span> <span class="Numeric">256</span><span class="Symbol">;</span> <span class="Identifier">i</span><span class="Symbol">+</span><span class="Symbol">+</span><span class="Braces">)</span> <span class="Braces">{</span>
            <span class="ReservedWord">int</span> <span class="Identifier">r</span> <span class="Symbol">=</span> <span class="Identifier">i</span><span class="Symbol">;</span>
            <span class="ReservedWord">for</span> <span class="Braces">(</span><span class="ReservedWord">int</span> <span class="Identifier">j</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span> <span class="Identifier">j</span> <span class="Symbol">&lt;</span> <span class="Numeric">8</span><span class="Symbol">;</span> <span class="Identifier">j</span><span class="Symbol">+</span><span class="Symbol">+</span><span class="Braces">)</span> <span class="Braces">{</span>
                <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">r</span> <span class="Symbol">&amp;</span> <span class="Numeric">1</span><span class="Braces">)</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">1</span><span class="Braces">)</span> <span class="Braces">{</span>
                    <span class="Identifier">r</span> <span class="Symbol">=</span> <span class="Braces">(</span><span class="Identifier">r</span> <span class="Symbol">&gt;</span><span class="Symbol">&gt;</span><span class="Symbol">&gt;</span> <span class="Numeric">1</span><span class="Braces">)</span> ^ <span class="Numeric">0xedb88320</span><span class="Symbol">;</span>
                <span class="Braces">}</span> <span class="ReservedWord">else</span> <span class="Braces">{</span>
                    <span class="Identifier">r</span> <span class="Symbol">&gt;</span><span class="Symbol">&gt;</span><span class="Symbol">&gt;</span><span class="Symbol">=</span> <span class="Numeric">1</span><span class="Symbol">;</span>
                <span class="Braces">}</span>
            <span class="Braces">}</span>
            <span class="Identifier">CRC_TABLE</span><span class="Braces">[</span><span class="Identifier">i</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Identifier">r</span><span class="Symbol">;</span>
        <span class="Braces">}</span>
    <span class="Braces">}</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">static</span> <span class="ReservedWord">final</span> <span class="ReservedWord">int</span> <span class="Identifier">DECRYPT_HEADER_SIZE</span> <span class="Symbol">=</span> <span class="Numeric">12</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">static</span> <span class="ReservedWord">final</span> <span class="ReservedWord">int</span><span class="Braces">[</span><span class="Braces">]</span> <span class="Identifier">LFH_SIGNATURE</span> <span class="Symbol">=</span> <span class="Braces">{</span><span class="Numeric">0x50</span>, <span class="Numeric">0x4b</span>, <span class="Numeric">0x03</span>, <span class="Numeric">0x04</span><span class="Braces">}</span><span class="Symbol">;</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">final</span> <span class="Identifier">InputStream</span> <span class="Identifier">delegate</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">final</span> <span class="Identifier">String</span> <span class="Identifier">password</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">final</span> <span class="ReservedWord">int</span> <span class="Identifier">keys</span><span class="Braces">[</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="ReservedWord">new</span> <span class="ReservedWord">int</span><span class="Braces">[</span><span class="Numeric">3</span><span class="Braces">]</span><span class="Symbol">;</span>

    <span class="ReservedWord">private</span> <span class="Identifier">State</span> <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">SIGNATURE</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">int</span> <span class="Identifier">skipBytes</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">int</span> <span class="Identifier">compressedSize</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">int</span> <span class="Identifier">value</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">int</span> <span class="Identifier">valuePos</span><span class="Symbol">;</span>
    <span class="ReservedWord">private</span> <span class="ReservedWord">int</span> <span class="Identifier">valueInc</span><span class="Symbol">;</span>

    <span class="ReservedWord">public</span> <span class="Identifier">ZipDecryptInputStream</span><span class="Braces">(</span><span class="Identifier">InputStream</span> <span class="Identifier">stream</span>, <span class="Identifier">String</span> <span class="Identifier">password</span><span class="Braces">)</span> <span class="Braces">{</span>
        <span class="ReservedWord">this</span>.<span class="Identifier">delegate</span> <span class="Symbol">=</span> <span class="Identifier">stream</span><span class="Symbol">;</span>
        <span class="ReservedWord">this</span>.<span class="Identifier">password</span> <span class="Symbol">=</span> <span class="Identifier">password</span><span class="Symbol">;</span>
    <span class="Braces">}</span>

    @<span class="Identifier">Override</span>
    <span class="ReservedWord">public</span> <span class="ReservedWord">int</span> <span class="Identifier">read</span><span class="Braces">(</span><span class="Braces">)</span> <span class="ReservedWord">throws</span> <span class="Identifier">IOException</span> <span class="Braces">{</span>
        <span class="ReservedWord">int</span> <span class="Identifier">result</span> <span class="Symbol">=</span> <span class="Identifier">delegate</span>.<span class="Identifier">read</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">skipBytes</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">0</span><span class="Braces">)</span> <span class="Braces">{</span>
            <span class="ReservedWord">switch</span> <span class="Braces">(</span><span class="Identifier">state</span><span class="Braces">)</span> <span class="Braces">{</span>
                <span class="ReservedWord">case</span> <span class="Identifier">SIGNATURE</span><span class="Symbol">:</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">result</span> <span class="Symbol">!</span><span class="Symbol">=</span> <span class="Identifier">LFH_SIGNATURE</span><span class="Braces">[</span><span class="Identifier">valuePos</span><span class="Braces">]</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">TAIL</span><span class="Symbol">;</span>
                    <span class="Braces">}</span> <span class="ReservedWord">else</span> <span class="Braces">{</span>
                        <span class="Identifier">valuePos</span><span class="Symbol">+</span><span class="Symbol">+</span><span class="Symbol">;</span>
                        <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">valuePos</span> <span class="Symbol">&gt;</span><span class="Symbol">=</span> <span class="Identifier">LFH_SIGNATURE</span>.<span class="Identifier">length</span><span class="Braces">)</span> <span class="Braces">{</span>
                            <span class="Identifier">skipBytes</span> <span class="Symbol">=</span> <span class="Numeric">2</span><span class="Symbol">;</span>
                            <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">FLAGS</span><span class="Symbol">;</span>
                        <span class="Braces">}</span>
                    <span class="Braces">}</span>
                    <span class="ReservedWord">break</span><span class="Symbol">;</span>
                <span class="ReservedWord">case</span> <span class="Identifier">FLAGS</span><span class="Symbol">:</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">result</span> <span class="Symbol">&amp;</span> <span class="Numeric">1</span><span class="Braces">)</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">0</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="ReservedWord">throw</span> <span class="ReservedWord">new</span> <span class="Identifier">IllegalStateException</span><span class="Braces">(</span><span class="String">&quot;ZIP not password protected.&quot;</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">result</span> <span class="Symbol">&amp;</span> <span class="Numeric">64</span><span class="Braces">)</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">64</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="ReservedWord">throw</span> <span class="ReservedWord">new</span> <span class="Identifier">IllegalStateException</span><span class="Braces">(</span><span class="String">&quot;Strong encryption used.&quot;</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">result</span> <span class="Symbol">&amp;</span> <span class="Numeric">8</span><span class="Braces">)</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">8</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="ReservedWord">throw</span> <span class="ReservedWord">new</span> <span class="Identifier">IllegalStateException</span><span class="Braces">(</span><span class="String">&quot;Unsupported ZIP format.&quot;</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="Identifier">result</span> <span class="Symbol">-</span><span class="Symbol">=</span> <span class="Numeric">1</span><span class="Symbol">;</span>
                    <span class="Identifier">compressedSize</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                    <span class="Identifier">valuePos</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                    <span class="Identifier">valueInc</span> <span class="Symbol">=</span> <span class="Identifier">DECRYPT_HEADER_SIZE</span><span class="Symbol">;</span>
                    <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">COMPRESSED_SIZE</span><span class="Symbol">;</span>
                    <span class="Identifier">skipBytes</span> <span class="Symbol">=</span> <span class="Numeric">11</span><span class="Symbol">;</span>
                    <span class="ReservedWord">break</span><span class="Symbol">;</span>
                <span class="ReservedWord">case</span> <span class="Identifier">COMPRESSED_SIZE</span><span class="Symbol">:</span>
                    <span class="Identifier">compressedSize</span> <span class="Symbol">+</span><span class="Symbol">=</span> <span class="Identifier">result</span> <span class="Symbol">&lt;</span><span class="Symbol">&lt;</span> <span class="Braces">(</span><span class="Numeric">8</span> <span class="Symbol">*</span> <span class="Identifier">valuePos</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="Identifier">result</span> <span class="Symbol">-</span><span class="Symbol">=</span> <span class="Identifier">valueInc</span><span class="Symbol">;</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">result</span> <span class="Symbol">&lt;</span> <span class="Numeric">0</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="Identifier">valueInc</span> <span class="Symbol">=</span> <span class="Numeric">1</span><span class="Symbol">;</span>
                        <span class="Identifier">result</span> <span class="Symbol">+</span><span class="Symbol">=</span> <span class="Numeric">256</span><span class="Symbol">;</span>
                    <span class="Braces">}</span> <span class="ReservedWord">else</span> <span class="Braces">{</span>
                        <span class="Identifier">valueInc</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="Identifier">valuePos</span><span class="Symbol">+</span><span class="Symbol">+</span><span class="Symbol">;</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">valuePos</span> <span class="Symbol">&gt;</span> <span class="Numeric">3</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="Identifier">valuePos</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                        <span class="Identifier">value</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                        <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">FN_LENGTH</span><span class="Symbol">;</span>
                        <span class="Identifier">skipBytes</span> <span class="Symbol">=</span> <span class="Numeric">4</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="ReservedWord">break</span><span class="Symbol">;</span>
                <span class="ReservedWord">case</span> <span class="Identifier">FN_LENGTH</span><span class="Symbol">:</span>
                <span class="ReservedWord">case</span> <span class="Identifier">EF_LENGTH</span><span class="Symbol">:</span>
                    <span class="Identifier">value</span> <span class="Symbol">+</span><span class="Symbol">=</span> <span class="Identifier">result</span> <span class="Symbol">&lt;</span><span class="Symbol">&lt;</span> <span class="Numeric">8</span> <span class="Symbol">*</span> <span class="Identifier">valuePos</span><span class="Symbol">;</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">valuePos</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">1</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="Identifier">valuePos</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                        <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">state</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">FN_LENGTH</span><span class="Braces">)</span> <span class="Braces">{</span>
                            <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">EF_LENGTH</span><span class="Symbol">;</span>
                        <span class="Braces">}</span> <span class="ReservedWord">else</span> <span class="Braces">{</span>
                            <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">HEADER</span><span class="Symbol">;</span>
                            <span class="Identifier">skipBytes</span> <span class="Symbol">=</span> <span class="Identifier">value</span><span class="Symbol">;</span>
                        <span class="Braces">}</span>
                    <span class="Braces">}</span> <span class="ReservedWord">else</span> <span class="Braces">{</span>
                        <span class="Identifier">valuePos</span> <span class="Symbol">=</span> <span class="Numeric">1</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="ReservedWord">break</span><span class="Symbol">;</span>
                <span class="ReservedWord">case</span> <span class="Identifier">HEADER</span><span class="Symbol">:</span>
                    <span class="Identifier">initKeys</span><span class="Braces">(</span><span class="Identifier">password</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="ReservedWord">for</span> <span class="Braces">(</span><span class="ReservedWord">int</span> <span class="Identifier">i</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span> <span class="Identifier">i</span> <span class="Symbol">&lt;</span> <span class="Identifier">DECRYPT_HEADER_SIZE</span><span class="Symbol">;</span> <span class="Identifier">i</span><span class="Symbol">+</span><span class="Symbol">+</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="Identifier">updateKeys</span><span class="Braces">(</span><span class="Braces">(</span><span class="ReservedWord">byte</span><span class="Braces">)</span> <span class="Braces">(</span><span class="Identifier">result</span> ^ <span class="Identifier">decryptByte</span><span class="Braces">(</span><span class="Braces">)</span><span class="Braces">)</span><span class="Braces">)</span><span class="Symbol">;</span>
                        <span class="Identifier">result</span> <span class="Symbol">=</span> <span class="Identifier">delegate</span>.<span class="Identifier">read</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="Identifier">compressedSize</span> <span class="Symbol">-</span><span class="Symbol">=</span> <span class="Identifier">DECRYPT_HEADER_SIZE</span><span class="Symbol">;</span>
                    <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">DATA</span><span class="Symbol">;</span>
                    <span class="Comment">// intentionally no break</span>
                <span class="ReservedWord">case</span> <span class="Identifier">DATA</span><span class="Symbol">:</span>
                    <span class="Identifier">result</span> <span class="Symbol">=</span> <span class="Braces">(</span><span class="Identifier">result</span> ^ <span class="Identifier">decryptByte</span><span class="Braces">(</span><span class="Braces">)</span><span class="Braces">)</span> <span class="Symbol">&amp;</span> <span class="Numeric">0xff</span><span class="Symbol">;</span>
                    <span class="Identifier">updateKeys</span><span class="Braces">(</span><span class="Braces">(</span><span class="ReservedWord">byte</span><span class="Braces">)</span> <span class="Identifier">result</span><span class="Braces">)</span><span class="Symbol">;</span>
                    <span class="Identifier">compressedSize</span><span class="Symbol">-</span><span class="Symbol">-</span><span class="Symbol">;</span>
                    <span class="ReservedWord">if</span> <span class="Braces">(</span><span class="Identifier">compressedSize</span> <span class="Symbol">=</span><span class="Symbol">=</span> <span class="Numeric">0</span><span class="Braces">)</span> <span class="Braces">{</span>
                        <span class="Identifier">valuePos</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span>
                        <span class="Identifier">state</span> <span class="Symbol">=</span> <span class="Identifier">State</span>.<span class="Identifier">SIGNATURE</span><span class="Symbol">;</span>
                    <span class="Braces">}</span>
                    <span class="ReservedWord">break</span><span class="Symbol">;</span>
                <span class="ReservedWord">case</span> <span class="Identifier">TAIL</span><span class="Symbol">:</span>
                    <span class="Comment">// do nothing</span>
            <span class="Braces">}</span>
        <span class="Braces">}</span> <span class="ReservedWord">else</span> <span class="Braces">{</span>
            <span class="Identifier">skipBytes</span><span class="Symbol">-</span><span class="Symbol">-</span><span class="Symbol">;</span>
        <span class="Braces">}</span>
        <span class="ReservedWord">return</span> <span class="Identifier">result</span><span class="Symbol">;</span>
    <span class="Braces">}</span>

    @<span class="Identifier">Override</span>
    <span class="ReservedWord">public</span> <span class="ReservedWord">void</span> <span class="Identifier">close</span><span class="Braces">(</span><span class="Braces">)</span> <span class="ReservedWord">throws</span> <span class="Identifier">IOException</span> <span class="Braces">{</span>
        <span class="Identifier">delegate</span>.<span class="Identifier">close</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="ReservedWord">super</span>.<span class="Identifier">close</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
    <span class="Braces">}</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">void</span> <span class="Identifier">initKeys</span><span class="Braces">(</span><span class="Identifier">String</span> <span class="Identifier">password</span><span class="Braces">)</span> <span class="Braces">{</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">0</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Numeric">305419896</span><span class="Symbol">;</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">1</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Numeric">591751049</span><span class="Symbol">;</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">2</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Numeric">878082192</span><span class="Symbol">;</span>
        <span class="ReservedWord">for</span> <span class="Braces">(</span><span class="ReservedWord">int</span> <span class="Identifier">i</span> <span class="Symbol">=</span> <span class="Numeric">0</span><span class="Symbol">;</span> <span class="Identifier">i</span> <span class="Symbol">&lt;</span> <span class="Identifier">password</span>.<span class="Identifier">length</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span> <span class="Identifier">i</span><span class="Symbol">+</span><span class="Symbol">+</span><span class="Braces">)</span> <span class="Braces">{</span>
            <span class="Identifier">updateKeys</span><span class="Braces">(</span><span class="Braces">(</span><span class="ReservedWord">byte</span><span class="Braces">)</span> <span class="Braces">(</span><span class="Identifier">password</span>.<span class="Identifier">charAt</span><span class="Braces">(</span><span class="Identifier">i</span><span class="Braces">)</span> <span class="Symbol">&amp;</span> <span class="Numeric">0xff</span><span class="Braces">)</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="Braces">}</span>
    <span class="Braces">}</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">void</span> <span class="Identifier">updateKeys</span><span class="Braces">(</span><span class="ReservedWord">byte</span> <span class="Identifier">charAt</span><span class="Braces">)</span> <span class="Braces">{</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">0</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Identifier">crc32</span><span class="Braces">(</span><span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">0</span><span class="Braces">]</span>, <span class="Identifier">charAt</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">1</span><span class="Braces">]</span> <span class="Symbol">+</span><span class="Symbol">=</span> <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">0</span><span class="Braces">]</span> <span class="Symbol">&amp;</span> <span class="Numeric">0xff</span><span class="Symbol">;</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">1</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">1</span><span class="Braces">]</span> <span class="Symbol">*</span> <span class="Numeric">134775813</span> <span class="Symbol">+</span> <span class="Numeric">1</span><span class="Symbol">;</span>
        <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">2</span><span class="Braces">]</span> <span class="Symbol">=</span> <span class="Identifier">crc32</span><span class="Braces">(</span><span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">2</span><span class="Braces">]</span>, <span class="Braces">(</span><span class="ReservedWord">byte</span><span class="Braces">)</span> <span class="Braces">(</span><span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">1</span><span class="Braces">]</span> <span class="Symbol">&gt;</span><span class="Symbol">&gt;</span> <span class="Numeric">24</span><span class="Braces">)</span><span class="Braces">)</span><span class="Symbol">;</span>
    <span class="Braces">}</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">byte</span> <span class="Identifier">decryptByte</span><span class="Braces">(</span><span class="Braces">)</span> <span class="Braces">{</span>
        <span class="ReservedWord">int</span> <span class="Identifier">temp</span> <span class="Symbol">=</span> <span class="Identifier">keys</span><span class="Braces">[</span><span class="Numeric">2</span><span class="Braces">]</span> <span class="Symbol">|</span> <span class="Numeric">2</span><span class="Symbol">;</span>
        <span class="ReservedWord">return</span> <span class="Braces">(</span><span class="ReservedWord">byte</span><span class="Braces">)</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">temp</span> <span class="Symbol">*</span> <span class="Braces">(</span><span class="Identifier">temp</span> ^ <span class="Numeric">1</span><span class="Braces">)</span><span class="Braces">)</span> <span class="Symbol">&gt;</span><span class="Symbol">&gt;</span><span class="Symbol">&gt;</span> <span class="Numeric">8</span><span class="Braces">)</span><span class="Symbol">;</span>
    <span class="Braces">}</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">int</span> <span class="Identifier">crc32</span><span class="Braces">(</span><span class="ReservedWord">int</span> <span class="Identifier">oldCrc</span>, <span class="ReservedWord">byte</span> <span class="Identifier">charAt</span><span class="Braces">)</span> <span class="Braces">{</span>
        <span class="ReservedWord">return</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">oldCrc</span> <span class="Symbol">&gt;</span><span class="Symbol">&gt;</span><span class="Symbol">&gt;</span> <span class="Numeric">8</span><span class="Braces">)</span> ^ <span class="Identifier">CRC_TABLE</span><span class="Braces">[</span><span class="Braces">(</span><span class="Identifier">oldCrc</span> ^ <span class="Identifier">charAt</span><span class="Braces">)</span> <span class="Symbol">&amp;</span> <span class="Numeric">0xff</span><span class="Braces">]</span><span class="Braces">)</span><span class="Symbol">;</span>
    <span class="Braces">}</span>

    <span class="ReservedWord">private</span> <span class="ReservedWord">static</span> <span class="Identifier">enum</span> <span class="Identifier">State</span> <span class="Braces">{</span>
        <span class="Identifier">SIGNATURE</span>, <span class="Identifier">FLAGS</span>, <span class="Identifier">COMPRESSED_SIZE</span>, <span class="Identifier">FN_LENGTH</span>, <span class="Identifier">EF_LENGTH</span>, <span class="Identifier">HEADER</span>, <span class="Identifier">DATA</span>, <span class="Identifier">TAIL</span>
    <span class="Braces">}</span>
<span class="Braces">}</span></pre>
</div>
<p>These are the limitations:</p>
<ul>
<li>Only the &#8220;Traditional PKWARE Encryption&#8221; is supported (spec. section VII)</li>
<li>Files that have the &#8220;compressed length&#8221; information at the end of the data section (rather than at the beginning) are not supported (see &#8220;general purpose bit flag&#8221;, bit 3 in section V, subsection J in the spec.)</li>
</ul>
<p>And this is how you can use it in your code:</p>
<div class="codebox">
<pre><span class="Include">import java.io.FileInputStream;</span>
<span class="Include">import java.io.FileOutputStream;</span>
<span class="Include">import java.io.IOException;</span>
<span class="Include">import java.util.zip.ZipEntry;</span>
<span class="Include">import java.util.zip.ZipInputStream;</span>

<span class="Comment">// usage: java Main [filename] [password]</span>
<span class="ReservedWord">public</span> <span class="ReservedWord">class</span> <span class="Identifier">Main</span> <span class="Braces">{</span>
    <span class="ReservedWord">public</span> <span class="ReservedWord">static</span> <span class="ReservedWord">void</span> <span class="Identifier">main</span><span class="Braces">(</span><span class="Identifier">String</span><span class="Braces">[</span><span class="Braces">]</span> <span class="Identifier">args</span><span class="Braces">)</span> <span class="ReservedWord">throws</span> <span class="Identifier">IOException</span> <span class="Braces">{</span>
        <span class="Comment">// password-protected zip file I need to read</span>
        <span class="Identifier">FileInputStream</span> <span class="Identifier">fis</span> <span class="Symbol">=</span> <span class="ReservedWord">new</span> <span class="Identifier">FileInputStream</span><span class="Braces">(</span><span class="Identifier">args</span><span class="Braces">[</span><span class="Numeric">0</span><span class="Braces">]</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="Comment">// wrap it in the decrypt stream</span>
        <span class="Identifier">ZipDecryptInputStream</span> <span class="Identifier">zdis</span> <span class="Symbol">=</span> <span class="ReservedWord">new</span> <span class="Identifier">ZipDecryptInputStream</span><span class="Braces">(</span><span class="Identifier">fis</span>, <span class="Identifier">args</span><span class="Braces">[</span><span class="Numeric">1</span><span class="Braces">]</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="Comment">// wrap the decrypt stream by the ZIP input stream</span>
        <span class="Identifier">ZipInputStream</span> <span class="Identifier">zis</span> <span class="Symbol">=</span> <span class="ReservedWord">new</span> <span class="Identifier">ZipInputStream</span><span class="Braces">(</span><span class="Identifier">zdis</span><span class="Braces">)</span><span class="Symbol">;</span>

        <span class="Comment">// read all the zip entries and save them as files</span>
        <span class="Identifier">ZipEntry</span> <span class="Identifier">ze</span><span class="Symbol">;</span>
        <span class="ReservedWord">while</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">ze</span> <span class="Symbol">=</span> <span class="Identifier">zis</span>.<span class="Identifier">getNextEntry</span><span class="Braces">(</span><span class="Braces">)</span><span class="Braces">)</span> <span class="Symbol">!</span><span class="Symbol">=</span> <span class="ReservedWord">null</span><span class="Braces">)</span> <span class="Braces">{</span>
            <span class="Identifier">FileOutputStream</span> <span class="Identifier">fos</span> <span class="Symbol">=</span> <span class="ReservedWord">new</span> <span class="Identifier">FileOutputStream</span><span class="Braces">(</span><span class="Identifier">ze</span>.<span class="Identifier">getName</span><span class="Braces">(</span><span class="Braces">)</span><span class="Braces">)</span><span class="Symbol">;</span>
            <span class="ReservedWord">int</span> <span class="Identifier">b</span><span class="Symbol">;</span>
            <span class="ReservedWord">while</span> <span class="Braces">(</span><span class="Braces">(</span><span class="Identifier">b</span> <span class="Symbol">=</span> <span class="Identifier">zis</span>.<span class="Identifier">read</span><span class="Braces">(</span><span class="Braces">)</span><span class="Braces">)</span> <span class="Symbol">!</span><span class="Symbol">=</span> <span class="Symbol">-</span><span class="Numeric">1</span><span class="Braces">)</span> <span class="Braces">{</span>
                <span class="Identifier">fos</span>.<span class="Identifier">write</span><span class="Braces">(</span><span class="Identifier">b</span><span class="Braces">)</span><span class="Symbol">;</span>
            <span class="Braces">}</span>
            <span class="Identifier">fos</span>.<span class="Identifier">close</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
            <span class="Identifier">zis</span>.<span class="Identifier">closeEntry</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
        <span class="Braces">}</span>
        <span class="Identifier">zis</span>.<span class="Identifier">close</span><span class="Braces">(</span><span class="Braces">)</span><span class="Symbol">;</span>
    <span class="Braces">}</span>
<span class="Braces">}</span></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.alutam.com/2009/10/31/reading-password-protected-zip-files-in-java/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
	</channel>
</rss>
