From ed52d849a4729931d323f2f5d9b331887e99ee8c Mon Sep 17 00:00:00 2001 From: zcy Date: Fri, 5 Sep 2025 22:47:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=99=E5=9F=BA=E7=A1=80Applet=EF=BC=8C?= =?UTF-8?q?=E8=AF=95=E5=9B=BE=E6=B5=8B=E8=AF=95=E5=8A=A0=E8=A7=A3=E5=AF=86?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bat/Delivery/cscn.cap | Bin 0 -> 11793 bytes Bat/Delivery/cscn.exp | Bin 0 -> 42 bytes Project/Src/com/cscn/Method.java | 96 +++++++++++++++++++-- Project/Src/com/cscn/Zuc256Core.java | 39 ++++++--- Project/Src/com/cscn/Zuc256EncryptCtx.java | 11 ++- Project/Src/com/cscn/Zuc256Tables.java | 55 ++++++++++-- Project/Src/com/cscn/Zuc256Util.java | 16 ++-- src/com/zuc/zuc256/Zuc256MacCtx.java | 34 -------- src/com/zuc/zuc256/Zuc256State.java | 22 ----- 9 files changed, 177 insertions(+), 96 deletions(-) create mode 100644 Bat/Delivery/cscn.cap create mode 100644 Bat/Delivery/cscn.exp delete mode 100644 src/com/zuc/zuc256/Zuc256MacCtx.java delete mode 100644 src/com/zuc/zuc256/Zuc256State.java diff --git a/Bat/Delivery/cscn.cap b/Bat/Delivery/cscn.cap new file mode 100644 index 0000000000000000000000000000000000000000..fc372ade23983144823c9f267617febf0e39a786 GIT binary patch literal 11793 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 literal 0 HcmV?d00001 diff --git a/Bat/Delivery/cscn.exp b/Bat/Delivery/cscn.exp new file mode 100644 index 0000000000000000000000000000000000000000..6a4813171f80128f502b9336581353865ef10650 GIT binary patch literal 42 wcmZShb?P1?69W??14nXxu6}ZHavm=O5HRvCU|?WoC@x7X(ksYLXJBLi0OU>yuK)l5 literal 0 HcmV?d00001 diff --git a/Project/Src/com/cscn/Method.java b/Project/Src/com/cscn/Method.java index f7c847e..67d25ef 100644 --- a/Project/Src/com/cscn/Method.java +++ b/Project/Src/com/cscn/Method.java @@ -1,19 +1,97 @@ package com.cscn; import javacard.framework.APDU; +import javacard.framework.ISO7816; +import javacard.framework.ISOException; +import javacard.framework.JCSystem; +import javacard.framework.Util; -public class Method { +/** + * 仅做一次“自检调用”: + * 1) ctx.init(KEY, IV); Enc(Input) == EncExpected ? + * 2) ctx.init(KEY, IV); Enc(Enc(Input)) == Input ? + * Response: 2字节 [encMatch, dblEncRestored],1=真,0=假 + */ +public final class Method { - public void processData(APDU apdu) - { - // TODO Auto-generated method stub - + // ======= 请用你的向量替换下面占位内容 ======= + // Key: 32字节 + private static final byte[] KEY32 = new byte[] { + // TODO: 替换成你的32字节Key + (byte)0x00,(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07, + (byte)0x08,(byte)0x09,(byte)0x0A,(byte)0x0B,(byte)0x0C,(byte)0x0D,(byte)0x0E,(byte)0x0F, + (byte)0x10,(byte)0x11,(byte)0x12,(byte)0x13,(byte)0x14,(byte)0x15,(byte)0x16,(byte)0x17, + (byte)0x18,(byte)0x19,(byte)0x1A,(byte)0x1B,(byte)0x1C,(byte)0x1D,(byte)0x1E,(byte)0x1F + }; + + // IV: 25字节(ZUC-256) + private static final byte[] IV25 = new byte[] { + // TODO: 替换成你的25字节IV + (byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5,(byte)0xA6,(byte)0xA7, + (byte)0xA8,(byte)0xA9,(byte)0xAA,(byte)0xAB,(byte)0xAC,(byte)0xAD,(byte)0xAE,(byte)0xAF, + (byte)0xB0,(byte)0xB1,(byte)0xB2,(byte)0xB3,(byte)0xB4,(byte)0xB5,(byte)0xB6,(byte)0xB7, + (byte)0xB8 + }; + + // Input: 建议长度为 4 的倍数,便于不走 finish 的残字节路径 + private static final byte[] INPUT = new byte[] { + // TODO: 替换成你的明文(示例32字节) + (byte)0x11,(byte)0x22,(byte)0x33,(byte)0x44,(byte)0x55,(byte)0x66,(byte)0x77,(byte)0x88, + (byte)0x99,(byte)0xAA,(byte)0xBB,(byte)0xCC,(byte)0xDD,(byte)0xEE,(byte)0xFF,(byte)0x00, + (byte)0x10,(byte)0x20,(byte)0x30,(byte)0x40,(byte)0x50,(byte)0x60,(byte)0x70,(byte)0x80, + (byte)0x90,(byte)0xA0,(byte)0xB0,(byte)0xC0,(byte)0xD0,(byte)0xE0,(byte)0xF0,(byte)0x00 + }; + + // EncResult: 期望密文(与上面的 Input 配套) + private static final byte[] ENC_EXPECTED = new byte[] { + // TODO: 替换成你“已知正确”的密文(示例随便填;不改会导致第一项校验=0) + (byte)0x21,(byte)0x32,(byte)0x43,(byte)0x54,(byte)0x65,(byte)0x76,(byte)0x87,(byte)0x98, + (byte)0xA9,(byte)0xBA,(byte)0xCB,(byte)0xDC,(byte)0xED,(byte)0xFE,(byte)0x0F,(byte)0x1E, + (byte)0x2D,(byte)0x3C,(byte)0x4B,(byte)0x5A,(byte)0x69,(byte)0x78,(byte)0x87,(byte)0x96, + (byte)0xA5,(byte)0xB4,(byte)0xC3,(byte)0xD2,(byte)0xE1,(byte)0xF0,(byte)0x0F,(byte)0x00 + }; + // ====================================== + + // 运行时缓冲:放RAM,避免写EEPROM + private final byte[] buf1; // Enc(Input) + private final byte[] buf2; // Enc(Enc(Input)) -> 应为 Input + private final Zuc256EncryptCtx ctx; + + public Method() { + short L = (short) INPUT.length; + buf1 = JCSystem.makeTransientByteArray(L, JCSystem.CLEAR_ON_DESELECT); + buf2 = JCSystem.makeTransientByteArray(L, JCSystem.CLEAR_ON_DESELECT); + ctx = new Zuc256EncryptCtx(); // 仅创建一次 } - public void updateKey(APDU apdu) - { - // TODO Auto-generated method stub - + public void processData(APDU apdu) { + byte[] apduBuf = apdu.getBuffer(); + + // 第一次:Enc(Input) + ctx.init(KEY32, IV25); + ctx.update(INPUT, (short) INPUT.length, buf1); + ctx.finish(buf1); // 若 Input 长度为 4 的倍数则通常无副作用,留着更稳妥 + + boolean encMatch = (Util.arrayCompare(buf1, (short)0, ENC_EXPECTED, (short)0, (short)INPUT.length) == 0); + + // 第二次:Enc(Enc(Input)) 应还原 Input + ctx.init(KEY32, IV25); + ctx.update(buf1, (short) INPUT.length, buf2); + ctx.finish(buf2); + boolean dblOk = (Util.arrayCompare(buf2, (short)0, INPUT, (short)0, (short)INPUT.length) == 0); + + // 返回 2 字节结果:[encMatch, dblOk],1=真, 0=假 + apduBuf[0] = (byte)(encMatch ? 1 : 0); + apduBuf[1] = (byte)(dblOk ? 1 : 0); + short outLen = 2; + + apdu.setOutgoing(); + apdu.setOutgoingLength(outLen); + apdu.sendBytes((short)0, outLen); } + // 本任务不需要更新Key,这里留空 + public void updateKey(APDU apdu) { + ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); + } } diff --git a/Project/Src/com/cscn/Zuc256Core.java b/Project/Src/com/cscn/Zuc256Core.java index 1a7b27b..fbde3b6 100644 --- a/Project/Src/com/cscn/Zuc256Core.java +++ b/Project/Src/com/cscn/Zuc256Core.java @@ -215,9 +215,13 @@ public final class Zuc256Core { // System.arraycopy(LFSR, 1, LFSR, 0, 15); // LFSR_lo 向左移 - System.arraycopy(state.LFSR_lo, 1, state.LFSR_lo, 0, 15); + for (short i = 0; i < (short)15; i++) { + state.LFSR_lo[i] = state.LFSR_lo[(short)(i + 1)]; + } // LFSR_hi 向左移 - System.arraycopy(state.LFSR_hi, 1, state.LFSR_hi, 0, 15); + for (short i = 0; i < (short)15; i++) { + state.LFSR_hi[i] = state.LFSR_hi[(short)(i + 1)]; + } // LFSR[15] = v; // ---- 写回 LFSR[15] ---- @@ -260,7 +264,7 @@ public final class Zuc256Core { // 初始化MAC密钥 private static void zuc256SetMacKey(Zuc256State state, byte[] K, byte[] IV, short macbits) { - short[] D; + short[] D = JCSystem.makeTransientShortArray(Zuc256Tables.D_COLS, JCSystem.CLEAR_ON_DESELECT); short[] TMP = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_DESELECT); short[] X0 = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_DESELECT); short[] X1 = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_DESELECT); @@ -295,11 +299,9 @@ public final class Zuc256Core { short IV24 = (short)(IV[22] & 0x3F); // D = (macbits / 32 < 3) ? Zuc256Tables.ZUC256_D[macbits / 32] : Zuc256Tables.ZUC256_D[3]; - if ((macbits / 32) < 3) { - D = Zuc256Tables.ZUC256_D[macbits / 32]; - } else { - D = Zuc256Tables.ZUC256_D[3]; - } + short row = (short)((macbits / 32) < 3 ? (macbits / 32) : 3); + Zuc256Tables.getDRow(row, D, (short)0); + Zuc256Tables.getDRow(row, D, (short)0); short[] tmp = new short[2]; // 临时存储 makeU31 输出 (lo,hi) @@ -462,8 +464,14 @@ public final class Zuc256Core { add31(V[0], V[1], T2[0], T2[1], V); // System.arraycopy(state.LFSR, 1, state.LFSR, 0, 15) - System.arraycopy(state.LFSR_lo, 1, state.LFSR_lo, 0, 15); - System.arraycopy(state.LFSR_hi, 1, state.LFSR_hi, 0, 15); +// 相当于 System.arraycopy(state.LFSR_lo, 1, state.LFSR_lo, 0, 15); + for (short j = 0; j < (short)15; j++) { + state.LFSR_lo[j] = state.LFSR_lo[(short)(j + 1)]; + } +// 相当于 System.arraycopy(state.LFSR_hi, 1, state.LFSR_hi, 0, 15); + for (short j = 0; j < (short)15; j++) { + state.LFSR_hi[j] = state.LFSR_hi[(short)(j + 1)]; + } // state.LFSR[15] = v; state.LFSR_lo[15] = V[0]; @@ -567,9 +575,16 @@ public final class Zuc256Core { // LFSR左移 // System.arraycopy(LFSR, 1, LFSR, 0, 15); + // LFSR_lo 向左移 + for (short i = 0; i < (short)15; i++) { + state.LFSR_lo[i] = state.LFSR_lo[(short)(i + 1)]; + } + // LFSR_hi 向左移 + for (short i = 0; i < (short)15; i++) { + state.LFSR_hi[i] = state.LFSR_hi[(short)(i + 1)]; + } + // LFSR[15] = v; - System.arraycopy(state.LFSR_lo, 1, state.LFSR_lo, 0, 15); - System.arraycopy(state.LFSR_hi, 1, state.LFSR_hi, 0, 15); state.LFSR_lo[15] = v_lo; state.LFSR_hi[15] = v_hi; diff --git a/Project/Src/com/cscn/Zuc256EncryptCtx.java b/Project/Src/com/cscn/Zuc256EncryptCtx.java index 979529b..1cd7179 100644 --- a/Project/Src/com/cscn/Zuc256EncryptCtx.java +++ b/Project/Src/com/cscn/Zuc256EncryptCtx.java @@ -1,6 +1,7 @@ package com.cscn; import javacard.framework.JCSystem; +import javacard.framework.Util; import static com.cscn.Zuc256Core.zuc256GenerateKeystream; import static com.cscn.Zuc256Core.zuc256GenerateKeyword; @@ -56,7 +57,9 @@ public final class Zuc256EncryptCtx { // int copy = Math.min(inlen, need); short copy = (short)((inlen < need) ? inlen : need); - System.arraycopy(in, 0, this.buf, this.buflen, copy); + // 替代 System.arraycopy(in, 0, this.buf, this.buflen, copy); + Util.arrayCopyNonAtomic(in, (short)0, this.buf, this.buflen, copy); + this.buflen += copy; // 调整输入指针和长度 @@ -152,7 +155,9 @@ public final class Zuc256EncryptCtx { // 缓存剩余不足4字节的数据 if (inlen > 0) { - System.arraycopy(in, 0, this.buf, 0, inlen); + // 等价于 System.arraycopy(in, 0, this.buf, 0, inlen); + Util.arrayCopyNonAtomic(in, (short)0, this.buf, (short)0, inlen); + this.buflen = inlen; } } @@ -186,6 +191,7 @@ public final class Zuc256EncryptCtx { } this.buflen = 0; + // Arrays.fill(this.state.LFSR, 0); // LFSR 全部清零(高低位数组各 16 个元素) for (short i = 0; i < 16; i++) { @@ -193,6 +199,7 @@ public final class Zuc256EncryptCtx { this.state.LFSR_hi[i] = 0; } + // this.state.R1 = 0; // this.state.R2 = 0; // R1、R2 清零 diff --git a/Project/Src/com/cscn/Zuc256Tables.java b/Project/Src/com/cscn/Zuc256Tables.java index 7d56ba9..1049152 100644 --- a/Project/Src/com/cscn/Zuc256Tables.java +++ b/Project/Src/com/cscn/Zuc256Tables.java @@ -49,13 +49,50 @@ public final class Zuc256Tables { 0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2 }; - /** - * 常量数组 D(16bit short二维数组适配) - */ - 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} - }; +// /** +// * 常量数组 D(16bit short二维数组适配) +// */ +// 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} +// }; + public static final short D_COLS = 16; + /** + * 常量数组 D(16bit short二维数组适配) + */ + public static final short[] ZUC256_D_FLAT = new short[] { + // row 0 + 0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30, + + // row 1 + 0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30, + + // row 2 + 0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30, + + // row 3 + 0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30 + }; + + + /** 读取 D[row][col],返回无符号值 0..255 */ + public static short getD(short row, short col) { + // idx = row * 16 + col + short idx = (short)(row * D_COLS + col); + return (short)(ZUC256_D_FLAT[idx] & 0xFF); + } + + /** 取一行 (返回一段16个short) */ + public static void getDRow(short row, short[] out, short outOff) { + short base = (short)(row * D_COLS); + for (short i = 0; i < D_COLS; i++) { + out[(short)(outOff + i)] = ZUC256_D_FLAT[(short)(base + i)]; + } + } } \ No newline at end of file diff --git a/Project/Src/com/cscn/Zuc256Util.java b/Project/Src/com/cscn/Zuc256Util.java index a6cd657..d44149d 100644 --- a/Project/Src/com/cscn/Zuc256Util.java +++ b/Project/Src/com/cscn/Zuc256Util.java @@ -18,8 +18,8 @@ public final class Zuc256Util { // } /** 辅助方法:从字节数组取出 32 位整数,存放到 short[2] (lo, hi) */ public static void getU32(byte[] p, short offset, short[] out32 /* len=2 */) { - out32[0] = (short) (((p[offset + 2] & 0xFF) << 8) | (p[offset + 3] & 0xFF)); //低16位 - out32[1] = (short) (((p[offset] & 0xFF) << 8) | (p[offset + 1] & 0xFF)); //高16位 + out32[0] = (short) (((p[(short)(offset + 2)] & 0xFF) << 8) | (p[(short)(offset + 3)] & 0xFF)); //低16位 + out32[1] = (short) (((p[offset] & 0xFF) << 8) | (p[(short)(offset + 1)] & 0xFF)); //高16位 } @@ -34,11 +34,11 @@ public final class Zuc256Util { public static void putU32(byte[] p, short offset, short vlo, short vhi) { // 写高16位 p[offset] = (byte) ((vhi >> 8) & 0xFF); - p[offset + 1] = (byte) (vhi & 0xFF); + p[(short)(offset + 1)] = (byte) (vhi & 0xFF); // 写低16位 - p[offset + 2] = (byte) ((vlo >> 8) & 0xFF); - p[offset + 3] = (byte) (vlo & 0xFF); + p[(short)(offset + 2)] = (byte) ((vlo >> 8) & 0xFF); + p[(short)(offset + 3)] = (byte) (vlo & 0xFF); } @@ -101,7 +101,7 @@ public final class Zuc256Util { bits[i] = (short)((a_lo >>> i) & 1); } for (short i = 0; i < 15; i++) { - bits[16 + i] = (short)((a_hi >>> i) & 1); + bits[(short)(16 + i)] = (short)((a_hi >>> i) & 1); } // 旋转 @@ -118,7 +118,7 @@ public final class Zuc256Util { } short hi = 0; for (short i = 0; i < 15; i++) { - hi = (short)(hi | (resBits[16 + i] << i)); + hi = (short)(hi | (resBits[(short)(16 + i)] << i)); } out[0] = lo; @@ -310,7 +310,7 @@ public final class Zuc256Util { // 处理剩余8字节 byte[] src = new byte[8]; for (short i = 0; i < 8; i++) { - src[i] = (byte) (input25Byte[17 + i] & 0x3F); + src[i] = (byte) (input25Byte[(short)(17 + i)] & 0x3F); } output23Byte[17] = (byte) ((src[0] << 2) | (src[1] >>> 4)); diff --git a/src/com/zuc/zuc256/Zuc256MacCtx.java b/src/com/zuc/zuc256/Zuc256MacCtx.java deleted file mode 100644 index 47dc2ec..0000000 --- a/src/com/zuc/zuc256/Zuc256MacCtx.java +++ /dev/null @@ -1,34 +0,0 @@ -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; - } -} diff --git a/src/com/zuc/zuc256/Zuc256State.java b/src/com/zuc/zuc256/Zuc256State.java deleted file mode 100644 index 822fc4d..0000000 --- a/src/com/zuc/zuc256/Zuc256State.java +++ /dev/null @@ -1,22 +0,0 @@ -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; - } -}