Files
se-algo/Project/Src/com/cscn/Zuc256Util.java
2025-09-05 16:25:32 +08:00

333 lines
9.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.cscn;
import javacard.framework.Util;
/**
* 辅助工具:装载/存储、位运算、线性变换、打印等。
*/
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位
out32[1] = (short) (((p[offset] & 0xFF) << 8) | (p[offset + 1] & 0xFF)); //高16位
}
// /** 辅助方法将32位整数转换为字节数组 */
// public static void putU32(byte[] p, int offset, int v) {
// p[offset] = (byte) (v >> 24);
// p[offset + 1] = (byte) (v >> 16);
// 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位
p[offset] = (byte) ((vhi >> 8) & 0xFF);
p[offset + 1] = (byte) (vhi & 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位加法: (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 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;
}
// /** 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 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;
}
// /** 32位旋转 */
// public static int rot32(int a, int k) {
// return (a << k) | (a >>> (32 - k));
// }
/** 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;
}
short lo, hi;
if (k < 16) {
// 左移 k
lo = (short)(a_lo << k);
hi = (short)(a_hi << k);
// 把溢出部分拼接
lo |= (short)((a_hi & 0xFFFF) >>> (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;
}
// /**
// * 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字节
Util.arrayCopyNonAtomic(input25Byte, (short)0, output23Byte, (short)0, (short)17);
// 处理剩余8字节
byte[] src = new byte[8];
for (short i = 0; i < 8; i++) {
src[i] = (byte) (input25Byte[17 + i] & 0x3F);
}
output23Byte[17] = (byte) ((src[0] << 2) | (src[1] >>> 4));
output23Byte[18] = (byte) (((src[1] & 0x0F) << 4) | (src[2] >>> 2));
output23Byte[19] = (byte) (((src[2] & 0x03) << 6) | src[3]);
output23Byte[20] = (byte) ((src[4] << 2) | (src[5] >>> 4));
output23Byte[21] = (byte) (((src[5] & 0x0F) << 4) | (src[6] >>> 2));
output23Byte[22] = (byte) (((src[6] & 0x03) << 6) | src[7]);
}
/** 打印/*十六进制调试用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();
}*/
}