130 lines
3.7 KiB
Java
130 lines
3.7 KiB
Java
package com.cscn.zuc256;
|
||
|
||
import com.cscn.Zuc256Core;
|
||
import com.cscn.Zuc256State;
|
||
|
||
import java.util.Arrays;
|
||
|
||
|
||
/**
|
||
* 加密上下文类
|
||
*/
|
||
public final class Zuc256EncryptCtx {
|
||
Zuc256State state;
|
||
byte[] buf;
|
||
int buflen;
|
||
|
||
public Zuc256EncryptCtx(Zuc256State state, byte[] buf){
|
||
this.state = state;
|
||
this.buf = buf;
|
||
}
|
||
|
||
public Zuc256EncryptCtx(Zuc256State state){
|
||
this.state = state;
|
||
this.buf = new byte[4];
|
||
}
|
||
|
||
public Zuc256EncryptCtx(){
|
||
this.state = new Zuc256State();
|
||
this.buf = new byte[4];
|
||
}
|
||
|
||
// 初始化加密上下文
|
||
public void init(byte[] key32, byte[] iv) {
|
||
Arrays.fill(this.buf, (byte) 0);
|
||
this.buflen = 0;
|
||
Zuc256Core.initState(this.state, key32, iv);
|
||
}
|
||
|
||
// 分阶段处理加密数据
|
||
public void update(byte[] in, int inlen, byte[] out) {
|
||
if (in == null || out == null || inlen == 0) return;
|
||
|
||
// 处理缓冲区中剩余的非4字节数据
|
||
if (this.buflen > 0) {
|
||
int need = 4 - this.buflen;
|
||
int copy = Math.min(inlen, need);
|
||
|
||
System.arraycopy(in, 0, this.buf, this.buflen, copy);
|
||
this.buflen += copy;
|
||
|
||
// 调整输入指针和长度
|
||
byte[] newIn = new byte[inlen - copy];
|
||
if (inlen - copy > 0) {
|
||
System.arraycopy(in, copy, newIn, 0, inlen - copy);
|
||
}
|
||
in = newIn;
|
||
inlen -= copy;
|
||
|
||
// 缓冲区已满,处理一个完整的4字节块
|
||
if (this.buflen == 4) {
|
||
int keystream = zuc256GenerateKeyword(this.state);
|
||
int plain = getU32(this.buf, 0);
|
||
putU32(out, 0, plain ^ keystream);
|
||
|
||
this.buflen = 0;
|
||
Arrays.fill(this.buf, (byte) 0);
|
||
|
||
// 调整输出指针
|
||
byte[] newOut = new byte[out.length - 4];
|
||
if (out.length - 4 > 0) {
|
||
System.arraycopy(out, 4, newOut, 0, out.length - 4);
|
||
}
|
||
out = newOut;
|
||
}
|
||
}
|
||
|
||
// 处理完整的4字节块
|
||
int fullBlocks = inlen / 4;
|
||
if (fullBlocks > 0) {
|
||
int[] keystream = new int[fullBlocks];
|
||
zuc256GenerateKeystream(this.state, fullBlocks, keystream);
|
||
|
||
// 逐块异或加密
|
||
for (int i = 0; i < fullBlocks; i++) {
|
||
int plain = getU32(in, i * 4);
|
||
putU32(out, i * 4, plain ^ keystream[i]);
|
||
}
|
||
|
||
// 调整输入指针和长度
|
||
int processed = fullBlocks * 4;
|
||
byte[] newIn = new byte[inlen - processed];
|
||
if (inlen - processed > 0) {
|
||
System.arraycopy(in, processed, newIn, 0, inlen - processed);
|
||
}
|
||
in = newIn;
|
||
inlen -= processed;
|
||
}
|
||
|
||
// 缓存剩余不足4字节的数据
|
||
if (inlen > 0) {
|
||
System.arraycopy(in, 0, this.buf, 0, inlen);
|
||
this.buflen = inlen;
|
||
}
|
||
}
|
||
|
||
// 完成加密处理
|
||
public void finish(byte[] out) {
|
||
if (this == null || out == null) return;
|
||
|
||
// 处理缓冲区中剩余的不足4字节数据
|
||
if (this.buflen > 0) {
|
||
int keystream = zuc256GenerateKeyword(this.state);
|
||
byte[] keystreamBytes = new byte[4];
|
||
putU32(keystreamBytes, 0, keystream);
|
||
|
||
// 逐字节异或
|
||
for (int i = 0; i < this.buflen; i++) {
|
||
out[i] = (byte) (this.buf[i] ^ keystreamBytes[i]);
|
||
}
|
||
}
|
||
|
||
// 清理上下文
|
||
Arrays.fill(this.buf, (byte) 0);
|
||
this.buflen = 0;
|
||
Arrays.fill(this.state.LFSR, 0);
|
||
this.state.R1 = 0;
|
||
this.state.R2 = 0;
|
||
}
|
||
}
|