Package com.zwl.util.zip

Source Code of com.zwl.util.zip.AesZipFileEncrypter

package com.zwl.util.zip;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import com.zwl.util.zip.impl.AESEncrypter;
import com.zwl.util.zip.impl.AESEncrypterBC;
import com.zwl.util.zip.impl.ExtZipEntry;
import com.zwl.util.zip.impl.ExtZipOutputStream;
import com.zwl.util.zip.impl.ZipFileEntryInputStream;

/**
* Create ZIP archive containing AES-256 encrypted entries. <br>
* One instance of this class represents one encrypted ZIP file, that can receive add() method calls
* that must be followed by one final call to close() to write the final archive part and close the
* output stream.
*
* TODO - support 128 + 192 keys
*
* @author olaf@merkert.de
* @author jean-luc.cooke@greenparty.ca
*/
public class AesZipFileEncrypter {

  private static final Logger LOG = Logger.getLogger(AesZipFileEncrypter.class.getName());

  // --------------------------------------------------------------------------

  protected ExtZipOutputStream zipOS;

  /**
   *
   * @param pathName
   *          to output zip file (aes encrypted zip file)
   */
  public AesZipFileEncrypter(String pathName) throws IOException {
    zipOS = new ExtZipOutputStream(new File(pathName));
  }

  /**
   *
   * @param outFile
   *          output file (aes encrypted zip file)
   */
  public AesZipFileEncrypter(File outFile) throws IOException {
    zipOS = new ExtZipOutputStream(outFile);
  }

  // --------------------------------------------------------------------------

  protected void add(ExtZipEntry zipEntry, InputStream zipData) throws IOException,
      UnsupportedEncodingException {
    zipOS.putNextEntry(zipEntry);

    byte[] data = new byte[1024];
    int read = zipData.read(data);
    while (read != -1) {
      zipOS.writeBytes(data, 0, read);
      read = zipData.read(data);
    }
  }

  protected void add(ZipFile inFile, String password) throws IOException,
      UnsupportedEncodingException {
    ZipFileEntryInputStream zfe = new ZipFileEntryInputStream(inFile);
    Enumeration<? extends ZipEntry> en = inFile.entries();
    while (en.hasMoreElements()) {
      ZipEntry ze = en.nextElement();
      zfe.nextEntry(ze);
      add(ze, zfe, password);
    }
    zfe.close();
  }

  // TODO - zipEntry might use extended local header
  protected void add(ZipEntry zipEntry, ZipFileEntryInputStream zipData, String password)
      throws IOException, UnsupportedEncodingException {
    AESEncrypter aesEncrypter = new AESEncrypterBC(password.getBytes("iso-8859-1"));

    ExtZipEntry entry = new ExtZipEntry(zipEntry.getName());
    entry.setMethod(zipEntry.getMethod());
    entry.setSize(zipEntry.getSize());
    entry.setCompressedSize(zipEntry.getCompressedSize() + 28);
    entry.setTime(zipEntry.getTime());
    entry.initEncryptedEntry();

    zipOS.putNextEntry(entry);
    // ZIP-file data contains: 1. salt 2. pwVerification 3. encryptedContent 4. authenticationCode
    zipOS.writeBytes(aesEncrypter.getSalt());
    zipOS.writeBytes(aesEncrypter.getPwVerification());

    byte[] data = new byte[1024];
    int read = zipData.read(data);
    while (read != -1) {
      aesEncrypter.encrypt(data, read);
      zipOS.writeBytes(data, 0, read);
      read = zipData.read(data);
    }

    byte[] finalAuthentication = aesEncrypter.getFinalAuthentication();
    if (LOG.isLoggable(Level.FINE)) {
      LOG.fine("finalAuthentication=" + Arrays.toString(finalAuthentication) + " at pos="
          + zipOS.getWritten());
    }

    zipOS.writeBytes(finalAuthentication);
  }

  /**
   * Add un-encrypted + un-zipped file to encrypted zip file.<br>
   *
   * @param file to add
   * @param pathForEntry to be used for addition of the file (path within zip file)
   * @param password to be used for encryption
   */
  public void add(File file, String pathForEntry, String password) throws IOException, UnsupportedEncodingException {
    FileInputStream fis = new FileInputStream(file);
    try {
      add(pathForEntry, fis, password);
    } finally {
      fis.close();
    }
  }

  /**
   * Add un-encrypted + un-zipped file to encrypted zip file.
   *
   * @param file to add, provides the path of the file within the zip file via its getPath()
   * @param password to be used for encryption
   */
  public void add(File file, String password) throws IOException, UnsupportedEncodingException {
    FileInputStream fis = new FileInputStream(file);
    try {
      add(file.getPath(), fis, password);
    } finally {
      fis.close();
    }
  }

  /**
   * Add un-encrypted + un-zipped InputStream contents as file "name" to encrypted zip file.
   *
   * @param name of the new zipEntry within the zip file
   * @param is provides the data to be added 
   * @param password to be used for encryption
   */
  public void add(String name, InputStream is, String password) throws IOException,  UnsupportedEncodingException {
    AESEncrypter aesEncrypter = new AESEncrypterBC(password.getBytes("iso-8859-1"));

    // Compress contents of inputStream and report on bytes read
    // we need to first compress to know details of entry
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DeflaterOutputStream dos = new DeflaterOutputStream(bos, new Deflater(9, true), 8 * 1024);
    int read, inputLen = 0;
    byte[] buf = new byte[8 * 1024];
    while ((read = is.read(buf)) > 0) {
      inputLen += read;
      dos.write(buf, 0, read);
    }
    dos.close();
    byte[] data = bos.toByteArray();

    ExtZipEntry entry = new ExtZipEntry(name);
    entry.setMethod(ZipEntry.DEFLATED);
    entry.setSize(inputLen);
    entry.setCompressedSize(data.length + 28);
    entry.setTime((new java.util.Date()).getTime());
    entry.initEncryptedEntry();

    zipOS.putNextEntry(entry);
    // ZIP-file data contains: 1. salt 2. pwVerification 3. encryptedContent 4. authenticationCode
    zipOS.writeBytes(aesEncrypter.getSalt());
    zipOS.writeBytes(aesEncrypter.getPwVerification());

    aesEncrypter.encrypt(data, data.length);
    zipOS.writeBytes(data, 0, data.length);

    byte[] finalAuthentication = aesEncrypter.getFinalAuthentication();
    if (LOG.isLoggable(Level.FINE)) {
      LOG.fine("finalAuthentication=" + Arrays.toString(finalAuthentication) + " at pos="
          + zipOS.getWritten());
    }

    zipOS.writeBytes(finalAuthentication);
  }

  // --------------------------------------------------------------------------

  /**
   * add one file to encrypted zip file
   *
   * @param pathToFile
   *          the file to add
   * @param password
   *          the password used for encryption
   * @throws IOException
  public void add(File pathToFile, String password) throws IOException {
    File outZipFile = new File(pathToFile + ".zip");
    zip(pathToFile, outZipFile);
    addAll(outZipFile, password);
    outZipFile.delete();
  }
   */

  // --------------------------------------------------------------------------

  /**
   * Zip contents of inFile to outFile.
   */
  public static void zip(File inFile, File outFile) throws IOException {
    FileInputStream fin = new FileInputStream(inFile);
    FileOutputStream fout = new FileOutputStream(outFile);
    ZipOutputStream zout = new ZipOutputStream(fout);

    zout.putNextEntry(new ZipEntry(inFile.getName()));
    byte[] buffer = new byte[1024];
    int len;
    while ((len = fin.read(buffer)) > 0) {
      zout.write(buffer, 0, len);
    }
    zout.closeEntry();

    zout.close();
    fin.close();
  }

  // --------------------------------------------------------------------------

  /**
   * Take all elements (files) from zip file and add them ENCRYPTED with password to the new zip
   * file created with this instance. <br>
   * Encrypted data of each file has the same size as the compressed data, though the file size is
   * increased by 26 bytes for salt and pw-verification bytes.<br>
   * While the {@link #add(File, String)} method does not need an additional zip file, this method
   * comes in handy, when your input data is larger then your available memory.
   *
   * @param pathToZipFile
   *          provides zipFileEntries for encryption
   * @param password
   *          used to perform the encryption
   * @throws IOException
   */
  public void addAll(File pathToZipFile, String password) throws IOException {
    ZipFile zipFile = new ZipFile(pathToZipFile);
    add(zipFile, password);
    zipFile.close();
  }

  // --------------------------------------------------------------------------

  /**
   * Client is required to call this method after he added all entries so the final archive part is
   * written.
   */
  public void close() throws IOException {
    zipOS.finish();
  }

  // --------------------------------------------------------------------------

  /**
   * Simply zip + encrypt one "inFile" to one "outFile" useing "password".
   */
  public static void zipAndEncrypt(File inFile, File outFile, String password) throws IOException {
    AesZipFileEncrypter enc = new AesZipFileEncrypter(outFile);
    enc.add(inFile, password);
    enc.close();
  }

}
TOP

Related Classes of com.zwl.util.zip.AesZipFileEncrypter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.