Compare commits

..

2 Commits

4 changed files with 132 additions and 89 deletions

View File

@@ -1,131 +1,141 @@
package com.zuc.zuc256; package com.zuc.zuc256;
import java.util.Arrays; import javacard.framework.JCSystem;
import javacard.framework.Util;
import static com.zuc.zuc256.Zuc256Core.zuc256GenerateKeystream;
import static com.zuc.zuc256.Zuc256Core.zuc256GenerateKeyword;
import static com.zuc.zuc256.Zuc256Util.getU32;
import static com.zuc.zuc256.Zuc256Util.putU32;
/** /**
* 加密上下文类 * 加密上下文类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);
}
} }

View File

@@ -1,15 +1,34 @@
package com.zuc.zuc256; package com.zuc.zuc256;
import javacard.framework.JCSystem;
/** /**
* MAC上下文类 * MAC上下文类Java Card兼容版本
*/ */
public final class Zuc256MacCtx { public final class Zuc256MacCtx {
int[] LFSR = new int[16]; // 所有32位int类型改为16位short类型适应Java Card 16位处理能力
int R1; short[] LFSR;
int R2; short R1;
byte[] buf = new byte[4]; short R2;
int buflen; byte[] buf;
int[] T = new int[4]; short buflen; // 长度变量使用short类型
int[] K0 = new int[4]; short[] T;
int macbits; 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;
}
} }

View File

@@ -1,10 +1,22 @@
package com.zuc.zuc256; package com.zuc.zuc256;
import javacard.framework.JCSystem;
/** /**
* ZUC状态类 * ZUC状态类Java Card兼容版本
*/ */
public final class Zuc256State { public final class Zuc256State {
int[] LFSR = new int[16]; // 线性反馈移位寄存器 // 适配Java Card 16位处理能力将int改为short
int R1; // 寄存器1 short[] LFSR; // 线性反馈移位寄存器
int R2; // 寄存器2 short R1; // 寄存器1
short R2; // 寄存器2
// 构造函数初始化瞬态数组
public Zuc256State() {
// 创建瞬态short数组长度16选择在卡片复位或切换应用时清除
LFSR = JCSystem.makeTransientShortArray((short)16, JCSystem.CLEAR_ON_DESELECT);
// 初始化寄存器值为0
R1 = 0;
R2 = 0;
}
} }

View File

@@ -3,13 +3,15 @@ package com.zuc.zuc256;
/** /**
* 常量表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, S116bit short数组适配
public static final int[] S0 = { public static final short[] S0 = {
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb, 0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90, 0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac, 0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
@@ -28,7 +30,7 @@ public final class Zuc256Tables {
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60 0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
}; };
public static final int[] S1 = { public static final short[] S1 = {
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77, 0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42, 0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1, 0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
@@ -48,12 +50,12 @@ public final class Zuc256Tables {
}; };
/** /**
* 常量数组 D * 常量数组 D16bit short二维数组适配
*/ */
public static final int[][] 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},
{0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30}, {0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30}, {0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30} {0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30}
}; };
} }