文章16 | 阅读 7015 | 点赞0
在java中提供了CipherInputStream
和CipherOutputStream
用于加解密的流处理,但是我在实际使用中发现会有一些莫名其妙的问题,数据丢失等,所以重写了两个流处理类。
package com.jianggujin.codec.util;
public interface JCipherStream {
/** * 长度为0的字节数组, 在编码解码时需要的话可以使用. */
byte[] EMPTY_BYTE_ARRAY = new byte[0];
int BLOCK_SIZE = 64;
}
package com.jianggujin.codec.util;
import java.io.IOException;
import java.io.InputStream;
import javax.crypto.Cipher;
public class JCipherInputStream extends InputStream implements JCipherStream {
private InputStream in;
private Cipher cipher;
private byte[] oneByteBuf = new byte[1];
private byte[] outBuf;
private int outByteCount = 0;
private int outByteOffset = 0;
private byte[] readBuf = new byte[128];
private boolean readOver = false;
public JCipherInputStream(Cipher cipher, InputStream in) {
this.cipher = cipher;
this.in = in;
}
public int read() throws IOException {
int count = this.read(this.oneByteBuf);
if (count != 1) {
return -1;
}
return this.oneByteBuf[0] & 0xff;
}
public int read(byte b[]) throws IOException {
if (b == null) {
throw new NullPointerException();
}
if (this.outByteCount == -1) {
return -1;
}
int hasCount = this.outByteCount - this.outByteOffset;
if (hasCount > b.length) {
System.arraycopy(this.outBuf, this.outByteOffset, b, 0, b.length);
this.outByteOffset += b.length;
return b.length;
}
int sum = 0;
int leftCount = b.length;
int copyPos = 0;
while (leftCount > 0) {
if (hasCount == 0) {
if (!this.readToBuf()) {
return sum == 0 ? -1 : sum;
}
}
hasCount = this.outByteCount - this.outByteOffset;
if (hasCount >= leftCount) {
System.arraycopy(this.outBuf, this.outByteOffset, b, copyPos, leftCount);
this.outByteOffset += leftCount;
sum += leftCount;
return sum;
} else {
System.arraycopy(this.outBuf, this.outByteOffset, b, copyPos, hasCount);
leftCount -= hasCount;
this.outByteOffset += hasCount;
sum += hasCount;
copyPos += hasCount;
hasCount = 0;
}
}
return sum;
}
private boolean readToBuf() throws IOException {
int count = this.in.read(this.readBuf);
if (count == -1) {
if (!this.readOver) {
byte[] result;
try {
result = this.cipher.doFinal(EMPTY_BYTE_ARRAY);
} catch (Exception e) {
throw new IOException(e);
}
this.outByteOffset = 0;
this.outByteCount = result.length;
this.outBuf = result;
this.readOver = true;
return result.length > 0;
}
this.outByteCount = -1;
this.outByteOffset = 0;
this.outBuf = null;
return false;
}
byte[] rbuf;
boolean over = count < this.readBuf.length;
if (!over) {
rbuf = this.readBuf;
} else {
rbuf = new byte[count];
System.arraycopy(this.readBuf, 0, rbuf, 0, count);
this.readOver = true;
}
byte[] result;
try {
result = over ? this.cipher.doFinal(rbuf) : this.cipher.update(rbuf);
} catch (Exception e) {
throw new IOException(e);
}
this.outByteOffset = 0;
this.outByteCount = result.length;
this.outBuf = result;
return true;
}
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if (off == 0 && len == b.length) {
return this.read(b);
}
int sum = 0;
int leftCount = len;
int nowCount = 0;
int copyPos = off;
byte[] temp = new byte[BLOCK_SIZE];
while (leftCount > 0) {
if (leftCount > BLOCK_SIZE) {
leftCount -= BLOCK_SIZE;
nowCount = BLOCK_SIZE;
} else {
temp = new byte[leftCount];
nowCount = leftCount;
leftCount = 0;
}
int count = this.read(temp);
if (count == -1) {
return sum == 0 ? -1 : sum;
} else if (count < nowCount) {
sum += count;
System.arraycopy(temp, 0, b, copyPos, count);
return sum;
}
System.arraycopy(temp, 0, b, copyPos, count);
sum += count;
copyPos += count;
}
return sum;
}
public int available() throws IOException {
return this.in.available();
}
public void close() throws IOException {
try {
this.cipher.doFinal(EMPTY_BYTE_ARRAY);
} catch (Exception e) {
throw new IOException(e);
}
this.in.close();
}
}
package com.jianggujin.codec.util;
import java.io.IOException;
import java.io.OutputStream;
import javax.crypto.Cipher;
public class JCipherOutputStream extends OutputStream implements JCipherStream {
private OutputStream out;
private Cipher cipher;
private byte[] oneByteBuf = new byte[1];
public JCipherOutputStream(Cipher cipher, OutputStream out) {
this.cipher = cipher;
this.out = out;
}
public void write(int b) throws IOException {
this.oneByteBuf[0] = (byte) b;
this.write(this.oneByteBuf);
}
public void write(byte b[]) throws IOException {
if (b == null) {
throw new NullPointerException();
}
byte[] result = this.cipher.update(b);
if (result.length > 0) {
this.out.write(result);
}
}
public void write(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
if (off == 0 && len == b.length) {
this.write(b);
return;
}
int leftCount = len;
int copyPos = off;
byte[] temp = new byte[BLOCK_SIZE];
while (leftCount > 0) {
if (leftCount > BLOCK_SIZE) {
System.arraycopy(b, copyPos, temp, 0, BLOCK_SIZE);
this.write(temp);
leftCount -= BLOCK_SIZE;
copyPos += BLOCK_SIZE;
} else {
temp = new byte[leftCount];
System.arraycopy(b, copyPos, temp, 0, leftCount);
this.write(temp);
copyPos += leftCount;
leftCount = 0;
}
}
}
public void flush() throws IOException {
this.out.flush();
}
public void close() throws IOException {
byte[] result;
try {
result = this.cipher.doFinal(EMPTY_BYTE_ARRAY);
} catch (Exception e) {
throw new IOException(e);
}
if (result.length > 0) {
this.out.write(result);
}
this.out.flush();
this.out.close();
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/jianggujin/article/details/81409723
内容来源于网络,如有侵权,请联系作者删除!