Compare commits
3 Commits
b331864cee
...
4dcf92584c
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dcf92584c | |||
| 8893172ea9 | |||
| 11c46c5557 |
@@ -1,131 +1,141 @@
|
|||||||
package com.cscn;
|
package com.zuc.zuc256;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import static com.cscn.Zuc256Core.zuc256GenerateKeystream;
|
|
||||||
import static com.cscn.Zuc256Core.zuc256GenerateKeyword;
|
|
||||||
import static com.cscn.Zuc256Util.getU32;
|
|
||||||
import static com.cscn.Zuc256Util.putU32;
|
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密上下文类
|
* 加密上下文类(Java Card兼容版本)
|
||||||
*/
|
*/
|
||||||
public final class Zuc256EncryptCtx {
|
public final class Zuc256EncryptCtx {
|
||||||
Zuc256State state;
|
Zuc256State state;
|
||||||
byte[] buf;
|
byte[] buf;
|
||||||
int buflen;
|
short buflen;
|
||||||
|
|
||||||
public Zuc256EncryptCtx(Zuc256State state, byte[] buf){
|
// 构造函数 - 使用已分配的缓冲区
|
||||||
|
public Zuc256EncryptCtx(Zuc256State state, byte[] buf) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.buf = buf;
|
this.buf = buf;
|
||||||
|
this.buflen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Zuc256EncryptCtx(Zuc256State state){
|
// 构造函数 - 自动分配缓冲区
|
||||||
|
public Zuc256EncryptCtx(Zuc256State state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.buf = new byte[4];
|
this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
this.buflen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Zuc256EncryptCtx(){
|
// 构造函数 - 完整初始化
|
||||||
|
public Zuc256EncryptCtx() {
|
||||||
this.state = new Zuc256State();
|
this.state = new Zuc256State();
|
||||||
this.buf = new byte[4];
|
this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
this.buflen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化加密上下文
|
// 初始化加密上下文
|
||||||
public void init(byte[] key32, byte[] iv) {
|
public void init(byte[] key32, short keyOff, short keyLen, byte[] iv, short ivOff, short ivLen) {
|
||||||
Arrays.fill(this.buf, (byte) 0);
|
// 清空缓冲区
|
||||||
|
Util.arrayFillNonAtomic(buf, (short)0, (short)buf.length, (byte)0);
|
||||||
this.buflen = 0;
|
this.buflen = 0;
|
||||||
Zuc256Core.initState(this.state, key32, iv);
|
// 初始化状态
|
||||||
|
Zuc256Core.initState(this.state, key32, keyOff, keyLen, iv, ivOff, ivLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分阶段处理加密数据
|
// 分阶段处理加密数据
|
||||||
public void update(byte[] in, int inlen, byte[] out) {
|
public void update(byte[] in, short inOff, short inlen, byte[] out, short outOff) {
|
||||||
if (in == null || out == null || inlen == 0) return;
|
if (in == null || out == null || inlen == 0) return;
|
||||||
|
|
||||||
|
short currentInOff = inOff;
|
||||||
|
short currentOutOff = outOff;
|
||||||
|
|
||||||
// 处理缓冲区中剩余的非4字节数据
|
// 处理缓冲区中剩余的非4字节数据
|
||||||
if (this.buflen > 0) {
|
if (this.buflen > 0) {
|
||||||
int need = 4 - this.buflen;
|
short need = (short)(4 - this.buflen);
|
||||||
int copy = Math.min(inlen, need);
|
short copy = (short)Math.min(inlen, need);
|
||||||
|
|
||||||
System.arraycopy(in, 0, this.buf, this.buflen, copy);
|
// 复制数据到缓冲区
|
||||||
|
Util.arrayCopyNonAtomic(in, currentInOff, this.buf, this.buflen, copy);
|
||||||
this.buflen += copy;
|
this.buflen += copy;
|
||||||
|
|
||||||
// 调整输入指针和长度
|
// 调整输入指针和长度
|
||||||
byte[] newIn = new byte[inlen - copy];
|
currentInOff += copy;
|
||||||
if (inlen - copy > 0) {
|
|
||||||
System.arraycopy(in, copy, newIn, 0, inlen - copy);
|
|
||||||
}
|
|
||||||
in = newIn;
|
|
||||||
inlen -= copy;
|
inlen -= copy;
|
||||||
|
|
||||||
// 缓冲区已满,处理一个完整的4字节块
|
// 缓冲区已满,处理一个完整的4字节块
|
||||||
if (this.buflen == 4) {
|
if (this.buflen == 4) {
|
||||||
int keystream = zuc256GenerateKeyword(this.state);
|
short keystream = zuc256GenerateKeyword(this.state);
|
||||||
int plain = getU32(this.buf, 0);
|
short plain = getU16(this.buf, (short)0); // 改为16位操作
|
||||||
putU32(out, 0, plain ^ keystream);
|
putU16(out, currentOutOff, (short)(plain ^ keystream));
|
||||||
|
|
||||||
|
// 重置缓冲区
|
||||||
this.buflen = 0;
|
this.buflen = 0;
|
||||||
Arrays.fill(this.buf, (byte) 0);
|
Util.arrayFillNonAtomic(this.buf, (short)0, (short)this.buf.length, (byte)0);
|
||||||
|
|
||||||
// 调整输出指针
|
// 调整输出指针
|
||||||
byte[] newOut = new byte[out.length - 4];
|
currentOutOff += 2; // 16位数据占2字节
|
||||||
if (out.length - 4 > 0) {
|
|
||||||
System.arraycopy(out, 4, newOut, 0, out.length - 4);
|
|
||||||
}
|
|
||||||
out = newOut;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理完整的4字节块
|
// 处理完整的2字节块(Java Card 16位操作)
|
||||||
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) {
|
if (inlen > 0) {
|
||||||
System.arraycopy(in, 0, this.buf, 0, inlen);
|
short fullBlocks = (short)(inlen / 2); // 16位块
|
||||||
this.buflen = inlen;
|
if (fullBlocks > 0) {
|
||||||
|
short[] keystream = JCSystem.makeTransientShortArray(fullBlocks, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
zuc256GenerateKeystream(this.state, fullBlocks, keystream);
|
||||||
|
|
||||||
|
// 逐块异或加密
|
||||||
|
for (short i = 0; i < fullBlocks; i++) {
|
||||||
|
short plain = getU16(in, (short)(currentInOff + (short)(i * 2)));
|
||||||
|
putU16(out, (short)(currentOutOff + (short)(i * 2)), (short)(plain ^ keystream[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调整输入指针和长度
|
||||||
|
short processed = (short)(fullBlocks * 2);
|
||||||
|
currentInOff += processed;
|
||||||
|
inlen -= processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存剩余不足2字节的数据
|
||||||
|
if (inlen > 0) {
|
||||||
|
Util.arrayCopyNonAtomic(in, currentInOff, this.buf, (short)0, inlen);
|
||||||
|
this.buflen = inlen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 完成加密处理
|
// 完成加密处理
|
||||||
public void finish(byte[] out) {
|
public void finish(byte[] out, short outOff) {
|
||||||
if (this == null || out == null) return;
|
if (out == null) return;
|
||||||
|
|
||||||
// 处理缓冲区中剩余的不足4字节数据
|
// 处理缓冲区中剩余的不足2字节数据
|
||||||
if (this.buflen > 0) {
|
if (this.buflen > 0) {
|
||||||
int keystream = zuc256GenerateKeyword(this.state);
|
short keystream = zuc256GenerateKeyword(this.state);
|
||||||
byte[] keystreamBytes = new byte[4];
|
byte[] keystreamBytes = JCSystem.makeTransientByteArray((short)2, JCSystem.CLEAR_ON_DESELECT);
|
||||||
putU32(keystreamBytes, 0, keystream);
|
putU16(keystreamBytes, (short)0, keystream);
|
||||||
|
|
||||||
// 逐字节异或
|
// 逐字节异或
|
||||||
for (int i = 0; i < this.buflen; i++) {
|
for (short i = 0; i < this.buflen; i++) {
|
||||||
out[i] = (byte) (this.buf[i] ^ keystreamBytes[i]);
|
out[(short)(outOff + i)] = (byte)(this.buf[i] ^ keystreamBytes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理上下文
|
// 清理上下文
|
||||||
Arrays.fill(this.buf, (byte) 0);
|
Util.arrayFillNonAtomic(this.buf, (short)0, (short)this.buf.length, (byte)0);
|
||||||
this.buflen = 0;
|
this.buflen = 0;
|
||||||
Arrays.fill(this.state.LFSR, 0);
|
// 清理状态
|
||||||
|
Util.arrayFillNonAtomic(this.state.LFSR, (short)0, (short)this.state.LFSR.length, (short)0);
|
||||||
this.state.R1 = 0;
|
this.state.R1 = 0;
|
||||||
this.state.R2 = 0;
|
this.state.R2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 16位数据读取(替代原32位实现)
|
||||||
|
private short getU16(byte[] buf, short off) {
|
||||||
|
return (short)(((buf[off] & 0xFF) << 8) | (buf[(short)(off + 1)] & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 16位数据写入(替代原32位实现)
|
||||||
|
private void putU16(byte[] buf, short off, short value) {
|
||||||
|
buf[off] = (byte)((value >>> 8) & 0xFF);
|
||||||
|
buf[(short)(off + 1)] = (byte)(value & 0xFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ package com.cscn;
|
|||||||
/**
|
/**
|
||||||
* 常量表:S0/S1 与 ZUC256_D。
|
* 常量表:S0/S1 与 ZUC256_D。
|
||||||
* 注意:JavaCard 目标环境建议将表定义为 static final 数组,按 int/short 存放。
|
* 注意:JavaCard 目标环境建议将表定义为 static final 数组,按 int/short 存放。
|
||||||
|
* 适配说明:已将 32bit int 数组改为 16bit short 数组,符合JavaCard 16bit能力要求
|
||||||
*/
|
*/
|
||||||
public final class Zuc256Tables {
|
public final class Zuc256Tables {
|
||||||
|
|
||||||
|
// 私有构造函数:防止类被实例化
|
||||||
private Zuc256Tables() {}
|
private Zuc256Tables() {}
|
||||||
|
|
||||||
// S盒:S0, S1
|
// S盒:S0, S1
|
||||||
@@ -48,7 +50,7 @@ public final class Zuc256Tables {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 常量数组 D
|
* 常量数组 D(16bit short二维数组适配)
|
||||||
*/
|
*/
|
||||||
public static final short[][] ZUC256_D = {
|
public static final short[][] ZUC256_D = {
|
||||||
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
|||||||
34
src/com/zuc/zuc256/Zuc256MacCtx.java
Normal file
34
src/com/zuc/zuc256/Zuc256MacCtx.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.zuc.zuc256;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MAC上下文类(Java Card兼容版本)
|
||||||
|
*/
|
||||||
|
public final class Zuc256MacCtx {
|
||||||
|
// 所有32位int类型改为16位short类型,适应Java Card 16位处理能力
|
||||||
|
short[] LFSR;
|
||||||
|
short R1;
|
||||||
|
short R2;
|
||||||
|
byte[] buf;
|
||||||
|
short buflen; // 长度变量使用short类型
|
||||||
|
short[] T;
|
||||||
|
short[] K0;
|
||||||
|
short macbits; // MAC位数使用short类型
|
||||||
|
|
||||||
|
// 构造函数初始化瞬态数组,符合Java Card内存管理规范
|
||||||
|
public Zuc256MacCtx() {
|
||||||
|
// 使用瞬态内存存储敏感数据,提高安全性
|
||||||
|
// CLEAR_ON_DESELECT:卡片复位或选择其他应用时清除数据
|
||||||
|
LFSR = JCSystem.makeTransientShortArray((short)16, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
buf = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
T = JCSystem.makeTransientShortArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
K0 = JCSystem.makeTransientShortArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
|
||||||
|
// 初始化变量
|
||||||
|
R1 = 0;
|
||||||
|
R2 = 0;
|
||||||
|
buflen = 0;
|
||||||
|
macbits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/com/zuc/zuc256/Zuc256State.java
Normal file
22
src/com/zuc/zuc256/Zuc256State.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.zuc.zuc256;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZUC状态类(Java Card兼容版本)
|
||||||
|
*/
|
||||||
|
public final class Zuc256State {
|
||||||
|
// 适配Java Card 16位处理能力,将int改为short
|
||||||
|
short[] LFSR; // 线性反馈移位寄存器
|
||||||
|
short R1; // 寄存器1
|
||||||
|
short R2; // 寄存器2
|
||||||
|
|
||||||
|
// 构造函数初始化瞬态数组
|
||||||
|
public Zuc256State() {
|
||||||
|
// 创建瞬态short数组,长度16,选择在卡片复位或切换应用时清除
|
||||||
|
LFSR = JCSystem.makeTransientShortArray((short)16, JCSystem.CLEAR_ON_DESELECT);
|
||||||
|
// 初始化寄存器值为0
|
||||||
|
R1 = 0;
|
||||||
|
R2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user