Posted at

Zip4jでバイト配列を暗号化zip圧縮する

More than 3 years have passed since last update.


目的

Java標準のjava.util.zipは暗号化に対応していません。

なので暗号化zipをしようとすると別途ライブラリが必要になります。

色々試したのですが、結局は一番メジャーらしいzip4jを使うことにしました。


zip4j

公式サイトはこちら

Maven Repositoryはこちら

最新のバージョンは1.3.2のようです。


コード


依存ライブラリを定義


pom.xml

    <dependencies>

<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>


暗号化zip部分

このライブラリに限らないのですが、zipエントリを作る際、実際に存在するファイルの属性を取得して利用しているため、バイト配列だけでは直接zipエントリを作成できません。

なので、Fileクラスの匿名クラスを使って対処します。

ただ、階層構造をもったzipファイルを作ろうとすると面倒なので、その場合は一時的にローカル出力したファイルを圧縮した方が楽かもしれません。


Zip.java

package com.company;

import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

public class Zip {

public byte[] encryptZip(final String fileName, final byte[] input, String password) throws IOException, ZipException {
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
parameters.setPassword(password);

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (net.lingala.zip4j.io.ZipOutputStream zipOutputStream = new net.lingala.zip4j.io.ZipOutputStream(byteArrayOutputStream)) {
File file = new File(fileName) {
@Override
public boolean exists() {return true;}
@Override
public boolean isDirectory() {return false;}
@Override
public String getAbsolutePath() {return fileName;}
@Override
public boolean isHidden() {return false;}
@Override
public long lastModified() {return System.currentTimeMillis();}
@Override
public long length() {return input.length;}
};

zipOutputStream.putNextEntry(file, parameters);
zipOutputStream.write(input);
zipOutputStream.closeEntry();
zipOutputStream.finish();
}

return byteArrayOutputStream.toByteArray();

}
}



呼び出し

あとはファイル名と暗号化zip圧縮したいバイト配列、パスワードを渡すだけです


Main.java

    public static void main(String[] args) {

Zip zip = new Zip();
try {
byte[] encrypted = zip.encryptZip("hoge.txt", new byte[]{0x30, 0x30}, "testPwd");
try(FileOutputStream stream = new FileOutputStream(".\test.zip")) {
stream.write(encrypted);
}
} catch (IOException | ZipException e) {
e.printStackTrace();
}
}

全部オンメモリで処理したい場合はこうなるかなと。