输入80E3,可执行算法正确性检验,验证通过,对len=38Bytes明文加密结果符合预期、解密结果符合输入;
输入80E2,可写入密钥到flash,若算法类型、key id, key版本一致,就写入,已满就报错,无记录就写入新记录; 输入80CA,可执行伪位置加密,原封不动将输入的data返回回来。
This commit is contained in:
@@ -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; // 无返回数据
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -134,34 +134,19 @@ public final class Zuc256Util {
|
||||
// }
|
||||
/** 32位循环左移: (a<<<k) */
|
||||
public static void rot32(short a_lo, short a_hi, short k, short[] out /*len==2*/) {
|
||||
k = (short)(k & 31); // 限制 0..31
|
||||
if (k == 0) {
|
||||
out[0] = a_lo;
|
||||
out[1] = a_hi;
|
||||
return;
|
||||
k = (short)(k & 31); // 0..31
|
||||
short lo = a_lo, hi = a_hi, nw_hi, nw_lo;
|
||||
while (k > 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;
|
||||
|
||||
Reference in New Issue
Block a user