java 压缩加密_java代码实现加密压缩文件解压

本文介绍了一个用于解密受密码保护的ZIP文件的Java类。该类通过读取ZIP文件头并使用提供的密码来初始化解密过程,从而允许访问加密的数据。文章还提供了一个示例程序,演示了如何使用此类从受保护的ZIP文件中提取文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.dashu.basicinfo.zip;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.zip.ZipEntry;

import java.util.zip.ZipInputStream;

public class ZipDecryptInputStream extends InputStream {

private static final int[] CRC_TABLE = new int[256];

// compute the table

// (could also have it pre-computed - see http://snippets.dzone.com/tag/crc32)

static {

for (int i = 0; i < 256; i++) {

int r = i;

for (int j = 0; j < 8; j++) {

if ((r & 1) == 1) {

r = (r >>> 1) ^ 0xedb88320;

} else {

r >>>= 1;

}

}

CRC_TABLE[i] = r;

}

}

private static final int DECRYPT_HEADER_SIZE = 12;

private static final int[] LFH_SIGNATURE = {0x50, 0x4b, 0x03, 0x04};

private final InputStream delegate;

private final String password;

private final int keys[] = new int[3];

private State state = State.SIGNATURE;

private int skipBytes;

private int compressedSize;

private int value;

private int valuePos;

private int valueInc;

public ZipDecryptInputStream(InputStream stream, String password) {

this.delegate = stream;

this.password = password;

}

@Override

public int read() throws IOException {

int result = delegate.read();

if (skipBytes == 0) {

switch (state) {

case SIGNATURE:

if (result != LFH_SIGNATURE[valuePos]) {

state = State.TAIL;

} else {

valuePos++;

if (valuePos >= LFH_SIGNATURE.length) {

skipBytes = 2;

state = State.FLAGS;

}

}

break;

case FLAGS:

if ((result & 1) == 0) {

throw new IllegalStateException("ZIP not password protected.");

}

if ((result & 64) == 64) {

throw new IllegalStateException("Strong encryption used.");

}

if ((result & 8) == 8) {

throw new IllegalStateException("Unsupported ZIP format.");

}

result -= 1;

compressedSize = 0;

valuePos = 0;

valueInc = DECRYPT_HEADER_SIZE;

state = State.COMPRESSED_SIZE;

skipBytes = 11;

break;

case COMPRESSED_SIZE:

compressedSize += result << (8 * valuePos);

result -= valueInc;

if (result < 0) {

valueInc = 1;

result += 256;

} else {

valueInc = 0;

}

valuePos++;

if (valuePos > 3) {

valuePos = 0;

value = 0;

state = State.FN_LENGTH;

skipBytes = 4;

}

break;

case FN_LENGTH:

case EF_LENGTH:

value += result << 8 * valuePos;

if (valuePos == 1) {

valuePos = 0;

if (state == State.FN_LENGTH) {

state = State.EF_LENGTH;

} else {

state = State.HEADER;

skipBytes = value;

}

} else {

valuePos = 1;

}

break;

case HEADER:

initKeys(password);

for (int i = 0; i < DECRYPT_HEADER_SIZE; i++) {

updateKeys((byte) (result ^ decryptByte()));

result = delegate.read();

}

compressedSize -= DECRYPT_HEADER_SIZE;

state = State.DATA;

// intentionally no break

case DATA:

result = (result ^ decryptByte()) & 0xff;

updateKeys((byte) result);

compressedSize--;

if (compressedSize == 0) {

valuePos = 0;

state = State.SIGNATURE;

}

break;

case TAIL:

// do nothing

}

} else {

skipBytes--;

}

return result;

}

@Override

public void close() throws IOException {

delegate.close();

super.close();

}

private void initKeys(String password) {

keys[0] = 305419896;

keys[1] = 591751049;

keys[2] = 878082192;

for (int i = 0; i < password.length(); i++) {

updateKeys((byte) (password.charAt(i) & 0xff));

}

}

private void updateKeys(byte charAt) {

keys[0] = crc32(keys[0], charAt);

keys[1] += keys[0] & 0xff;

keys[1] = keys[1] * 134775813 + 1;

keys[2] = crc32(keys[2], (byte) (keys[1] >> 24));

}

private byte decryptByte() {

int temp = keys[2] | 2;

return (byte) ((temp * (temp ^ 1)) >>> 8);

}

private int crc32(int oldCrc, byte charAt) {

return ((oldCrc >>> 8) ^ CRC_TABLE[(oldCrc ^ charAt) & 0xff]);

}

private static enum State {

SIGNATURE, FLAGS, COMPRESSED_SIZE, FN_LENGTH, EF_LENGTH, HEADER, DATA, TAIL

}

public static void main(String[] args) throws Exception {

// password-protected zip file I need to read

FileInputStream fis = new FileInputStream("d:/123/one.zip");

// wrap it in the decrypt stream

ZipDecryptInputStream zdis = new ZipDecryptInputStream(fis, "1234567");

// wrap the decrypt stream by the ZIP input stream

ZipInputStream zis = new ZipInputStream(zdis);

// read all the zip entries and save them as files

ZipEntry ze;

while ((ze = zis.getNextEntry()) != null) {

File f = new File("d:/123/"+ze.getName());

FileOutputStream fos = new FileOutputStream(f);

int b;

try {

while ((b = zis.read()) != -1) {

fos.write(b);

}

} catch (Exception e) {

fos.close();

f.delete();

zis.closeEntry();

break;

}

fos.close();

zis.closeEntry();

}

zis.close();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值