View Javadoc

1   /*
2    * WizCrypt.java
3    *
4    * Created on 23 December 2006, 09:48
5    *
6    * To change this template, choose Tools | Template Manager
7    * and open the template in the editor.
8    */
9   
10  package org.wiztools.wizcrypt;
11  
12  import java.io.IOException;
13  import java.io.InputStream;
14  import java.io.OutputStream;
15  import java.nio.charset.Charset;
16  import java.util.Arrays;
17  import java.util.ResourceBundle;
18  import java.util.zip.GZIPInputStream;
19  import java.util.zip.GZIPOutputStream;
20  import javax.crypto.CipherInputStream;
21  import javax.crypto.CipherOutputStream;
22  
23  /***
24   * This class has the public APIs of WizCrypt application to do encryption and decryption.
25   * @see CipherKeyGen
26   * @see CipherKey
27   * @author subhash
28   */
29  public final class WizCrypt {
30      
31      private static final ResourceBundle rb = ResourceBundle.getBundle("org.wiztools.wizcrypt.wizcryptmsg");
32      
33      /*** Disallow public creation of instances of this object. */
34      private WizCrypt() {
35      }
36      
37      /***
38       * This is the public API exposed to encrypt.
39       * 
40       * 
41       * @param is The input stream that needs to be encrypted.
42       * @param os The output stream where the encrypted content 
43       *     of <code>is</code> need to be written.
44       * @param ck The <code>CipherKey</code> object. This has to be 
45       *     created by passing the password to 
46       *     <code>CipherKeyGen.getCipherKeyForEncrypt(String keyStr)</code>.
47       * @param cb <code>Callback</code> object for monitoring the progress.
48       * @param size The size of the <code>is</code> stream. When this is passed,
49       *      the <code>Callback.notifyProgress(long value)</code> will receive
50       *      the percentage completed. If this is not passed, it will get the
51       *      number of bytes read and processed.
52       * @see CipherKeyGen#getCipherKeyForEncrypt(String keyStr)
53       * @see CipherKey
54       * @see Callback
55       * @throws IOException <code>IOException</code> is thrown when 
56       *     faced with IO issues during read/write.
57       */
58      public static void encrypt(final InputStream is, final OutputStream os, 
59              final CipherKey ck, final Callback cb, final long size) throws IOException{
60          
61          CipherInputStream cis = null;
62          OutputStream gos = new GZIPOutputStream(os);
63          try{
64              if(cb != null){
65                  cb.begin();
66              }
67              
68              cis = new CipherInputStream(is, ck.cipher);
69              
70              // Write the file-format magic number
71              byte[] versionStr = FileFormatVersion.WC07.getBytes(WizCryptAlgorithms.STR_ENCODE);
72              gos.write(versionStr);
73              
74              // Write the hash in next 16 bytes
75              gos.write(ck.passKeyHash);
76              
77              int i = -1;
78              byte[] buffer = new byte[0xFFFF];
79              long readSize = 0;
80              while((i=cis.read(buffer)) != -1){
81                  gos.write(buffer, 0, i);
82                  readSize += i;
83                  if(cb != null){
84                      if(size == -1){
85                          cb.notifyProgress(readSize);
86                      }
87                      else{
88                          cb.notifyProgress(readSize * 100 / size);
89                      }
90                  }
91              }
92          }
93          finally{
94              try{
95                  if(gos != null){
96                      gos.close();
97                  }
98              } catch(IOException ioe){
99                  System.err.println(ioe.getMessage());
100             }
101             try{
102                 if(cis != null){
103                     cis.close();
104                 }
105             } catch(IOException ioe){
106                 System.err.println(ioe.getMessage());
107             }
108             if(cb != null){
109                 cb.end();
110             }
111         }
112     }
113     
114     /***
115      * @see #encrypt(InputStream is, OutputStream os, 
116      *      CipherKey ck, Callback cb, long size)
117      */
118     public static void encrypt(final InputStream is, final OutputStream os, 
119             final CipherKey ck) throws IOException{
120         encrypt(is, os, ck, null, -1);
121     }
122     
123     /***
124      * @see #encrypt(InputStream is, OutputStream os, 
125      *      CipherKey ck, Callback cb, long size)
126      */
127     public static void encrypt(final InputStream is, final OutputStream os, 
128             final CipherKey ck, final Callback cb) throws IOException{
129         encrypt(is, os, ck, cb, -1);
130     }
131     
132     /***
133      * This is the public API exposed to decrypt.
134      * 
135      * 
136      * @param is The input stream that needs to be decrypted.
137      * @param os The output stream where the decrypted content 
138      *      of <code>is</code> need to be written.
139      * @param ck The <code>CipherKey</code> object. This has to be 
140      *      created by passing the password to 
141      *      <code>CipherKeyGen.getCipherKeyForDecrypt(String keyStr)</code>.
142      * @param cb <code>Callback</code> object for monitoring the progress.
143      * @param size The size of the <code>is</code> stream. When this is passed,
144      *      the <code>Callback.notifyProgress(long value)</code> will receive
145      *      the percentage completed. If this is not passed, it will get the
146      *      number of bytes read and processed.
147      * @see CipherKeyGen#getCipherKeyForDecrypt(String keyStr)
148      * @see CipherKey
149      * @see Callback
150      * @throws PasswordMismatchException <code>PasswordMismatchException</code> 
151      *      is thrown when the supplied password is wrong.
152      * @throws IOException <code>IOException</code> is thrown when faced with 
153      *      IO issues during read/write.
154      */
155     public static void decrypt(final InputStream is, final OutputStream os, 
156             final CipherKey ck, final Callback cb, final long size) throws IOException, PasswordMismatchException{
157         
158         CipherOutputStream cos = null;
159         InputStream gis = new GZIPInputStream(is);
160         try{
161             if(cb != null){
162                 cb.begin();
163             }
164             
165             // Read the magic number
166             byte[] versionStr = FileFormatVersion.WC07.getBytes(WizCryptAlgorithms.STR_ENCODE);
167             int versionByteLen = versionStr.length;
168             byte[] magicNumber = new byte[versionByteLen];
169             gis.read(magicNumber, 0, versionByteLen);
170             System.out.println("magicNumber: "+new String(magicNumber));
171             
172             // read 16 bytes from fis
173             byte[] filePassKeyHash = new byte[16];
174             gis.read(filePassKeyHash, 0, 16);
175             
176             if(!Arrays.equals(ck.passKeyHash, filePassKeyHash)){
177                 throw new PasswordMismatchException(rb.getString("err.pwd.not.match"));
178             }
179             
180             cos = new CipherOutputStream(os, ck.cipher);
181             
182             int i = -1;
183             byte[] buffer = new byte[0xFFFF];
184             long readSize = 0;
185             while((i=gis.read(buffer)) != -1){
186                 cos.write(buffer, 0, i);
187                 readSize += i;
188                 if(cb != null){
189                     if(size == -1){
190                         cb.notifyProgress(readSize);
191                     }
192                     else{
193                         cb.notifyProgress(readSize * 100 / size);
194                     }
195                 }
196             }
197         }
198         finally{
199             try{
200                 if(cos != null){
201                     cos.close();
202                 }
203             } catch(IOException ioe){
204                 System.err.println(ioe.getMessage());
205             }
206             try{
207                 if(gis != null){
208                     gis.close();
209                 }
210             } catch(IOException ioe){
211                 System.err.println(ioe.getMessage());
212             }
213             if(cb != null){
214                 cb.end();
215             }
216         }
217     }
218     
219     /***
220      * @see #decrypt(InputStream is, OutputStream os, 
221      *      CipherKey ck, Callback cb, long size)
222      */
223     public static void decrypt(final InputStream is, final OutputStream os, 
224             final CipherKey ck) throws IOException, PasswordMismatchException{
225         decrypt(is, os, ck, null, -1);
226     }
227     
228     /***
229      * @see #decrypt(InputStream is, OutputStream os, 
230      *      CipherKey ck, Callback cb, long size)
231      */
232     public static void decrypt(final InputStream is, final OutputStream os, 
233             final CipherKey ck, final Callback cb) throws IOException, 
234                 PasswordMismatchException{
235         decrypt(is, os, ck, cb, -1);
236     }
237 }