框架初始化

This commit is contained in:
zcy
2025-09-03 15:40:10 +08:00
parent 176b0aa6f6
commit 1b4c192180
12 changed files with 408 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
package com.zuc.zuc256;
/**
* ZUC-256 核心:状态初始化、密钥字生成、密钥流生成。
* 仅保留对外 API 与内部步骤骨架,细节待填。
*/
public final class Zuc256Core {
private Zuc256Core() {}
/** 初始化状态Key + IV */
public static void init(Zuc256State st, byte[] key32, byte[] ivN) {
// TODO: 1) 按表和 key/iv 装载 LFSR 初值
// TODO: 2) 置 R1/R2
// TODO: 3) 预运行若干轮
throw new UnsupportedOperationException("TODO: init");
}
/** 生成单个 32bit 密钥字 */
public static int generateKeyword(Zuc256State st) {
// TODO: 1) BitReconstruction
// TODO: 2) 非线性变换 F -> W
// TODO: 3) LFSR 下一步with/without carry 按标准)
// TODO: 4) 输出 W ⊕ X(??)(依实现)
throw new UnsupportedOperationException("TODO: generateKeyword");
}
/** 生成 nwords 个 32bit 密钥字到 ks[] */
public static void generateKeystream(Zuc256State st, int nwords, int[] ks) {
for (int i = 0; i < nwords; i++) {
ks[i] = generateKeyword(st); // TODO: 替换为高效批量实现(可选)
}
}
}

View File

@@ -0,0 +1,51 @@
package com.zuc.zuc256;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
/**
* 演示主函数:保持与你的单文件示例一致的调用路径。
* 说明:核心函数仍未实现,运行会抛出 UnsupportedOperationException。
*/
public final class Zuc256Demo {
public static void main(String[] args) {
// 1. 明文
byte[] plaintext = "ZUC256对称加解密测试:1234567890".getBytes(StandardCharsets.UTF_8);
System.out.println("明文: " + new String(plaintext, StandardCharsets.UTF_8));
Zuc256Util.printHex("明文(十六进制)", plaintext, plaintext.length);
// 2. 密钥(32字节ASCII)
byte[] key = "0123456789abcdef0123456789abcdef".getBytes(StandardCharsets.US_ASCII);
Zuc256Util.printHex("密钥", key, key.length);
// 3. 初始向量(25字节ASCII) -> 提取 23 字节
byte[] inputIv25Byte = "0123456789abcdefg01234567".getBytes(StandardCharsets.US_ASCII);
byte[] iv = new byte[23];
// TODO: 按你的 C 规则提取
// Zuc256Util.extractIv(inputIv25Byte, iv);
Zuc256Util.printHex("提取后的IV(占位)", iv, iv.length);
// 4. 加密/解密缓冲区
byte[] ciphertext = new byte[plaintext.length];
byte[] decrypted = new byte[plaintext.length];
// 5. 加密
Zuc256EncryptCtx enc = new Zuc256EncryptCtx();
enc.init(key, iv);
enc.update(plaintext, 0, plaintext.length, ciphertext, 0);
Zuc256Util.printHex("密文", ciphertext, ciphertext.length);
// 6. 解密(重新初始化)
Zuc256EncryptCtx dec = new Zuc256EncryptCtx();
dec.init(key, iv);
dec.update(ciphertext, 0, ciphertext.length, decrypted, 0);
Zuc256Util.printHex("解密后", decrypted, decrypted.length);
System.out.println("解密文本: " + new String(decrypted, StandardCharsets.UTF_8));
// 7. 验证
System.out.println(Arrays.equals(plaintext, decrypted)
? "=== 测试成功: 解密结果与明文一致 ==="
: "=== 测试失败: 解密结果与明文不一致 ===");
}
}

View File

@@ -0,0 +1,42 @@
package com.zuc.zuc256;
import java.util.Arrays;
/**
* 分段加/解密上下文(流密码:同一流程)。
* 注意JavaCard 上尽量复用缓冲,避免额外分配。
*/
public final class Zuc256EncryptCtx {
private final Zuc256State st = new Zuc256State();
// 流水寄存(可选):缓存当前 32bit 密钥字与已用字节数
private int keystreamWord;
private int usedBytes;
public void init(byte[] key32, byte[] iv) {
Arrays.fill(st.lfsr, 0);
st.r1 = st.r2 = 0;
usedBytes = 4; // 令首次进入 update() 时强制拉取新字
Zuc256Core.init(st, key32, iv);
}
/**
* 分段处理in/out 可同缓冲(就地异或)。
*/
public void update(byte[] in, int inOff, int inLen, byte[] out, int outOff) {
// TODO: 逐字节与 keystreamWord 异或4 字节耗尽后生成下一字
throw new UnsupportedOperationException("TODO: update");
}
public void finish(byte[] out, int outOff) {
// 流密码无填充;如需 MAC/尾处理,放到 MAC 上下文中
}
/** 一次性处理(便利方法) */
public static void crypt(byte[] key32, byte[] iv, byte[] in, int inOff, int inLen, byte[] out, int outOff) {
Zuc256EncryptCtx ctx = new Zuc256EncryptCtx();
ctx.init(key32, iv);
ctx.update(in, inOff, inLen, out, outOff);
ctx.finish(out, outOff + inLen);
}
}

View File

@@ -0,0 +1,29 @@
package com.zuc.zuc256;
/**
* MAC 上下文可选ZUC-256-EIA3 类似流程)
* 这里只给出骨架,按你的 C 代码把细节补齐。
*/
public final class Zuc256MacCtx {
private final Zuc256State st = new Zuc256State();
private int macBits; // 32/64/128...
private int acc; // 累加器/寄存器,视实现调整
public void init(byte[] key32, byte[] iv, int macBits) {
this.macBits = macBits;
this.acc = 0;
Zuc256Core.init(st, key32, iv);
// TODO: 若 MAC 需特殊 IV/派生,按 C 版本处理
throw new UnsupportedOperationException("TODO: MAC init details");
}
public void update(byte[] data, int off, int len) {
// TODO: 消耗比特/字节流并累积 acc
throw new UnsupportedOperationException("TODO: MAC update");
}
public void finish(byte[] tag, int tagOff) {
// TODO: 输出 macBits 位标签到 tag[]
throw new UnsupportedOperationException("TODO: MAC finish");
}
}

View File

@@ -0,0 +1,16 @@
package com.zuc.zuc256;
/**
* ZUC 内部状态LFSR(16x31bit) + R1/R2。
* Java 中用 int 保存(仅低 31 位有效)。
*/
public final class Zuc256State {
public final int[] lfsr = new int[16]; // 线性反馈移位寄存器31bit/项
public int r1; // 32bit working register
public int r2; // 32bit working register
public void reset() {
for (int i = 0; i < lfsr.length; i++) lfsr[i] = 0;
r1 = 0; r2 = 0;
}
}

View File

@@ -0,0 +1,28 @@
package com.zuc.zuc256;
/**
* 常量表S0/S1 与 ZUC256_D。
* 注意JavaCard 目标环境建议将表定义为 static final 数组,按 int/short 存放。
* TODO: 将 C 版本中的表逐项拷入。
*/
public final class Zuc256Tables {
private Zuc256Tables() {}
// S盒S0, S1
public static final int[] S0 = {
// TODO: 填入 256 项
};
public static final int[] S1 = {
// TODO: 填入 256 项
};
/**
* 常量数组 D按标准/实现定义)
* 说明:根据你的 C 代码布局选择 int[?][?] 或 int[] 线性展开。
*/
public static final int[][] ZUC256_D = {
// TODO: 填入
};
}

View File

@@ -0,0 +1,104 @@
package com.zuc.zuc256;
import java.util.Locale;
/**
* 辅助工具:装载/存储、位运算、线性变换、打印等。
* 默认使用大端序(与大多数参考实现一致),如需小端请统一替换。
*/
public final class Zuc256Util {
private Zuc256Util() {}
// === Byte <-> U32 ===
/** 从 p[offset..offset+3] 读 32bit大端 */
public static int getU32(byte[] p, int offset) {
// TODO: 如需小端,改为反序装载
int v = ((p[offset] & 0xFF) << 24)
| ((p[offset + 1] & 0xFF) << 16)
| ((p[offset + 2] & 0xFF) << 8)
| (p[offset + 3] & 0xFF);
return v;
}
/** 将 v 写入 p[offset..offset+3](大端) */
public static void putU32(byte[] p, int offset, int v) {
// TODO: 如需小端,改为反序存储
p[offset] = (byte)((v >>> 24) & 0xFF);
p[offset + 1] = (byte)((v >>> 16) & 0xFF);
p[offset + 2] = (byte)((v >>> 8) & 0xFF);
p[offset + 3] = (byte)(v & 0xFF);
}
// === 31/32 位运算 ===
/** 31 位加法(丢弃第 32 位),仅保留低 31 位 */
public static int add31(int a, int b) {
// TODO: 对齐 C 的具体实现细节(是否有进位回注)
return (a + b) & 0x7FFFFFFF;
}
/** 31 位循环左移(仅低 31 位参与) */
public static int rot31(int a, int k) {
int x = a & 0x7FFFFFFF;
k %= 31;
return ((x << k) | (x >>> (31 - k))) & 0x7FFFFFFF;
}
/** 32 位循环左移 */
public static int rot32(int a, int k) {
int s = k & 31;
return (a << s) | (a >>> (32 - s));
}
// === 线性变换(与标准一致) ===
public static int L1(int x) {
// TODO: 填入 L1 具体移位与异或
throw new UnsupportedOperationException("TODO: L1");
}
public static int L2(int x) {
// TODO: 填入 L2 具体移位与异或
throw new UnsupportedOperationException("TODO: L2");
}
// === 组装整数 ===
/** makeU31: 由 4 个 8bit 组为 31bit 值(按标准约定截断/掩码) */
public static int makeU31(int a, int b, int c, int d) {
// TODO: 对齐 C 代码的拼接与掩码方式
int v = ((a & 0xFF) << 23)
| ((b & 0xFF) << 15)
| ((c & 0xFF) << 7)
| ((d & 0x7F));
return v & 0x7FFFFFFF;
}
/** makeU32: 由 4 个 8bit 组为 32bit 值(大端) */
public static int makeU32(int a, int b, int c, int d) {
return ((a & 0xFF) << 24)
| ((b & 0xFF) << 16)
| ((c & 0xFF) << 8)
| (d & 0xFF);
}
// === IV 处理与打印 ===
/** 将 25 字节输入提取/压缩为 23 字节 IV按你的 C 规则) */
public static void extractIv(byte[] input25Byte, byte[] output23Byte) {
// TODO: 按 C 逻辑实现
throw new UnsupportedOperationException("TODO: extractIv");
}
/** 打印十六进制(调试用,生产/JC 环境可移除) */
public static void printHex(String label, byte[] data, int len) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
sb.append(String.format(Locale.ROOT, "%02X", data[i]));
if (i + 1 < len) sb.append(i % 16 == 15 ? "\n" : " ");
}
System.out.println(label + ":\n" + sb);
}
}