diff --git a/Project/Src/com/cscn/Zuc256Util.java b/Project/Src/com/cscn/Zuc256Util.java index f45201f..d57b598 100644 --- a/Project/Src/com/cscn/Zuc256Util.java +++ b/Project/Src/com/cscn/Zuc256Util.java @@ -1,5 +1,7 @@ package com.cscn; +import javacard.framework.Util; + /** * 辅助工具:装载/存储、位运算、线性变换、打印等。 */ @@ -7,6 +9,13 @@ public final class Zuc256Util { private Zuc256Util() {} +// /** 辅助方法:将字节数组转换为32位整数 */ +// public static int getU32(byte[] p, int offset) { +// return ((p[offset] & 0xFF) << 24) | +// ((p[offset + 1] & 0xFF) << 16) | +// ((p[offset + 2] & 0xFF) << 8) | +// (p[offset + 3] & 0xFF); +// } /** 辅助方法:从字节数组取出 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位 @@ -21,81 +30,286 @@ public final class Zuc256Util { // p[offset + 2] = (byte) (v >> 8); // p[offset + 3] = (byte) v; // } - /** 辅助方法:将32位整数(vlo=低16位, vhi=高16位)写入字节数组 */ public static void putU32(byte[] p, short offset, short vlo, short vhi) { // 写高16位 - putU16(p, offset, vhi); - // 写低16位 - putU16(p, (short)(offset + 2), vlo); - } + p[offset] = (byte) ((vhi >> 8) & 0xFF); + p[offset + 1] = (byte) (vhi & 0xFF); - /** 辅助方法:将16位整数(short)写入字节数组,高字节在前 */ - public static void putU16(byte[] p, short offset, short v) { - p[offset] = (byte) ((v >> 8) & 0xFF); - p[offset + 1] = (byte) (v & 0xFF); + // 写低16位 + p[offset + 2] = (byte) ((vlo >> 8) & 0xFF); + p[offset + 3] = (byte) (vlo & 0xFF); } // === 31/32 位运算 === - /** 31位加法 */ - public static int add31(int a, int b) { - long sum = (long)a + b; - return (int) ((sum & 0x7FFFFFFF) + (sum >> 31)); - } - - /** 31位旋转 */ - public static int rot31(int a, int k) { - return ((a << k) | (a >>> (31 - k))) & 0x7FFFFFFF; - } - - /** 32位旋转 */ - public static int rot32(int a, int k) { - return (a << k) | (a >>> (32 - k)); - } - - /** - * L1函数 +// /** 31位加法 */ +// public static int add31(int a, int b) { +// long sum = (long)a + b; +// return (int) ((sum & 0x7FFFFFFF) + (sum >> 31)); +// } + /** 31位加法: (a+b) mod (2^31 - 1) + * 输入: a_lo=低16位, a_hi=高15位 + * b_lo=低16位, b_hi=高15位 + * 输出: out[0]=lo, out[1]=hi */ - public static int L1(int x) { - return x ^ rot32(x, 2) ^ rot32(x, 10) ^ rot32(x, 18) ^ rot32(x, 24); + public static void add31(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /* len==2 */) { + // ---- 低16位相加 ---- + short lo = (short)(a_lo + b_lo); + short carry = (short)(((lo & 0xFFFF) < (a_lo & 0xFFFF)) ? 1 : 0); + + // ---- 高15位相加 + 进位 ---- + short hi_raw = (short)((short)((a_hi & 0x7FFF) + (b_hi & 0x7FFF)) + carry); + + // 提取第31位(hi_raw bit15) + short topbit = (short)((hi_raw >>> 15) & 1); + short hi = (short)(hi_raw & 0x7FFF); // 保留15位 + + // ---- 若第31位=1,再+1 ---- + if (topbit == 1) { + short lo2 = (short)(lo + 1); + short c2 = (short)((lo2 == 0) ? 1 : 0); // lo溢出时进位 + lo = lo2; + hi = (short)((hi + c2) & 0x7FFF); + } + + out[0] = lo; + out[1] = hi; } - /** - * L2函数 + +// /** 31位旋转 */ +// public static int rot31(int a, int k) { +// return ((a << k) | (a >>> (31 - k))) & 0x7FFFFFFF; +// } + /** 31位循环左移: (a <<< k) mod (2^31 -1) + * 输入: a_lo=低16位, a_hi=高15位 + * 输出: out[0]=lo, out[1]=hi */ - public static int L2(int x) { - return x ^ rot32(x, 8) ^ rot32(x, 14) ^ rot32(x, 22) ^ rot32(x, 30); + public static void rot31(short a_lo, short a_hi, short k, short[] out /* len==2 */) { + k = (short)(k % 31); // 限制在 0..30 + if (k == 0) { + out[0] = a_lo; + out[1] = (short)(a_hi & 0x7FFF); + return; + } + + // 拆成 31 位数组 [bit0..bit30] + short[] bits = new short[31]; + for (short i = 0; i < 16; i++) { + bits[i] = (short)((a_lo >>> i) & 1); + } + for (short i = 0; i < 15; i++) { + bits[16 + i] = (short)((a_hi >>> i) & 1); + } + + // 旋转 + short[] resBits = new short[31]; + for (short i = 0; i < 31; i++) { + short j = (short)((i + k) % 31); + resBits[j] = bits[i]; + } + + // 拼回 lo, hi + short lo = 0; + for (short i = 0; i < 16; i++) { + lo = (short)(lo | (resBits[i] << i)); + } + short hi = 0; + for (short i = 0; i < 15; i++) { + hi = (short)(hi | (resBits[16 + i] << i)); + } + + out[0] = lo; + out[1] = hi; } - /** 创建31位无符号整数 */ - public static int makeU31(int a, int b, int c, int d) { - return (((a & 0xFF) << 23) | - ((b & 0xFF) << 16) | - ((c & 0xFF) << 8) | - (d & 0xFF)) & 0x7FFFFFFF; + +// /** 32位旋转 */ +// public static int rot32(int a, int k) { +// return (a << k) | (a >>> (32 - k)); +// } + /** 32位循环左移: (a<<>> (16 - k)); + hi |= (short)((a_lo & 0xFFFF) >>> (16 - k)); + } else { + short s = (short)(k - 16); + lo = (short)(a_hi << s); + hi = (short)(a_lo << s); + + lo |= (short)((a_lo & 0xFFFF) >>> (16 - s)); + hi |= (short)((a_hi & 0xFFFF) >>> (16 - s)); + } + + out[0] = lo; + out[1] = hi; } - /** 创建32位无符号整数 */ - public static int makeU32(int a, int b, int c, int d) { - return ((a & 0xFF) << 24) | - ((b & 0xFF) << 16) | - ((c & 0xFF) << 8) | - (d & 0xFF); + +// /** +// * L1函数 +// */ +// public static int L1(int x) { +// return x ^ rot32(x, 2) ^ rot32(x, 10) ^ rot32(x, 18) ^ rot32(x, 24); +// } + /** + * L1函数: x ^ (x<<<2) ^ (x<<<10) ^ (x<<<18) ^ (x<<<24) + * 输入: x_lo, x_hi + * 输出: out[0]=lo, out[1]=hi + */ + public static void L1(short x_lo, short x_hi, short[] out /*len==2*/) { + short[] t = new short[2]; + short[] acc = new short[2]; + + // acc = x + acc[0] = x_lo; + acc[1] = x_hi; + + // acc ^= rot32(x, 2) + rot32(x_lo, x_hi, (short)2, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + // acc ^= rot32(x, 10) + rot32(x_lo, x_hi, (short)10, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + // acc ^= rot32(x, 18) + rot32(x_lo, x_hi, (short)18, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + // acc ^= rot32(x, 24) + rot32(x_lo, x_hi, (short)24, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + out[0] = acc[0]; + out[1] = acc[1]; } +// /** +// * L2函数 +// */ +// public static int L2(int x) { +// return x ^ rot32(x, 8) ^ rot32(x, 14) ^ rot32(x, 22) ^ rot32(x, 30); +// } + /** + * L2函数: x ^ (x<<<8) ^ (x<<<14) ^ (x<<<22) ^ (x<<<30) + * 输入: x_lo, x_hi + * 输出: 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[] acc = new short[2]; + + // acc = x + acc[0] = x_lo; + acc[1] = x_hi; + + // acc ^= rot32(x, 8) + rot32(x_lo, x_hi, (short)8, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + // acc ^= rot32(x, 14) + rot32(x_lo, x_hi, (short)14, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + // acc ^= rot32(x, 22) + rot32(x_lo, x_hi, (short)22, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + // acc ^= rot32(x, 30) + rot32(x_lo, x_hi, (short)30, t); + acc[0] ^= t[0]; + acc[1] ^= t[1]; + + out[0] = acc[0]; + out[1] = acc[1]; + } + + +// /** 创建31位无符号整数 */ +// public static int makeU31(int a, int b, int c, int d) { +// return (((a & 0xFF) << 23) | +// ((b & 0xFF) << 16) | +// ((c & 0xFF) << 8) | +// (d & 0xFF)) & 0x7FFFFFFF; +// } + /** 创建31位无符号整数,结果放到 out[0]=lo, out[1]=hi(15位) */ + public static void makeU31(short a, short b, short c, short d, short[] out /*len==2*/) { + // 四个字节 + short b0 = (short)(a & 0xFF); // 最高字节 + short b1 = (short)(b & 0xFF); + short b2 = (short)(c & 0xFF); + short b3 = (short)(d & 0xFF); // 最低字节 + + // 拼成 32 位: b0<<24 | b1<<16 | b2<<8 | b3 + // lo = 低16位 + out[0] = (short)((b2 << 8) | b3); + + // hi = 高15位(丢弃 bit31) + out[1] = (short)(((b0 & 0x7F) << 8) | b1); + } + + +// /** 创建32位无符号整数 */ +// public static int makeU32(int a, int b, int c, int d) { +// return ((a & 0xFF) << 24) | +// ((b & 0xFF) << 16) | +// ((c & 0xFF) << 8) | +// (d & 0xFF); +// } + /** 创建32位无符号整数,结果放到 out[0]=lo, out[1]=hi */ + public static void makeU32(short a, short b, short c, short d, short[] out /*len==2*/) { + // 四个字节 + short b0 = (short)(a & 0xFF); // 最高字节 + short b1 = (short)(b & 0xFF); + short b2 = (short)(c & 0xFF); + short b3 = (short)(d & 0xFF); // 最低字节 + + // lo = 低16位 + out[0] = (short)((b2 << 8) | b3); + + // hi = 高16位 + out[1] = (short)((b0 << 8) | b1); + } + + + /** 提取IV */ public static void extractIv(byte[] input25Byte, byte[] output23Byte) { if (input25Byte == null || output23Byte == null) return; // 复制前17字节 - System.arraycopy(input25Byte, 0, output23Byte, 0, 17); + Util.arrayCopyNonAtomic(input25Byte, (short)0, output23Byte, (short)0, (short)17); + // 处理剩余8字节 byte[] src = new byte[8]; - for (int i = 0; i < 8; i++) { + for (short i = 0; i < 8; i++) { src[i] = (byte) (input25Byte[17 + i] & 0x3F); } @@ -107,12 +321,12 @@ public final class Zuc256Util { output23Byte[22] = (byte) (((src[6] & 0x03) << 6) | src[7]); } - /** 打印十六进制(调试用,TODO 生产/JC 环境可移除) */ + /** 打印/*十六进制(调试用,TODO 生产/JC 环境可移除) *//* public static void printHex(String label, byte[] data, int len) { System.out.print(label + ": "); for (int i = 0; i < len; i++) { System.out.printf("%02x ", data[i] & 0xFF); } System.out.println(); - } + }*/ }