位置加密applet基本实现,目录下包含c java参考代码、打包工具、说明文档、 #2

Merged
zcy merged 20 commits from zcy_dev_cap into main 2025-09-09 02:39:35 +00:00
744 changed files with 18944 additions and 2214 deletions
Showing only changes of commit 5456e990e6 - Show all commits

View File

@@ -58,6 +58,7 @@ public final class Method {
ctx = new Zuc256EncryptCtx(); // 仅创建一次 ctx = new Zuc256EncryptCtx(); // 仅创建一次
} }
public void processData(APDU apdu) { public void processData(APDU apdu) {
short L = (short) INPUT.length; short L = (short) INPUT.length;
byte[] buf1; // Enc(Input) byte[] buf1; // Enc(Input)
@@ -92,8 +93,113 @@ public final class Method {
apdu.sendBytes((short)0, outLen); apdu.sendBytes((short)0, outLen);
} }
// 本任务不需要更新Key这里留空 /**
public void updateKey(APDU apdu) { * fake数据生成函数
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); * 输入: 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; // 无返回数据
}
} }

View File

@@ -1,6 +1,3 @@
/**
*
*/
package com.cscn; package com.cscn;
import javacard.framework.APDU; import javacard.framework.APDU;
@@ -16,19 +13,24 @@ import org.globalplatform.SecureChannel;
*/ */
public class XwSecurity extends Applet { 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_EXTERNAL_AUTH = (byte)0x82; // public static final byte INS_INITIAL_UPDATE = (byte)0x50;
//
// public static final byte INS_EXTERNAL_AUTH = (byte)0x82;
private Method method; private Method method;
byte[] key_store_byte;
public XwSecurity(byte[] bArray, short bOffset, byte bLength) { public XwSecurity(byte[] bArray, short bOffset, byte bLength) {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
method = new Method(); method = new Method();
key_store_byte = new byte[80];
register(bArray, (short)(bOffset + 1), bArray[bOffset]); register(bArray, (short)(bOffset + 1), bArray[bOffset]);
} }
@@ -52,29 +54,40 @@ public class XwSecurity extends Applet {
} }
byte[] buf = apdu.getBuffer(); byte[] buf = apdu.getBuffer();
short off = ISO7816.OFFSET_CDATA;
short len = apdu.setIncomingAndReceive();
switch (buf[ISO7816.OFFSET_INS]) switch (buf[ISO7816.OFFSET_INS])
{ {
case INS_INITIAL_UPDATE: // case INS_INITIAL_UPDATE:
SecureChannel sc = GPSystem.getSecureChannel(); // SecureChannel sc = GPSystem.getSecureChannel();
sc.processSecurity(apdu); // sc.processSecurity(apdu);
break; // break;
//
// case INS_EXTERNAL_AUTH:
// sc = GPSystem.getSecureChannel();
// sc.processSecurity(apdu);
// break;
case INS_EXTERNAL_AUTH:
sc = GPSystem.getSecureChannel();
sc.processSecurity(apdu);
break;
case INS_PROCESS_DATA: case INS_PROCESS_DATA:
method.processData(apdu); method.processData(apdu);
break; break;
case INS_STORE_DATA:
method.updateKey(apdu);
break;
default: case INS_LOCATION_ENCRYPT:
// good practice: If you don't know the INStruction, say so: len = method.processDataFake(buf, off, len, key_store_byte);
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); 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);
} }

View File

@@ -67,20 +67,20 @@ public class Zuc256Core {
// BitReconstruction4 // BitReconstruction4
short c15 = (short)((LFSR_lo[15] & (short)0x8000) >>> 15); // 左移产生的进位 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 X0[0] = LFSR_lo[14]; // lo
// X1 = ((L11 & 0xFFFF) << 16) | (L9 >>> 15) // X1 = ((L11 & 0xFFFF) << 16) | (L9 >>> 15)
X1[1] = LFSR_lo[11]; 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 = ((L7 & 0xFFFF) << 16) | (L5 >>> 15)
X2[1] = LFSR_lo[7]; 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 = ((L2 & 0xFFFF) << 16) | (L0 >>> 15)
X3[1] = LFSR_lo[2]; 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 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
// X1 = ((L11 & 0xFFFF)<<16) | (L9>>>15) // X1 = ((L11 & 0xFFFF)<<16) | (L9>>>15)
X1[1] = state.LFSR_lo[11]; 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 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
// X2 = ((L7 & 0xFFFF)<<16) | (L5>>>15) // X2 = ((L7 & 0xFFFF)<<16) | (L5>>>15)
X2[1] = state.LFSR_lo[7]; 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 // BitReconstruction2
// X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15); // X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
X1[1] = state.LFSR_lo[11]; 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 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
X2[1] = state.LFSR_lo[7]; 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) // F_(X1, X2)
// W1 = R1 + X1; // 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; // 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));
// U = L1((W1<<16)|(W2>>>16)) → lo=W2_hi, hi=W1_lo // U = L1((W1<<16)|(W2>>>16)) → lo=W2_hi, hi=W1_lo

View File

@@ -89,7 +89,7 @@ public final class Zuc256EncryptCtx {
short[] res = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_DESELECT); short[] res = JCSystem.makeTransientShortArray((short)2, JCSystem.CLEAR_ON_DESELECT);
xor32(plain[0], plain[1], ks[0], ks[1], res); xor32(plain[0], plain[1], ks[0], ks[1], res);
// 写回 out 的前4字节 // 写回 out 的前4字节
putU32(out, outPos, res[0], res[1]); putU32(out, (short)0, res[0], res[1]);
this.buflen = 0; this.buflen = 0;
// Arrays.fill(this.buf, (byte) 0); // Arrays.fill(this.buf, (byte) 0);
@@ -156,7 +156,7 @@ public final class Zuc256EncryptCtx {
// 缓存剩余不足4字节的数据 // 缓存剩余不足4字节的数据
if (inlen > 0) { 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); Util.arrayCopyNonAtomic(in, (short)inPos, this.buf, (short)0, inlen);
this.buflen = inlen; this.buflen = inlen;
} }
@@ -179,14 +179,17 @@ public final class Zuc256EncryptCtx {
putU32(keystreamBytes, (short)0, ks[0], ks[1]); putU32(keystreamBytes, (short)0, ks[0], ks[1]);
// 逐字节异或 // 逐字节异或
short outOffset = (short)(out.length - this.buflen);
for (short i = 0; i < this.buflen; i++) { 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); // 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; this.buf[i] = (byte)0;
} }

View File

@@ -3,7 +3,7 @@ package com.cscn;
/** /**
* ZUC状态类JavaCard版int 拆为 hi/lo short * ZUC状态类JavaCard版int 拆为 hi/lo short
*/ */
public final class Zuc256State { public class Zuc256State {
// LFSR: 原 int[16] -> hi/lo 各 16 // LFSR: 原 int[16] -> hi/lo 各 16
public short[] LFSR_hi = new short[16]; public short[] LFSR_hi = new short[16];
public short[] LFSR_lo = new short[16]; public short[] LFSR_lo = new short[16];

View File

@@ -134,34 +134,19 @@ public final class Zuc256Util {
// } // }
/** 32位循环左移: (a<<<k) */ /** 32位循环左移: (a<<<k) */
public static void rot32(short a_lo, short a_hi, short k, short[] out /*len==2*/) { public static void rot32(short a_lo, short a_hi, short k, short[] out /*len==2*/) {
k = (short)(k & 31); // 限制 0..31 k = (short)(k & 31); // 0..31
if (k == 0) { short lo = a_lo, hi = a_hi, nw_hi, nw_lo;
out[0] = a_lo; while (k > 0) {
out[1] = a_hi; // 先做 1 位循环左移
return; // 注意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--;
} }
out[0] = lo; // 低16位
short lo, hi; out[1] = hi; // 高16位
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;
} }
@@ -221,7 +206,7 @@ public final class Zuc256Util {
* 输出: out[0]=lo, out[1]=hi * 输出: out[0]=lo, out[1]=hi
*/ */
public static void L2(short x_lo, short x_hi, short[] out /*len==2*/) { 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]; short[] acc = new short[2];
// acc = x // acc = x
@@ -358,35 +343,39 @@ public final class Zuc256Util {
} }
/** /**
* 32位加法 + 返回进位 * 32位加法 + 返回进位(只用 short
* 输入: (a_hi:a_lo) + (b_hi:b_lo) * 输入: (a_hi:a_lo) + (b_hi:b_lo)
* 输出: out[0]=lo, out[1]=hi * 输出: out[0]=lo, out[1]=hi
* 返回: 进位 (01) * 返回: 最终进位(0/1)
*/ */
static short add32_with_carry(short a_lo, short a_hi, static short add32_with_carry(short a_lo, short a_hi,
short b_lo, short b_hi, short b_lo, short b_hi,
short[] out /* len=2 */) { short[] out /* len=2 */) {
// 低 16 位相加 // ---- 低16位分两段8位相加 ----
short lo = (short)(a_lo + b_lo); short s0 = (short)((a_lo & (short)0x00FF) + (b_lo & (short)0x00FF)); // 0..510
// 判断低 16 位是否溢出 short c0 = (short)(s0 >>> 8); // 0/1
short carry_lo = (short)(((a_lo & (short)0xFFFF) + (b_lo & (short)0xFFFF)) >>> 16); 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 位相加 + 低位进位 // ---- 高16位再分两段8位相加并加上 c1 ----
short hi_tmp = (short)(a_hi + b_hi); short s2 = (short)((a_hi & (short)0x00FF) + (b_hi & (short)0x00FF) + c1);
short carry_hi1 = (short)(((a_hi & (short)0xFFFF) + (b_hi & (short)0xFFFF)) >>> 16); 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[0] = lo;
out[1] = hi; out[1] = hi;
return (short)(c3 & 1);
// 最终进位 = 高位相加本身的进位 + 高位再加低位进位的进位
return (short)((carry_hi1 + carry_hi2) & 0x1);
} }
/** /**
* 64位加法: a4 + b4 -> a4 * 64位加法: a4 + b4 -> a4
* 输入输出: short[4],低到高 (a[0]=lo16, a[1]=hi16, a[2]=lo16 of high dword, a[3]=hi16 of high dword) * 输入输出: 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]; a[1] = tmp[1];
// 高 32 位 + carry // 高 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[2] = tmp[0];
a[3] = tmp[1]; a[3] = tmp[1];
} }
@@ -418,38 +407,32 @@ public final class Zuc256Util {
* 结果放到64位数 a (a[0]=最低16位 ... a[3]=最高16位)。 * 结果放到64位数 a (a[0]=最低16位 ... a[3]=最高16位)。
*/ */
static void create_64b_from_32b(short[] a/*len=4*/, short[] b/*len=2*/, short k) { static void create_64b_from_32b(short[] a/*len=4*/, short[] b/*len=2*/, short k) {
// 先清零 short a0 = b[0], a1 = b[1], a2 = 0, a3 = 0;
a[0] = 0; a[1] = 0; a[2] = 0; a[3] = 0;
if (k == 0) { if (k >= 16) {
a[0] = b[0]; a3 = a2; // 0
a[1] = b[1]; a2 = a1; // 原 hi16
return; a1 = a0; // 原 lo16
a0 = 0;
k = (short)(k - 16);
} }
if (k < 16) { while (k > 0) {
// lo << k short c0 = (short)((a0 >>> 15) & 1);
a[0] = (short)(b[0] << k); short c1 = (short)((a1 >>> 15) & 1);
// hi << k, 以及 lo >>> (16-k) 进位 short c2 = (short)((a2 >>> 15) & 1);
a[1] = (short)((b[1] << k) | ((b[0] & (short)0xFFFF) >>> (16 - k)));
// hi >>> (16-k) 残留进到 a[2] a3 = (short)((a3 << 1) | c2);
a[2] = (short)((b[1] & (short)0xFFFF) >>> (16 - k)); a2 = (short)((a2 << 1) | c1);
return; a1 = (short)((a1 << 1) | c0);
a0 = (short)(a0 << 1);
k--;
} }
if (k == 16) { a[0] = a0; a[1] = a1; a[2] = a2; a[3] = a3;
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 & 0x7FFFFFFF),结果放在 out[4]只保留低32位并清掉最高bit。 * (A & 0x7FFFFFFF),结果放在 out[4]只保留低32位并清掉最高bit。
*/ */
@@ -480,10 +463,9 @@ public final class Zuc256Util {
short c1 = (short)((out[1] & (short)0xFFFF) >>> 15); short c1 = (short)((out[1] & (short)0xFFFF) >>> 15);
short c2 = (short)((out[2] & (short)0xFFFF) >>> 15); short c2 = (short)((out[2] & (short)0xFFFF) >>> 15);
out[0] = (short)(((out[0] & (short)0xFFFF) >>> 15) | (out[1] << 1)); out[0] = (short)((c0 & 0x0001) | (out[1] << 1));
out[1] = (short)(((out[1] & (short)0xFFFF) >>> 15) | (out[2] << 1)); out[1] = (short)((c1 & 0x0001) | (out[2] << 1));
out[2] = (short)(((out[2] & (short)0xFFFF) >>> 15) | (out[3] << 1)); out[2] = (short)(c2 & 0x0001);
out[3] = (short)((out[3] & (short)0xFFFF) >>> 15);
} }
/** /**
@@ -493,8 +475,8 @@ public final class Zuc256Util {
*/ */
static void shr32u1(short lo, short hi, short[] out) { static void shr32u1(short lo, short hi, short[] out) {
// >>>1先处理低16位 // >>>1先处理低16位
short newLo = (short)(((lo & (short)0xFFFF) >>> 1) | ((hi & 0x0001) << 15)); short newLo = (short)(((((lo & (short)0xFFFF) >>> 1) & (short)0x7FFF)) | ((hi & 0x0001) << 15));
short newHi = (short)((hi & (short)0xFFFF) >>> 1); short newHi = (short)(((hi & (short)0xFFFF) >>> 1) & (short)0x7FFF);
out[0] = newLo; out[0] = newLo;
out[1] = newHi; out[1] = newHi;