位置加密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 18840 additions and 2214 deletions
Showing only changes of commit b41fff9d09 - Show all commits

View File

@@ -6,6 +6,7 @@ import javacard.framework.ISOException;
import javacard.framework.JCSystem; import javacard.framework.JCSystem;
import javacard.framework.Util; import javacard.framework.Util;
/** /**
* 仅做一次“自检调用”: * 仅做一次“自检调用”:
* 1) ctx.init(KEY, IV); Enc(Input) == EncExpected ? * 1) ctx.init(KEY, IV); Enc(Input) == EncExpected ?
@@ -13,65 +14,66 @@ import javacard.framework.Util;
* Response: 2字节 [encMatch, dblEncRestored]1=真0=假 * Response: 2字节 [encMatch, dblEncRestored]1=真0=假
*/ */
public final class Method { public final class Method {
// ======= 已按你提供的数据填充 =======
// ======= 请用你的向量替换下面占位内容 =======
// Key: 32字节 // Key: 32字节
private static final byte[] KEY32 = new byte[] { private static final byte[] KEY32 = new byte[] {
// TODO: 替换成你的32字节Key (byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,(byte)0x37,
(byte)0x00,(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07, (byte)0x38,(byte)0x39,(byte)0x61,(byte)0x62,(byte)0x63,(byte)0x64,(byte)0x65,(byte)0x66,
(byte)0x08,(byte)0x09,(byte)0x0A,(byte)0x0B,(byte)0x0C,(byte)0x0D,(byte)0x0E,(byte)0x0F, (byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,(byte)0x37,
(byte)0x10,(byte)0x11,(byte)0x12,(byte)0x13,(byte)0x14,(byte)0x15,(byte)0x16,(byte)0x17, (byte)0x38,(byte)0x39,(byte)0x61,(byte)0x62,(byte)0x63,(byte)0x64,(byte)0x65,(byte)0x66
(byte)0x18,(byte)0x19,(byte)0x1A,(byte)0x1B,(byte)0x1C,(byte)0x1D,(byte)0x1E,(byte)0x1F
}; };
// IV: 25字节ZUC-256 // IV: 你提供的是23字节如需25字节请补齐两字节
private static final byte[] IV25 = new byte[] { private static final byte[] IV25 = new byte[] {
// TODO: 替换成你的25字节IV (byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,(byte)0x37,
(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5,(byte)0xA6,(byte)0xA7, (byte)0x38,(byte)0x39,(byte)0x61,(byte)0x62,(byte)0x63,(byte)0x64,(byte)0x65,(byte)0x66,
(byte)0xA8,(byte)0xA9,(byte)0xAA,(byte)0xAB,(byte)0xAC,(byte)0xAD,(byte)0xAE,(byte)0xAF, (byte)0x67,(byte)0xC3,(byte)0x1C,(byte)0xB3,(byte)0xD3,(byte)0x5D,(byte)0xB7
(byte)0xB0,(byte)0xB1,(byte)0xB2,(byte)0xB3,(byte)0xB4,(byte)0xB5,(byte)0xB6,(byte)0xB7,
(byte)0xB8
}; };
// Input: 建议长度为 4 的倍数,便于不走 finish 的残字节路径 // Input: 明文38字节
private static final byte[] INPUT = new byte[] { private static final byte[] INPUT = new byte[] {
// TODO: 替换成你的明文示例32字节 (byte)0x5A,(byte)0x55,(byte)0x43,(byte)0x32,(byte)0x35,(byte)0x36,(byte)0xE5,(byte)0xAF,
(byte)0x11,(byte)0x22,(byte)0x33,(byte)0x44,(byte)0x55,(byte)0x66,(byte)0x77,(byte)0x88, (byte)0xB9,(byte)0xE7,(byte)0xA7,(byte)0xB0,(byte)0xE5,(byte)0x8A,(byte)0xA0,(byte)0xE8,
(byte)0x99,(byte)0xAA,(byte)0xBB,(byte)0xCC,(byte)0xDD,(byte)0xEE,(byte)0xFF,(byte)0x00, (byte)0xA7,(byte)0xA3,(byte)0xE5,(byte)0xAF,(byte)0x86,(byte)0xE6,(byte)0xB5,(byte)0x8B,
(byte)0x10,(byte)0x20,(byte)0x30,(byte)0x40,(byte)0x50,(byte)0x60,(byte)0x70,(byte)0x80, (byte)0xE8,(byte)0xAF,(byte)0x95,(byte)0x3A,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,
(byte)0x90,(byte)0xA0,(byte)0xB0,(byte)0xC0,(byte)0xD0,(byte)0xE0,(byte)0xF0,(byte)0x00 (byte)0x35,(byte)0x36,(byte)0x37,(byte)0x38,(byte)0x39,(byte)0x30
}; };
// EncResult: 期望密文(与上面的 Input 配套 // EncResult: 期望密文(38字节
private static final byte[] ENC_EXPECTED = new byte[] { private static final byte[] ENC_EXPECTED = new byte[] {
// TODO: 替换成你“已知正确”的密文(示例随便填;不改会导致第一项校验=0 (byte)0x6C,(byte)0xEE,(byte)0x3C,(byte)0xFA,(byte)0xDE,(byte)0xBB,(byte)0xCB,(byte)0xE5,
(byte)0x21,(byte)0x32,(byte)0x43,(byte)0x54,(byte)0x65,(byte)0x76,(byte)0x87,(byte)0x98, (byte)0x33,(byte)0x51,(byte)0x07,(byte)0x07,(byte)0x90,(byte)0x25,(byte)0x93,(byte)0x27,
(byte)0xA9,(byte)0xBA,(byte)0xCB,(byte)0xDC,(byte)0xED,(byte)0xFE,(byte)0x0F,(byte)0x1E, (byte)0x94,(byte)0xF5,(byte)0x18,(byte)0x70,(byte)0xEF,(byte)0x71,(byte)0x72,(byte)0x7D,
(byte)0x2D,(byte)0x3C,(byte)0x4B,(byte)0x5A,(byte)0x69,(byte)0x78,(byte)0x87,(byte)0x96, (byte)0xBA,(byte)0x8D,(byte)0xBF,(byte)0x4F,(byte)0x61,(byte)0xC9,(byte)0xA8,(byte)0xE9,
(byte)0xA5,(byte)0xB4,(byte)0xC3,(byte)0xD2,(byte)0xE1,(byte)0xF0,(byte)0x0F,(byte)0x00 (byte)0xFF,(byte)0x19,(byte)0xF9,(byte)0xF9,(byte)0xE2,(byte)0xD2
}; };
// ====================================== // ======================================
// 运行时缓冲放RAM避免写EEPROM // 运行时缓冲放RAM避免写EEPROM
private final byte[] buf1; // Enc(Input)
private final byte[] buf2; // Enc(Enc(Input)) -> 应为 Input
private final Zuc256EncryptCtx ctx; private final Zuc256EncryptCtx ctx;
public Method() { 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(); // 仅创建一次 ctx = new Zuc256EncryptCtx(); // 仅创建一次
} }
public void processData(APDU apdu) { public void processData(APDU apdu) {
short L = (short) INPUT.length;
byte[] buf1; // Enc(Input)
byte[] buf2; // Enc(Enc(Input)) -> 应为 Input
buf1 = JCSystem.makeTransientByteArray(L, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
buf2 = JCSystem.makeTransientByteArray(L, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
byte[] apduBuf = apdu.getBuffer(); byte[] apduBuf = apdu.getBuffer();
// 第一次Enc(Input) // 第一次Enc(Input)
ctx.init(KEY32, IV25); ctx.init(KEY32, IV25);
Zuc256State tmpState = ctx.state;
ctx.update(INPUT, (short) INPUT.length, buf1); ctx.update(INPUT, (short) INPUT.length, buf1);
ctx.finish(buf1); // 若 Input 长度为 4 的倍数则通常无副作用,留着更稳妥 ctx.finish(buf1); // 若 Input 长度为 4 的倍数则通常无副作用,留着更稳妥
Zuc256State tmpState2 = ctx.state;
boolean encMatch = (Util.arrayCompare(buf1, (short)0, ENC_EXPECTED, (short)0, (short)INPUT.length) == 0); boolean encMatch = (Util.arrayCompare(buf1, (short)0, ENC_EXPECTED, (short)0, (short)INPUT.length) == 0);
// 第二次Enc(Enc(Input)) 应还原 Input // 第二次Enc(Enc(Input)) 应还原 Input

View File

@@ -371,12 +371,13 @@ public class Zuc256Core {
state.LFSR_lo[15] = tmp[0]; state.LFSR_hi[15] = tmp[1]; state.LFSR_lo[15] = tmp[0]; state.LFSR_hi[15] = tmp[1];
short c15_2 = 0;
for (short i = 0; i < 32; i++) { for (short i = 0; i < 32; i++) {
// BitReconstruction3 // BitReconstruction3
// X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF); // X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
// X0 = ((L15 & 0x7FFF8000)<<1) | (L14 & 0xFFFF) // X0 = ((L15 & 0x7FFF8000)<<1) | (L14 & 0xFFFF)
short c15 = (short)((state.LFSR_lo[15] & (short)0x8000) >>> 15); c15_2 = (short)((state.LFSR_lo[15] & (short)0x8000) >>> 15);
X0[1] = (short)(((state.LFSR_hi[15] & (short)0x7FFF) << 1) | c15); X0[1] = (short)(((state.LFSR_hi[15] & (short)0x7FFF) << 1) | (short)(c15_2 & 0x0001));
X0[0] = state.LFSR_lo[14]; X0[0] = state.LFSR_lo[14];
// X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15); // X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
@@ -459,7 +460,7 @@ public class Zuc256Core {
// v = add31(v, W >>> 1); // v = add31(v, W >>> 1);
shr32u1(W[0], W[1], T2); // T2[0]=lo, T2[1]=hi无符号>>>1 shr32u1(W[0], W[1], T2); // T2[0]=lo, T2[1]=hi无符号>>>1
T2[1] = (short)(T2[1] & 0x7FFF); // 只保留31位 T2[1] = (short)(T2[1] & (short)0xFFFF); // 只保留31位
add31(V[0], V[1], T2[0], T2[1], V); add31(V[0], V[1], T2[0], T2[1], V);
// System.arraycopy(state.LFSR, 1, state.LFSR, 0, 15) // System.arraycopy(state.LFSR, 1, state.LFSR, 0, 15)

View File

@@ -57,8 +57,10 @@ public final class Zuc256Util {
public static void add31(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /* len==2 */) { public static void add31(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /* len==2 */) {
// ---- 低16位相加 ---- // ---- 低16位相加 ----
short lo = (short)(a_lo + b_lo); short lo = (short)(a_lo + b_lo);
short carry = (short)(((lo & 0xFFFF) < (a_lo & 0xFFFF)) ? 1 : 0); short carry = (short)(
( ( (short)( (a_lo & b_lo) | ((a_lo | b_lo) & (short)~lo) ) ) & (short)0x8000 ) != 0
? 1 : 0
);
// ---- 高15位相加 + 进位 ---- // ---- 高15位相加 + 进位 ----
short hi_raw = (short)((short)((a_hi & 0x7FFF) + (b_hi & 0x7FFF)) + carry); short hi_raw = (short)((short)((a_hi & 0x7FFF) + (b_hi & 0x7FFF)) + carry);
@@ -147,15 +149,15 @@ public final class Zuc256Util {
hi = (short)(a_hi << k); hi = (short)(a_hi << k);
// 把溢出部分拼接 // 把溢出部分拼接
lo |= (short)((a_hi & 0xFFFF) >>> (16 - k)); lo |= (short)((a_hi & (short)0xFFFF) >>> (16 - k));
hi |= (short)((a_lo & 0xFFFF) >>> (16 - k)); hi |= (short)((a_lo & (short)0xFFFF) >>> (16 - k));
} else { } else {
short s = (short)(k - 16); short s = (short)(k - 16);
lo = (short)(a_hi << s); lo = (short)(a_hi << s);
hi = (short)(a_lo << s); hi = (short)(a_lo << s);
lo |= (short)((a_lo & 0xFFFF) >>> (16 - s)); lo |= (short)((a_lo & (short)0xFFFF) >>> (16 - s));
hi |= (short)((a_hi & 0xFFFF) >>> (16 - s)); hi |= (short)((a_hi & (short)0xFFFF) >>> (16 - s));
} }
out[0] = lo; out[0] = lo;
@@ -271,7 +273,7 @@ public final class Zuc256Util {
out[0] = (short)((b2 << 8) | b3); out[0] = (short)((b2 << 8) | b3);
// hi = 高15位丢弃 bit31 // hi = 高15位丢弃 bit31
out[1] = (short)(((b0 & 0x7F) << 8) | b1); out[1] = (short)((b0 << 7) | b1);
} }
@@ -367,14 +369,14 @@ public final class Zuc256Util {
// 低 16 位相加 // 低 16 位相加
short lo = (short)(a_lo + b_lo); short lo = (short)(a_lo + b_lo);
// 判断低 16 位是否溢出 // 判断低 16 位是否溢出
short carry_lo = (short)(((a_lo & 0xFFFF) + (b_lo & 0xFFFF)) >>> 16); short carry_lo = (short)(((a_lo & (short)0xFFFF) + (b_lo & (short)0xFFFF)) >>> 16);
// 高 16 位相加 + 低位进位 // 高 16 位相加 + 低位进位
short hi_tmp = (short)(a_hi + b_hi); short hi_tmp = (short)(a_hi + b_hi);
short carry_hi1 = (short)(((a_hi & 0xFFFF) + (b_hi & 0xFFFF)) >>> 16); short carry_hi1 = (short)(((a_hi & (short)0xFFFF) + (b_hi & (short)0xFFFF)) >>> 16);
short hi = (short)(hi_tmp + carry_lo); short hi = (short)(hi_tmp + carry_lo);
short carry_hi2 = (short)(((hi_tmp & 0xFFFF) + (carry_lo & 0xFFFF)) >>> 16); short carry_hi2 = (short)(((hi_tmp & (short)0xFFFF) + (carry_lo & (short)0xFFFF)) >>> 16);
// 输出结果 // 输出结果
out[0] = lo; out[0] = lo;
@@ -398,7 +400,7 @@ public final class Zuc256Util {
a[1] = tmp[1]; a[1] = tmp[1];
// 高 32 位 + carry // 高 32 位 + carry
add32((short)(a[2] + (carry & 0xFFFF)), a[3], b[2], b[3], tmp); add32((short)(a[2] + (carry & (short)0xFFFF)), a[3], b[2], b[3], tmp);
a[2] = tmp[0]; a[2] = tmp[0];
a[3] = tmp[1]; a[3] = tmp[1];
} }
@@ -429,9 +431,9 @@ public final class Zuc256Util {
// lo << k // lo << k
a[0] = (short)(b[0] << k); a[0] = (short)(b[0] << k);
// hi << k, 以及 lo >>> (16-k) 进位 // hi << k, 以及 lo >>> (16-k) 进位
a[1] = (short)((b[1] << k) | ((b[0] & 0xFFFF) >>> (16 - k))); a[1] = (short)((b[1] << k) | ((b[0] & (short)0xFFFF) >>> (16 - k)));
// hi >>> (16-k) 残留进到 a[2] // hi >>> (16-k) 残留进到 a[2]
a[2] = (short)((b[1] & 0xFFFF) >>> (16 - k)); a[2] = (short)((b[1] & (short)0xFFFF) >>> (16 - k));
return; return;
} }
@@ -444,8 +446,8 @@ public final class Zuc256Util {
// 16 < k < 32 // 16 < k < 32
short kk = (short)(k - 16); short kk = (short)(k - 16);
a[1] = (short)(b[0] << kk); a[1] = (short)(b[0] << kk);
a[2] = (short)((b[1] << kk) | ((b[0] & 0xFFFF) >>> (16 - kk))); a[2] = (short)((b[1] << kk) | ((b[0] & (short)0xFFFF) >>> (16 - kk)));
a[3] = (short)((b[1] & 0xFFFF) >>> (16 - kk)); a[3] = (short)((b[1] & (short)0xFFFF) >>> (16 - kk));
} }
/** /**
@@ -474,14 +476,14 @@ public final class Zuc256Util {
out[3] = 0; // 高位补0 out[3] = 0; // 高位补0
// 再右移 15 位 // 再右移 15 位
short c0 = (short)((out[0] & 0xFFFF) >>> 15); // out[0] 最后一位变进位 short c0 = (short)((out[0] & (short)0xFFFF) >>> 15); // out[0] 最后一位变进位
short c1 = (short)((out[1] & 0xFFFF) >>> 15); short c1 = (short)((out[1] & (short)0xFFFF) >>> 15);
short c2 = (short)((out[2] & 0xFFFF) >>> 15); short c2 = (short)((out[2] & (short)0xFFFF) >>> 15);
out[0] = (short)(((out[0] & 0xFFFF) >>> 15) | (out[1] << 1)); out[0] = (short)(((out[0] & (short)0xFFFF) >>> 15) | (out[1] << 1));
out[1] = (short)(((out[1] & 0xFFFF) >>> 15) | (out[2] << 1)); out[1] = (short)(((out[1] & (short)0xFFFF) >>> 15) | (out[2] << 1));
out[2] = (short)(((out[2] & 0xFFFF) >>> 15) | (out[3] << 1)); out[2] = (short)(((out[2] & (short)0xFFFF) >>> 15) | (out[3] << 1));
out[3] = (short)((out[3] & 0xFFFF) >>> 15); out[3] = (short)((out[3] & (short)0xFFFF) >>> 15);
} }
/** /**
@@ -491,8 +493,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 & 0xFFFF) >>> 1) | ((hi & 0x0001) << 15)); short newLo = (short)(((lo & (short)0xFFFF) >>> 1) | ((hi & 0x0001) << 15));
short newHi = (short)((hi & 0xFFFF) >>> 1); short newHi = (short)((hi & (short)0xFFFF) >>> 1);
out[0] = newLo; out[0] = newLo;
out[1] = newHi; out[1] = newHi;