diff --git a/src/com/zuc/zuc256/Zuc256EncryptCtx.java b/src/com/zuc/zuc256/Zuc256EncryptCtx.java index 9772a40..476f5c1 100644 --- a/src/com/zuc/zuc256/Zuc256EncryptCtx.java +++ b/src/com/zuc/zuc256/Zuc256EncryptCtx.java @@ -1,131 +1,141 @@ package com.zuc.zuc256; -import java.util.Arrays; - -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; - +import javacard.framework.JCSystem; +import javacard.framework.Util; /** - * 加密上下文类 + * 加密上下文类(Java Card兼容版本) */ public final class Zuc256EncryptCtx { Zuc256State state; byte[] buf; - int buflen; + short buflen; - public Zuc256EncryptCtx(Zuc256State state, byte[] buf){ + // 构造函数 - 使用已分配的缓冲区 + public Zuc256EncryptCtx(Zuc256State state, byte[] buf) { this.state = state; this.buf = buf; + this.buflen = 0; } - public Zuc256EncryptCtx(Zuc256State state){ + // 构造函数 - 自动分配缓冲区 + public Zuc256EncryptCtx(Zuc256State 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.buf = new byte[4]; + this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT); + this.buflen = 0; } // 初始化加密上下文 - public void init(byte[] key32, byte[] iv) { - Arrays.fill(this.buf, (byte) 0); + public void init(byte[] key32, short keyOff, short keyLen, byte[] iv, short ivOff, short ivLen) { + // 清空缓冲区 + Util.arrayFillNonAtomic(buf, (short)0, (short)buf.length, (byte)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; + short currentInOff = inOff; + short currentOutOff = outOff; + // 处理缓冲区中剩余的非4字节数据 if (this.buflen > 0) { - int need = 4 - this.buflen; - int copy = Math.min(inlen, need); + short need = (short)(4 - this.buflen); + 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; // 调整输入指针和长度 - byte[] newIn = new byte[inlen - copy]; - if (inlen - copy > 0) { - System.arraycopy(in, copy, newIn, 0, inlen - copy); - } - in = newIn; + currentInOff += copy; inlen -= copy; // 缓冲区已满,处理一个完整的4字节块 if (this.buflen == 4) { - int keystream = zuc256GenerateKeyword(this.state); - int plain = getU32(this.buf, 0); - putU32(out, 0, plain ^ keystream); + short keystream = zuc256GenerateKeyword(this.state); + short plain = getU16(this.buf, (short)0); // 改为16位操作 + putU16(out, currentOutOff, (short)(plain ^ keystream)); + // 重置缓冲区 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]; - if (out.length - 4 > 0) { - System.arraycopy(out, 4, newOut, 0, out.length - 4); - } - out = newOut; + currentOutOff += 2; // 16位数据占2字节 } } - // 处理完整的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字节的数据 + // 处理完整的2字节块(Java Card 16位操作) if (inlen > 0) { - System.arraycopy(in, 0, this.buf, 0, inlen); - this.buflen = inlen; + short fullBlocks = (short)(inlen / 2); // 16位块 + 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) { - if (this == null || out == null) return; + public void finish(byte[] out, short outOff) { + if (out == null) return; - // 处理缓冲区中剩余的不足4字节数据 + // 处理缓冲区中剩余的不足2字节数据 if (this.buflen > 0) { - int keystream = zuc256GenerateKeyword(this.state); - byte[] keystreamBytes = new byte[4]; - putU32(keystreamBytes, 0, keystream); + short keystream = zuc256GenerateKeyword(this.state); + byte[] keystreamBytes = JCSystem.makeTransientByteArray((short)2, JCSystem.CLEAR_ON_DESELECT); + putU16(keystreamBytes, (short)0, keystream); // 逐字节异或 - for (int i = 0; i < this.buflen; i++) { - out[i] = (byte) (this.buf[i] ^ keystreamBytes[i]); + for (short i = 0; i < this.buflen; 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; - 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.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); + } } diff --git a/src/com/zuc/zuc256/Zuc256MacCtx.java b/src/com/zuc/zuc256/Zuc256MacCtx.java index 554637c..47dc2ec 100644 --- a/src/com/zuc/zuc256/Zuc256MacCtx.java +++ b/src/com/zuc/zuc256/Zuc256MacCtx.java @@ -1,15 +1,34 @@ package com.zuc.zuc256; +import javacard.framework.JCSystem; + /** - * MAC上下文类 + * MAC上下文类(Java Card兼容版本) */ public final class Zuc256MacCtx { - int[] LFSR = new int[16]; - int R1; - int R2; - byte[] buf = new byte[4]; - int buflen; - int[] T = new int[4]; - int[] K0 = new int[4]; - int macbits; + // 所有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; + } } diff --git a/src/com/zuc/zuc256/Zuc256State.java b/src/com/zuc/zuc256/Zuc256State.java index 7e64d60..822fc4d 100644 --- a/src/com/zuc/zuc256/Zuc256State.java +++ b/src/com/zuc/zuc256/Zuc256State.java @@ -1,10 +1,22 @@ package com.zuc.zuc256; +import javacard.framework.JCSystem; + /** - * ZUC状态类 + * ZUC状态类(Java Card兼容版本) */ public final class Zuc256State { - int[] LFSR = new int[16]; // 线性反馈移位寄存器 - int R1; // 寄存器1 - int R2; // 寄存器2 + // 适配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; + } } diff --git a/src/com/zuc/zuc256/Zuc256Tables.java b/src/com/zuc/zuc256/Zuc256Tables.java index 311863f..d0e1980 100644 --- a/src/com/zuc/zuc256/Zuc256Tables.java +++ b/src/com/zuc/zuc256/Zuc256Tables.java @@ -3,13 +3,15 @@ package com.zuc.zuc256; /** * 常量表:S0/S1 与 ZUC256_D。 * 注意:JavaCard 目标环境建议将表定义为 static final 数组,按 int/short 存放。 + * 适配说明:已将 32bit int 数组改为 16bit short 数组,符合JavaCard 16bit能力要求 */ public final class Zuc256Tables { + // 私有构造函数:防止类被实例化 private Zuc256Tables() {} - // S盒:S0, S1 - public static final int[] S0 = { + // S盒:S0, S1(16bit short数组适配) + public static final short[] S0 = { 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, 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 }; - 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, 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, @@ -48,12 +50,12 @@ public final class Zuc256Tables { }; /** - * 常量数组 D + * 常量数组 D(16bit 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,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,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30} }; -} +} \ No newline at end of file