From 5456e990e6f027e997a3e6c2c52aac1dd1a63b97 Mon Sep 17 00:00:00 2001 From: zcy Date: Mon, 8 Sep 2025 23:46:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BE=93=E5=85=A580E3=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E7=AE=97=E6=B3=95=E6=AD=A3=E7=A1=AE=E6=80=A7?= =?UTF-8?q?=E6=A3=80=E9=AA=8C=EF=BC=8C=E9=AA=8C=E8=AF=81=E9=80=9A=E8=BF=87?= =?UTF-8?q?=EF=BC=8C=E5=AF=B9len=3D38Bytes=E6=98=8E=E6=96=87=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=E7=BB=93=E6=9E=9C=E7=AC=A6=E5=90=88=E9=A2=84=E6=9C=9F?= =?UTF-8?q?=E3=80=81=E8=A7=A3=E5=AF=86=E7=BB=93=E6=9E=9C=E7=AC=A6=E5=90=88?= =?UTF-8?q?=E8=BE=93=E5=85=A5;=20=E8=BE=93=E5=85=A580E2=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E5=86=99=E5=85=A5=E5=AF=86=E9=92=A5=E5=88=B0flash=EF=BC=8C?= =?UTF-8?q?=E8=8B=A5=E7=AE=97=E6=B3=95=E7=B1=BB=E5=9E=8B=E3=80=81key=20id,?= =?UTF-8?q?=20key=E7=89=88=E6=9C=AC=E4=B8=80=E8=87=B4=EF=BC=8C=E5=B0=B1?= =?UTF-8?q?=E5=86=99=E5=85=A5=EF=BC=8C=E5=B7=B2=E6=BB=A1=E5=B0=B1=E6=8A=A5?= =?UTF-8?q?=E9=94=99=EF=BC=8C=E6=97=A0=E8=AE=B0=E5=BD=95=E5=B0=B1=E5=86=99?= =?UTF-8?q?=E5=85=A5=E6=96=B0=E8=AE=B0=E5=BD=95;=20=E8=BE=93=E5=85=A580CA?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E6=89=A7=E8=A1=8C=E4=BC=AA=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E5=8A=A0=E5=AF=86=EF=BC=8C=E5=8E=9F=E5=B0=81=E4=B8=8D=E5=8A=A8?= =?UTF-8?q?=E5=B0=86=E8=BE=93=E5=85=A5=E7=9A=84data=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=9B=9E=E6=9D=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Project/Src/com/cscn/Method.java | 112 ++++++++++++++++- Project/Src/com/cscn/XwSecurity.java | 79 +++++++----- Project/Src/com/cscn/Zuc256Core.java | 20 +-- Project/Src/com/cscn/Zuc256EncryptCtx.java | 11 +- Project/Src/com/cscn/Zuc256State.java | 2 +- Project/Src/com/cscn/Zuc256Util.java | 134 +++++++++------------ 6 files changed, 231 insertions(+), 127 deletions(-) diff --git a/Project/Src/com/cscn/Method.java b/Project/Src/com/cscn/Method.java index 1a2cb4a..a428852 100644 --- a/Project/Src/com/cscn/Method.java +++ b/Project/Src/com/cscn/Method.java @@ -58,6 +58,7 @@ public final class Method { ctx = new Zuc256EncryptCtx(); // 仅创建一次 } + public void processData(APDU apdu) { short L = (short) INPUT.length; byte[] buf1; // Enc(Input) @@ -92,8 +93,113 @@ public final class Method { apdu.sendBytes((short)0, outLen); } - // 本任务不需要更新Key,这里留空 - public void updateKey(APDU apdu) { - ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); + /** + * fake数据生成函数 + * 输入: stmsi[6], data[5] + * 输出: fakedata[5] + */ + private void makeFakeData(byte[] stmsi, byte[] data, byte[] fakedata) { + // 示例:逐字节异或 stmsi 前5字节 + for (short i = 0; i < (short)5; i++) { + fakedata[i] = (byte)(data[i]); + } } + + /** + * APDU处理函数 + */ + public short processDataFake(byte[] buffer, short off, short len, byte[] key_store) { + // 至少要有 12 个字节:1+1+1+6+5 + if (len < (short)12) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + + // === 解析入参 === + byte inType = buffer[(short)(off + 0)]; // 类型 A1 + byte inLen = buffer[(short)(off + 1)]; // 长度 0x0C + byte secParam = buffer[(short)(off + 2)]; // 安全参数 + + // STMSI + byte[] stmsi = JCSystem.makeTransientByteArray((short)6, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); + Util.arrayCopyNonAtomic(buffer, (short)(off + 3), stmsi, (short)0, (short)6); + + // data + byte[] data = JCSystem.makeTransientByteArray((short)5, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); + Util.arrayCopyNonAtomic(buffer, (short)(off + 9), data, (short)0, (short)5); + + // === 生成 fakedata === + byte[] fakedata = JCSystem.makeTransientByteArray((short)5, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); + makeFakeData(stmsi, data, fakedata); + + // === 出参组装 === + buffer[(short)(off + 0)] = (byte)0xA1; // 类型 + buffer[(short)(off + 1)] = (byte)0x06; // 长度 + buffer[(short)(off + 2)] = (byte)0x01; // 密钥选取 + Util.arrayCopyNonAtomic(fakedata, (short)0, buffer, (short)(off + 3), (short)5); + + return (short)8; // 出参总长度 + } + + + + public short updateKey(byte[] buffer, short off, short len, byte[] key_store) { + final short SLOT_SIZE = 40; // 每个槽固定40字节 + final short HDR_LEN = 4; // 报文头长度: [0]=keyLenField, [1]=alg, [2]=keyId, [3]=ver + + // === 解析头 === + byte keyLenField = buffer[(short)(off + 0)]; // 包含头部+密钥的总长度 + byte alg = buffer[(short)(off + 1)]; + byte keyId = buffer[(short)(off + 2)]; + byte ver = buffer[(short)(off + 3)]; + + // 计算实际密钥长度 + short realKeyLen = (short)(keyLenField - (byte)3); // 长度字段 = key长度 + 3字节头 + if (realKeyLen <= 0) { + ISOException.throwIt(ISO7816.SW_DATA_INVALID); // key长度不合法 + } + + // 检查APDU长度和key长度是否匹配 + if (len != (short)(HDR_LEN + realKeyLen)) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + if (len > SLOT_SIZE) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + + // === 将原有 key_store 拷贝到 RAM,避免直接覆盖 EEPROM (可选) === + byte[] key_buf = JCSystem.makeTransientByteArray((short)80, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); + Util.arrayCopyNonAtomic(key_store, (short)0, key_buf, (short)0, (short)key_store.length); + + // === 遍历槽,找到匹配的 (alg, keyId, ver),否则找空槽 === + short slots = (short)(key_store.length / SLOT_SIZE); + short target = -1; + for (short i = 0; i < slots; i++) { + short base = (short)(i * SLOT_SIZE); + byte algOld = key_store[(short)(base + 1)]; + byte keyIdOld = key_store[(short)(base + 2)]; + byte verOld = key_store[(short)(base + 3)]; + + if (algOld == alg && keyId == keyIdOld && ver == verOld) { + target = i; // 找到已存在的,覆盖它 + break; + } + if (key_store[base] == (byte)0x00 && target == -1) { + target = i; // 找到第一个空槽 + } + } + + if (target == -1) { + ISOException.throwIt(ISO7816.SW_FILE_FULL); // 没有空位 + } + + // === 覆盖写入本次APDU的头+密钥数据 === + short base = (short)(target * SLOT_SIZE); + // 先清空槽 + Util.arrayFillNonAtomic(key_store, base, SLOT_SIZE, (byte)0x00); + // 再写入APDU传入的头+数据 (len 个字节) + Util.arrayCopyNonAtomic(buffer, off, key_store, base, len); + + return 0; // 无返回数据 + } + } diff --git a/Project/Src/com/cscn/XwSecurity.java b/Project/Src/com/cscn/XwSecurity.java index e7fca65..2b801b5 100644 --- a/Project/Src/com/cscn/XwSecurity.java +++ b/Project/Src/com/cscn/XwSecurity.java @@ -1,6 +1,3 @@ -/** - * - */ package com.cscn; import javacard.framework.APDU; @@ -16,20 +13,25 @@ import org.globalplatform.SecureChannel; */ public class XwSecurity extends Applet { - public static final byte INS_PROCESS_DATA = (byte)0xCA; + public static final byte INS_PROCESS_DATA = (byte)0xE3; - public static final byte INS_STORE_DATA = (byte)0xE2; + public static final byte INS_LOCATION_ENCRYPT = (byte)0xCA; - public static final byte INS_INITIAL_UPDATE = (byte)0x50; + public static final byte INS_STORE_KEY = (byte)0xE2; + +// public static final byte INS_INITIAL_UPDATE = (byte)0x50; +// +// public static final byte INS_EXTERNAL_AUTH = (byte)0x82; - public static final byte INS_EXTERNAL_AUTH = (byte)0x82; - private Method method; - + + byte[] key_store_byte; + public XwSecurity(byte[] bArray, short bOffset, byte bLength) { // TODO Auto-generated constructor stub method = new Method(); - + key_store_byte = new byte[80]; + register(bArray, (short)(bOffset + 1), bArray[bOffset]); } @@ -50,33 +52,44 @@ public class XwSecurity extends Applet { if(method == null) { return; } - + byte[] buf = apdu.getBuffer(); + short off = ISO7816.OFFSET_CDATA; + short len = apdu.setIncomingAndReceive(); + switch (buf[ISO7816.OFFSET_INS]) { - case INS_INITIAL_UPDATE: - SecureChannel sc = GPSystem.getSecureChannel(); - sc.processSecurity(apdu); - break; - - case INS_EXTERNAL_AUTH: - sc = GPSystem.getSecureChannel(); - sc.processSecurity(apdu); - break; - - case INS_PROCESS_DATA: - method.processData(apdu); - break; - - case INS_STORE_DATA: - method.updateKey(apdu); - break; - - default: - // good practice: If you don't know the INStruction, say so: - ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); +// case INS_INITIAL_UPDATE: +// SecureChannel sc = GPSystem.getSecureChannel(); +// sc.processSecurity(apdu); +// break; +// +// case INS_EXTERNAL_AUTH: +// sc = GPSystem.getSecureChannel(); +// sc.processSecurity(apdu); +// break; + + + case INS_PROCESS_DATA: + method.processData(apdu); + break; + + + case INS_LOCATION_ENCRYPT: + len = method.processDataFake(buf, off, len, key_store_byte); + apdu.setOutgoingAndSend(off, len); + break; + + case INS_STORE_KEY: + len = method.updateKey(buf, off, len, key_store_byte); + apdu.setOutgoingAndSend(off, len); + break; + + default: + // good practice: If you don't know the INStruction, say so: + ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } - + } } \ No newline at end of file diff --git a/Project/Src/com/cscn/Zuc256Core.java b/Project/Src/com/cscn/Zuc256Core.java index 6570b3c..f18a085 100644 --- a/Project/Src/com/cscn/Zuc256Core.java +++ b/Project/Src/com/cscn/Zuc256Core.java @@ -67,20 +67,20 @@ public class Zuc256Core { // BitReconstruction4 short c15 = (short)((LFSR_lo[15] & (short)0x8000) >>> 15); // 左移产生的进位 - X0[1] = (short)(((LFSR_hi[15] & (short)0x7FFF) << 1) | c15); // hi + X0[1] = (short)(((LFSR_hi[15] & (short)0x7FFF) << 1) | (short)(c15 & 0x0001)); // hi X0[0] = LFSR_lo[14]; // lo // X1 = ((L11 & 0xFFFF) << 16) | (L9 >>> 15) X1[1] = LFSR_lo[11]; - X1[0] = (short)(((LFSR_lo[9] & (short)0x8000) >>> 15) | (LFSR_hi[9] << 1)); + X1[0] = (short)((((LFSR_lo[9] & (short)0x8000) >>> 15) & 0X0001) | (LFSR_hi[9] << 1)); // X2 = ((L7 & 0xFFFF) << 16) | (L5 >>> 15) X2[1] = LFSR_lo[7]; - X2[0] = (short)(((LFSR_lo[5] & (short)0x8000) >>> 15) | (LFSR_hi[5] << 1)); + X2[0] = (short)((((LFSR_lo[5] & (short)0x8000) >>> 15) & 0X0001) | (LFSR_hi[5] << 1)); // X3 = ((L2 & 0xFFFF) << 16) | (L0 >>> 15) X3[1] = LFSR_lo[2]; - X3[0] = (short)(((LFSR_lo[0] & (short)0x8000) >>> 15) | (LFSR_hi[0] << 1)); + X3[0] = (short)((((LFSR_lo[0] & (short)0x8000) >>> 15) & 0X0001) | (LFSR_hi[0] << 1)); @@ -383,12 +383,12 @@ public class Zuc256Core { // X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15); // X1 = ((L11 & 0xFFFF)<<16) | (L9>>>15) X1[1] = state.LFSR_lo[11]; - X1[0] = (short)(((state.LFSR_lo[9] & (short)0x8000) >>> 15) | (state.LFSR_hi[9] << 1)); + X1[0] = (short)((((state.LFSR_lo[9] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[9] << 1)); // X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15); // X2 = ((L7 & 0xFFFF)<<16) | (L5>>>15) X2[1] = state.LFSR_lo[7]; - X2[0] = (short)(((state.LFSR_lo[5] & (short)0x8000) >>> 15) | (state.LFSR_hi[5] << 1)); + X2[0] = (short)((((state.LFSR_lo[5] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[5] << 1)); @@ -481,17 +481,17 @@ public class Zuc256Core { // BitReconstruction2 // X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15); X1[1] = state.LFSR_lo[11]; - X1[0] = (short)(((state.LFSR_lo[9] & (short)0x8000) >>> 15) | (state.LFSR_hi[9] << 1)); + X1[0] = (short)((((state.LFSR_lo[9] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[9] << 1)); // X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15); X2[1] = state.LFSR_lo[7]; - X2[0] = (short)(((state.LFSR_lo[5] & (short)0x8000) >>> 15) | (state.LFSR_hi[5] << 1)); + X2[0] = (short)((((state.LFSR_lo[5] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[5] << 1)); // F_(X1, X2) // W1 = R1 + X1; - add32(state.R1_lo, state.R1_hi, X1[0], X1[1], W1); // W1 = R1 + X1 + add32(R1[0], R1[1], X1[0], X1[1], W1); // W1 = R1 + X1 // W2 = R2 ^ X2; - xor32(state.R2_lo, state.R2_hi, X2[0], X2[1], W2); // W2 = R2 ^ X2 + xor32(R2[0], R2[1], X2[0], X2[1], W2); // W2 = R2 ^ X2 // U = L1((W1 << 16) | (W2 >>> 16)); // U = L1((W1<<16)|(W2>>>16)) → lo=W2_hi, hi=W1_lo diff --git a/Project/Src/com/cscn/Zuc256EncryptCtx.java b/Project/Src/com/cscn/Zuc256EncryptCtx.java index 1cd7179..b844d7d 100644 --- a/Project/Src/com/cscn/Zuc256EncryptCtx.java +++ b/Project/Src/com/cscn/Zuc256EncryptCtx.java @@ -89,7 +89,7 @@ public final class Zuc256EncryptCtx { short[] res = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_DESELECT); xor32(plain[0], plain[1], ks[0], ks[1], res); // 写回 out 的前4字节 - putU32(out, outPos, res[0], res[1]); + putU32(out, (short)0, res[0], res[1]); this.buflen = 0; // Arrays.fill(this.buf, (byte) 0); @@ -156,7 +156,7 @@ public final class Zuc256EncryptCtx { // 缓存剩余不足4字节的数据 if (inlen > 0) { // 等价于 System.arraycopy(in, 0, this.buf, 0, inlen); - Util.arrayCopyNonAtomic(in, (short)0, this.buf, (short)0, inlen); + Util.arrayCopyNonAtomic(in, (short)inPos, this.buf, (short)0, inlen); this.buflen = inlen; } @@ -179,14 +179,17 @@ public final class Zuc256EncryptCtx { putU32(keystreamBytes, (short)0, ks[0], ks[1]); // 逐字节异或 + short outOffset = (short)(out.length - this.buflen); for (short i = 0; i < this.buflen; i++) { - out[i] = (byte) (this.buf[i] ^ keystreamBytes[i]); + out[(short)(i+outOffset)] = (byte) (this.buf[i] ^ keystreamBytes[i]); } } + + // 清理上下文 // Arrays.fill(this.buf, (byte) 0); - for (short i = 0; i < (short)this.buf.length; i++) { + for(short i=0; i<4; i++) { this.buf[i] = (byte)0; } diff --git a/Project/Src/com/cscn/Zuc256State.java b/Project/Src/com/cscn/Zuc256State.java index 8e65c5f..360aee8 100644 --- a/Project/Src/com/cscn/Zuc256State.java +++ b/Project/Src/com/cscn/Zuc256State.java @@ -3,7 +3,7 @@ package com.cscn; /** * ZUC状态类(JavaCard版,int 拆为 hi/lo short) */ -public final class Zuc256State { +public class Zuc256State { // LFSR: 原 int[16] -> hi/lo 各 16 public short[] LFSR_hi = new short[16]; public short[] LFSR_lo = new short[16]; diff --git a/Project/Src/com/cscn/Zuc256Util.java b/Project/Src/com/cscn/Zuc256Util.java index a50aa65..06ac703 100644 --- a/Project/Src/com/cscn/Zuc256Util.java +++ b/Project/Src/com/cscn/Zuc256Util.java @@ -134,34 +134,19 @@ public final class Zuc256Util { // } /** 32位循环左移: (a<< 0) { + // 先做 1 位循环左移 + // 注意:short 在 >>> 时会先提升为 int,所以下面都再用 &1 取最低位,避免符号扩展影响 + nw_hi = (short)((hi << 1) | ((lo >>> 15) & 1)); + nw_lo = (short)((lo << 1) | ((hi >>> 15) & 1)); + hi = nw_hi; + lo = nw_lo; + k--; } - - short lo, hi; - - if (k < 16) { - // 左移 k - lo = (short)(a_lo << k); - hi = (short)(a_hi << k); - - // 把溢出部分拼接 - lo |= (short)((a_hi & (short)0xFFFF) >>> (16 - k)); - hi |= (short)((a_lo & (short)0xFFFF) >>> (16 - k)); - } else { - short s = (short)(k - 16); - lo = (short)(a_hi << s); - hi = (short)(a_lo << s); - - lo |= (short)((a_lo & (short)0xFFFF) >>> (16 - s)); - hi |= (short)((a_hi & (short)0xFFFF) >>> (16 - s)); - } - - out[0] = lo; - out[1] = hi; + out[0] = lo; // 低16位 + out[1] = hi; // 高16位 } @@ -221,7 +206,7 @@ public final class Zuc256Util { * 输出: out[0]=lo, out[1]=hi */ public static void L2(short x_lo, short x_hi, short[] out /*len==2*/) { - short[] t = new short[2]; + short[] t = new short[2];//todo to ram short[] acc = new short[2]; // acc = x @@ -358,35 +343,39 @@ public final class Zuc256Util { } /** - * 32位加法 + 返回进位 + * 32位加法 + 返回进位(只用 short) * 输入: (a_hi:a_lo) + (b_hi:b_lo) * 输出: out[0]=lo, out[1]=hi - * 返回: 进位 (0或1) + * 返回: 最终进位(0/1) */ static short add32_with_carry(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /* len=2 */) { - // 低 16 位相加 - short lo = (short)(a_lo + b_lo); - // 判断低 16 位是否溢出 - short carry_lo = (short)(((a_lo & (short)0xFFFF) + (b_lo & (short)0xFFFF)) >>> 16); + // ---- 低16位:分两段8位相加 ---- + short s0 = (short)((a_lo & (short)0x00FF) + (b_lo & (short)0x00FF)); // 0..510 + short c0 = (short)(s0 >>> 8); // 0/1 + short s1 = (short)(((a_lo >>> 8) & (short)0x00FF) + + ((b_lo >>> 8) & (short)0x00FF) + + c0); // 0..511 + short c1 = (short)(s1 >>> 8); // 0/1 + short lo = (short)((s1 << 8) | (s0 & (short)0x00FF)); - // 高 16 位相加 + 低位进位 - short hi_tmp = (short)(a_hi + b_hi); - short carry_hi1 = (short)(((a_hi & (short)0xFFFF) + (b_hi & (short)0xFFFF)) >>> 16); + // ---- 高16位:再分两段8位相加,并加上 c1 ---- + short s2 = (short)((a_hi & (short)0x00FF) + (b_hi & (short)0x00FF) + c1); + short c2 = (short)(s2 >>> 8); // 0/1 + short s3 = (short)(((a_hi >>> 8) & (short)0x00FF) + + ((b_hi >>> 8) & (short)0x00FF) + + c2); // 0..511 + short c3 = (short)(s3 >>> 8); // 最终进位 0/1 + short hi = (short)((s3 << 8) | (s2 & (short)0x00FF)); - short hi = (short)(hi_tmp + carry_lo); - short carry_hi2 = (short)(((hi_tmp & (short)0xFFFF) + (carry_lo & (short)0xFFFF)) >>> 16); - - // 输出结果 out[0] = lo; out[1] = hi; - - // 最终进位 = 高位相加本身的进位 + 高位再加低位进位的进位 - return (short)((carry_hi1 + carry_hi2) & 0x1); + return (short)(c3 & 1); } + /** * 64位加法: a4 + b4 -> a4 * 输入输出: short[4],低到高 (a[0]=lo16, a[1]=hi16, a[2]=lo16 of high dword, a[3]=hi16 of high dword) @@ -400,7 +389,7 @@ public final class Zuc256Util { a[1] = tmp[1]; // 高 32 位 + carry - add32((short)(a[2] + (carry & (short)0xFFFF)), a[3], b[2], b[3], tmp); + add32((short)(a[2] + (short)(carry & (short)0x0001)), a[3], b[2], b[3], tmp); a[2] = tmp[0]; a[3] = tmp[1]; } @@ -418,38 +407,32 @@ public final class Zuc256Util { * 结果放到64位数 a (a[0]=最低16位 ... a[3]=最高16位)。 */ static void create_64b_from_32b(short[] a/*len=4*/, short[] b/*len=2*/, short k) { - // 先清零 - a[0] = 0; a[1] = 0; a[2] = 0; a[3] = 0; + short a0 = b[0], a1 = b[1], a2 = 0, a3 = 0; - if (k == 0) { - a[0] = b[0]; - a[1] = b[1]; - return; + if (k >= 16) { + a3 = a2; // 0 + a2 = a1; // 原 hi16 + a1 = a0; // 原 lo16 + a0 = 0; + k = (short)(k - 16); } - if (k < 16) { - // lo << k - a[0] = (short)(b[0] << k); - // hi << k, 以及 lo >>> (16-k) 进位 - a[1] = (short)((b[1] << k) | ((b[0] & (short)0xFFFF) >>> (16 - k))); - // hi >>> (16-k) 残留进到 a[2] - a[2] = (short)((b[1] & (short)0xFFFF) >>> (16 - k)); - return; + while (k > 0) { + short c0 = (short)((a0 >>> 15) & 1); + short c1 = (short)((a1 >>> 15) & 1); + short c2 = (short)((a2 >>> 15) & 1); + + a3 = (short)((a3 << 1) | c2); + a2 = (short)((a2 << 1) | c1); + a1 = (short)((a1 << 1) | c0); + a0 = (short)(a0 << 1); + k--; } - if (k == 16) { - a[1] = b[0]; - a[2] = b[1]; - return; - } - - // 16 < k < 32 - short kk = (short)(k - 16); - a[1] = (short)(b[0] << kk); - a[2] = (short)((b[1] << kk) | ((b[0] & (short)0xFFFF) >>> (16 - kk))); - a[3] = (short)((b[1] & (short)0xFFFF) >>> (16 - kk)); + a[0] = a0; a[1] = a1; a[2] = a2; a[3] = a3; } + /** * (A & 0x7FFFFFFF),结果放在 out[4],只保留低32位并清掉最高bit。 */ @@ -480,10 +463,9 @@ public final class Zuc256Util { short c1 = (short)((out[1] & (short)0xFFFF) >>> 15); short c2 = (short)((out[2] & (short)0xFFFF) >>> 15); - out[0] = (short)(((out[0] & (short)0xFFFF) >>> 15) | (out[1] << 1)); - out[1] = (short)(((out[1] & (short)0xFFFF) >>> 15) | (out[2] << 1)); - out[2] = (short)(((out[2] & (short)0xFFFF) >>> 15) | (out[3] << 1)); - out[3] = (short)((out[3] & (short)0xFFFF) >>> 15); + out[0] = (short)((c0 & 0x0001) | (out[1] << 1)); + out[1] = (short)((c1 & 0x0001) | (out[2] << 1)); + out[2] = (short)(c2 & 0x0001); } /** @@ -493,8 +475,8 @@ public final class Zuc256Util { */ static void shr32u1(short lo, short hi, short[] out) { // >>>1:先处理低16位 - short newLo = (short)(((lo & (short)0xFFFF) >>> 1) | ((hi & 0x0001) << 15)); - short newHi = (short)((hi & (short)0xFFFF) >>> 1); + short newLo = (short)(((((lo & (short)0xFFFF) >>> 1) & (short)0x7FFF)) | ((hi & 0x0001) << 15)); + short newHi = (short)(((hi & (short)0xFFFF) >>> 1) & (short)0x7FFF); out[0] = newLo; out[1] = newHi;