框架初始化
This commit is contained in:
35
src/com/zuc/zuc256/Zuc256Core.java
Normal file
35
src/com/zuc/zuc256/Zuc256Core.java
Normal 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: 替换为高效批量实现(可选)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
51
src/com/zuc/zuc256/Zuc256Demo.java
Normal file
51
src/com/zuc/zuc256/Zuc256Demo.java
Normal 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)
|
||||
? "=== 测试成功: 解密结果与明文一致 ==="
|
||||
: "=== 测试失败: 解密结果与明文不一致 ===");
|
||||
}
|
||||
}
|
||||
42
src/com/zuc/zuc256/Zuc256EncryptCtx.java
Normal file
42
src/com/zuc/zuc256/Zuc256EncryptCtx.java
Normal 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);
|
||||
}
|
||||
}
|
||||
29
src/com/zuc/zuc256/Zuc256MacCtx.java
Normal file
29
src/com/zuc/zuc256/Zuc256MacCtx.java
Normal 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");
|
||||
}
|
||||
}
|
||||
16
src/com/zuc/zuc256/Zuc256State.java
Normal file
16
src/com/zuc/zuc256/Zuc256State.java
Normal 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;
|
||||
}
|
||||
}
|
||||
28
src/com/zuc/zuc256/Zuc256Tables.java
Normal file
28
src/com/zuc/zuc256/Zuc256Tables.java
Normal 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: 填入
|
||||
};
|
||||
}
|
||||
104
src/com/zuc/zuc256/Zuc256Util.java
Normal file
104
src/com/zuc/zuc256/Zuc256Util.java
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user