Files
se-algo/Project/Src/com/cscn/Zuc256Core.java
2025-09-05 15:15:33 +08:00

295 lines
10 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 static com.cscn.Zuc256Util.L1;
import static com.cscn.Zuc256Util.L2;
import static com.cscn.Zuc256Util.add31;
import static com.cscn.Zuc256Util.makeU31;
import static com.cscn.Zuc256Util.makeU32;
import static com.cscn.Zuc256Util.rot31;
/**
* ZUC-256 核心:状态初始化、密钥字生成、密钥流生成。
*/
public final class Zuc256Core {
private Zuc256Core() {}
/** 初始化状态Key + IV */
public static void initState(Zuc256State state, byte[] key32, byte[] iv) {
zuc256SetMacKey(state, key32, iv, 0);
}
/** 生成单个密钥字 */
public static int generateKeyword(Zuc256State state) {
int[] LFSR = state.LFSR;
int R1 = state.R1;
int R2 = state.R2;
int X0, X1, X2, X3;
int W1, W2, U, V;
int Z;
// BitReconstruction4
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
X3 = ((LFSR[2] & 0xFFFF) << 16) | (LFSR[0] >>> 15);
Z = X3 ^ ((X0 ^ R1) + R2);
// F_(X1, X2)
W1 = R1 + X1;
W2 = R2 ^ X2;
U = L1((W1 << 16) | (W2 >>> 16));
V = L2((W2 << 16) | (W1 >>> 16));
R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
Zuc256Tables.S1[(U >>> 16) & 0xFF],
Zuc256Tables.S0[(U >>> 8) & 0xFF],
Zuc256Tables.S1[U & 0xFF]);
R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
Zuc256Tables.S1[(V >>> 16) & 0xFF],
Zuc256Tables.S0[(V >>> 8) & 0xFF],
Zuc256Tables.S1[V & 0xFF]);
// LFSRWithWorkMode
long a = LFSR[0];
a += (long)LFSR[0] << 8;
a += (long)LFSR[4] << 20;
a += (long)LFSR[10] << 21;
a += (long)LFSR[13] << 17;
a += (long)LFSR[15] << 15;
a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
System.arraycopy(LFSR, 1, LFSR, 0, 15);
LFSR[15] = v;
state.R1 = R1;
state.R2 = R2;
return Z;
}
// 生成指定长度的密钥流
public static void zuc256GenerateKeystream(Zuc256State state, int nwords, int[] keystream) {
int[] LFSR = state.LFSR;
int R1 = state.R1;
int R2 = state.R2;
int X0, X1, X2, X3;
int W1, W2, U, V;
for (int i = 0; i < nwords; i++) {
// BitReconstruction4
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
X3 = ((LFSR[2] & 0xFFFF) << 16) | (LFSR[0] >>> 15);
keystream[i] = X3 ^ ((X0 ^ R1) + R2);
// F_(X1, X2)
W1 = R1 + X1;
W2 = R2 ^ X2;
U = L1((W1 << 16) | (W2 >>> 16));
V = L2((W2 << 16) | (W1 >>> 16));
// S盒查找
int T0 = Zuc256Tables.S0[(U >>> 24) & 0xFF] & 0xFF;
int T2 = Zuc256Tables.S0[(U >>> 8) & 0xFF] & 0xFF;
int T4 = Zuc256Tables.S0[(V >>> 24) & 0xFF] & 0xFF;
int T6 = Zuc256Tables.S0[(V >>> 8) & 0xFF] & 0xFF;
int T1 = Zuc256Tables.S1[(U >>> 16) & 0xFF] & 0xFF;
int T3 = Zuc256Tables.S1[U & 0xFF] & 0xFF;
int T5 = Zuc256Tables.S1[(V >>> 16) & 0xFF] & 0xFF;
int T7 = Zuc256Tables.S1[V & 0xFF] & 0xFF;
R1 = makeU32(T0, T1, T2, T3);
R2 = makeU32(T4, T5, T6, T7);
// LFSRWithWorkMode
long a = LFSR[0];
a += (long)LFSR[0] << 8;
a += (long)LFSR[4] << 20;
a += (long)LFSR[10] << 21;
a += (long)LFSR[13] << 17;
a += (long)LFSR[15] << 15;
a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
System.arraycopy(LFSR, 1, LFSR, 0, 15);
LFSR[15] = v;
}
state.R1 = R1;
state.R2 = R2;
}
// 生成单个密钥字
public static int zuc256GenerateKeyword(Zuc256State state) {
int[] LFSR = state.LFSR;
int R1 = state.R1;
int R2 = state.R2;
int X0, X1, X2, X3;
int W1, W2, U, V;
int Z;
// BitReconstruction4
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
X3 = ((LFSR[2] & 0xFFFF) << 16) | (LFSR[0] >>> 15);
Z = X3 ^ ((X0 ^ R1) + R2);
// F_(X1, X2)
W1 = R1 + X1;
W2 = R2 ^ X2;
U = L1((W1 << 16) | (W2 >>> 16));
V = L2((W2 << 16) | (W1 >>> 16));
R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
Zuc256Tables.S1[(U >>> 16) & 0xFF],
Zuc256Tables.S0[(U >>> 8) & 0xFF],
Zuc256Tables.S1[U & 0xFF]);
R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
Zuc256Tables.S1[(V >>> 16) & 0xFF],
Zuc256Tables.S0[(V >>> 8) & 0xFF],
Zuc256Tables.S1[V & 0xFF]);
// LFSRWithWorkMode
long a = LFSR[0];
a += (long)LFSR[0] << 8;
a += (long)LFSR[4] << 20;
a += (long)LFSR[10] << 21;
a += (long)LFSR[13] << 17;
a += (long)LFSR[15] << 15;
a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
System.arraycopy(LFSR, 1, LFSR, 0, 15);
LFSR[15] = v;
state.R1 = R1;
state.R2 = R2;
return Z;
}
// 初始化MAC密钥
private static void zuc256SetMacKey(Zuc256State key, byte[] K, byte[] IV, int macbits) {
int[] LFSR = key.LFSR;
int R1 = 0;
int R2 = 0;
int X0, X1, X2;
int W, W1, W2, U, V;
int[] D;
int IV17 = (IV[17] & 0xFF) >> 2;
int IV18 = ((IV[17] & 0x03) << 4) | ((IV[18] & 0xFF) >> 4);
int IV19 = ((IV[18] & 0x0F) << 2) | ((IV[19] & 0xFF) >> 6);
int IV20 = IV[19] & 0x3F;
int IV21 = (IV[20] & 0xFF) >> 2;
int IV22 = ((IV[20] & 0x03) << 4) | ((IV[21] & 0xFF) >> 4);
int IV23 = ((IV[21] & 0x0F) << 2) | ((IV[22] & 0xFF) >> 6);
int IV24 = IV[22] & 0x3F;
D = (macbits / 32 < 3) ? Zuc256Tables.ZUC256_D[macbits / 32] : Zuc256Tables.ZUC256_D[3];
LFSR[0] = makeU31(K[0] & 0xFF, D[0], K[21] & 0xFF, K[16] & 0xFF);
LFSR[1] = makeU31(K[1] & 0xFF, D[1], K[22] & 0xFF, K[17] & 0xFF);
LFSR[2] = makeU31(K[2] & 0xFF, D[2], K[23] & 0xFF, K[18] & 0xFF);
LFSR[3] = makeU31(K[3] & 0xFF, D[3], K[24] & 0xFF, K[19] & 0xFF);
LFSR[4] = makeU31(K[4] & 0xFF, D[4], K[25] & 0xFF, K[20] & 0xFF);
LFSR[5] = makeU31(IV[0] & 0xFF, (D[5] | IV17), K[5] & 0xFF, K[26] & 0xFF);
LFSR[6] = makeU31(IV[1] & 0xFF, (D[6] | IV18), K[6] & 0xFF, K[27] & 0xFF);
LFSR[7] = makeU31(IV[10] & 0xFF, (D[7] | IV19), K[7] & 0xFF, IV[2] & 0xFF);
LFSR[8] = makeU31(K[8] & 0xFF, (D[8] | IV20), IV[3] & 0xFF, IV[11] & 0xFF);
LFSR[9] = makeU31(K[9] & 0xFF, (D[9] | IV21), IV[12] & 0xFF, IV[4] & 0xFF);
LFSR[10] = makeU31(IV[5] & 0xFF, (D[10] | IV22), K[10] & 0xFF, K[28] & 0xFF);
LFSR[11] = makeU31(K[11] & 0xFF, (D[11] | IV23), IV[6] & 0xFF, IV[13] & 0xFF);
LFSR[12] = makeU31(K[12] & 0xFF, (D[12] | IV24), IV[7] & 0xFF, IV[14] & 0xFF);
LFSR[13] = makeU31(K[13] & 0xFF, D[13], IV[15] & 0xFF, IV[8] & 0xFF);
LFSR[14] = makeU31(K[14] & 0xFF, (D[14] | (K[31] >>> 4)), IV[16] & 0xFF, IV[9] & 0xFF);
LFSR[15] = makeU31(K[15] & 0xFF, (D[15] | (K[31] & 0x0F)), K[30] & 0xFF, K[29] & 0xFF);
for (int i = 0; i < 32; i++) {
// BitReconstruction3
X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
// F(X0, X1, X2)
W = (X0 ^ R1) + R2;
W1 = R1 + X1;
W2 = R2 ^ X2;
U = L1((W1 << 16) | (W2 >>> 16));
V = L2((W2 << 16) | (W1 >>> 16));
R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
Zuc256Tables.S1[(U >>> 16) & 0xFF],
Zuc256Tables.S0[(U >>> 8) & 0xFF],
Zuc256Tables.S1[U & 0xFF]);
R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
Zuc256Tables.S1[(V >>> 16) & 0xFF],
Zuc256Tables.S0[(V >>> 8) & 0xFF],
Zuc256Tables.S1[V & 0xFF]);
// LFSRWithInitialisationMode(W >> 1)
int v = LFSR[0];
v = add31(v, rot31(LFSR[0], 8));
v = add31(v, rot31(LFSR[4], 20));
v = add31(v, rot31(LFSR[10], 21));
v = add31(v, rot31(LFSR[13], 17));
v = add31(v, rot31(LFSR[15], 15));
v = add31(v, W >>> 1);
System.arraycopy(LFSR, 1, LFSR, 0, 15);
LFSR[15] = v;
}
// BitReconstruction2
X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
// F_(X1, X2)
W1 = R1 + X1;
W2 = R2 ^ X2;
U = L1((W1 << 16) | (W2 >>> 16));
V = L2((W2 << 16) | (W1 >>> 16));
R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
Zuc256Tables.S1[(U >>> 16) & 0xFF],
Zuc256Tables.S0[(U >>> 8) & 0xFF],
Zuc256Tables.S1[U & 0xFF]);
R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
Zuc256Tables.S1[(V >>> 16) & 0xFF],
Zuc256Tables.S0[(V >>> 8) & 0xFF],
Zuc256Tables.S1[V & 0xFF]);
// LFSRWithWorkMode
long a = LFSR[0];
a += (long)LFSR[0] << 8;
a += (long)LFSR[4] << 20;
a += (long)LFSR[10] << 21;
a += (long)LFSR[13] << 17;
a += (long)LFSR[15] << 15;
a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
System.arraycopy(LFSR, 1, LFSR, 0, 15);
LFSR[15] = v;
key.R1 = R1;
key.R2 = R2;
}
}