Files
se-algo/java/zuc256.java
2025-09-03 15:12:39 +08:00

553 lines
21 KiB
Java
Raw Permalink 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.

import java.util.Arrays;
public class zuc256 {
// S盒定义
private static final int[] S0 = {
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
};
private static final int[] S1 = {
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2
};
// 常量数组D
private static final int[][] ZUC256_D = {
{0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
{0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30}
};
// ZUC状态类
public static class ZUCState {
int[] LFSR = new int[16]; // 线性反馈移位寄存器
int R1; // 寄存器1
int R2; // 寄存器2
}
// 加密上下文类
public static class ZUC256EncryptCtx {
ZUCState state = new ZUCState();
byte[] buf = new byte[4];
int buflen;
}
// MAC上下文类
public static class ZUC256MacCtx {
int[] LFSR = new int[16];
int R1;
int R2;
byte[] buf = new byte[4];
int buflen;
int[] T = new int[4];
int[] K0 = new int[4];
int macbits;
}
// 辅助方法将字节数组转换为32位整数
private 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位整数转换为字节数组
private 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;
}
// 31位加法
private static int add31(int a, int b) {
long sum = (long)a + b;
return (int) ((sum & 0x7FFFFFFF) + (sum >> 31));
}
// 31位旋转
private static int rot31(int a, int k) {
return ((a << k) | (a >>> (31 - k))) & 0x7FFFFFFF;
}
// 32位旋转
private static int rot32(int a, int k) {
return (a << k) | (a >>> (32 - k));
}
// L1函数
private static int L1(int x) {
return x ^ rot32(x, 2) ^ rot32(x, 10) ^ rot32(x, 18) ^ rot32(x, 24);
}
// L2函数
private static int L2(int x) {
return x ^ rot32(x, 8) ^ rot32(x, 14) ^ rot32(x, 22) ^ rot32(x, 30);
}
// 初始化MAC密钥
private static void zuc256SetMacKey(ZUCState 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) ? ZUC256_D[macbits / 32] : 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(S0[(U >>> 24) & 0xFF],
S1[(U >>> 16) & 0xFF],
S0[(U >>> 8) & 0xFF],
S1[U & 0xFF]);
R2 = makeU32(S0[(V >>> 24) & 0xFF],
S1[(V >>> 16) & 0xFF],
S0[(V >>> 8) & 0xFF],
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(S0[(U >>> 24) & 0xFF],
S1[(U >>> 16) & 0xFF],
S0[(U >>> 8) & 0xFF],
S1[U & 0xFF]);
R2 = makeU32(S0[(V >>> 24) & 0xFF],
S1[(V >>> 16) & 0xFF],
S0[(V >>> 8) & 0xFF],
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;
}
// 创建31位无符号整数
private 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位无符号整数
private static int makeU32(int a, int b, int c, int d) {
return ((a & 0xFF) << 24) |
((b & 0xFF) << 16) |
((c & 0xFF) << 8) |
(d & 0xFF);
}
// 初始化ZUC256状态
public static void zuc256Init(ZUCState state, byte[] K, byte[] IV) {
zuc256SetMacKey(state, K, IV, 0);
}
// 生成单个密钥字
public static int zuc256GenerateKeyword(ZUCState 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(S0[(U >>> 24) & 0xFF],
S1[(U >>> 16) & 0xFF],
S0[(U >>> 8) & 0xFF],
S1[U & 0xFF]);
R2 = makeU32(S0[(V >>> 24) & 0xFF],
S1[(V >>> 16) & 0xFF],
S0[(V >>> 8) & 0xFF],
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(ZUCState 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 = S0[(U >>> 24) & 0xFF] & 0xFF;
int T2 = S0[(U >>> 8) & 0xFF] & 0xFF;
int T4 = S0[(V >>> 24) & 0xFF] & 0xFF;
int T6 = S0[(V >>> 8) & 0xFF] & 0xFF;
int T1 = S1[(U >>> 16) & 0xFF] & 0xFF;
int T3 = S1[U & 0xFF] & 0xFF;
int T5 = S1[(V >>> 16) & 0xFF] & 0xFF;
int T7 = 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 void zuc256EncryptInit(ZUC256EncryptCtx ctx, byte[] K, byte[] IV) {
Arrays.fill(ctx.buf, (byte) 0);
ctx.buflen = 0;
zuc256Init(ctx.state, K, IV);
}
// 分阶段处理加密数据
public static void zuc256EncryptUpdate(ZUC256EncryptCtx ctx, byte[] in, int inlen, byte[] out) {
if (in == null || out == null || inlen == 0) return;
// 处理缓冲区中剩余的非4字节数据
if (ctx.buflen > 0) {
int need = 4 - ctx.buflen;
int copy = Math.min(inlen, need);
System.arraycopy(in, 0, ctx.buf, ctx.buflen, copy);
ctx.buflen += copy;
// 调整输入指针和长度
byte[] newIn = new byte[inlen - copy];
if (inlen - copy > 0) {
System.arraycopy(in, copy, newIn, 0, inlen - copy);
}
in = newIn;
inlen -= copy;
// 缓冲区已满处理一个完整的4字节块
if (ctx.buflen == 4) {
int keystream = zuc256GenerateKeyword(ctx.state);
int plain = getU32(ctx.buf, 0);
putU32(out, 0, plain ^ keystream);
ctx.buflen = 0;
Arrays.fill(ctx.buf, (byte) 0);
// 调整输出指针
byte[] newOut = new byte[out.length - 4];
if (out.length - 4 > 0) {
System.arraycopy(out, 4, newOut, 0, out.length - 4);
}
out = newOut;
}
}
// 处理完整的4字节块
int fullBlocks = inlen / 4;
if (fullBlocks > 0) {
int[] keystream = new int[fullBlocks];
zuc256GenerateKeystream(ctx.state, fullBlocks, keystream);
// 逐块异或加密
for (int i = 0; i < fullBlocks; i++) {
int plain = getU32(in, i * 4);
putU32(out, i * 4, plain ^ keystream[i]);
}
// 调整输入指针和长度
int processed = fullBlocks * 4;
byte[] newIn = new byte[inlen - processed];
if (inlen - processed > 0) {
System.arraycopy(in, processed, newIn, 0, inlen - processed);
}
in = newIn;
inlen -= processed;
}
// 缓存剩余不足4字节的数据
if (inlen > 0) {
System.arraycopy(in, 0, ctx.buf, 0, inlen);
ctx.buflen = inlen;
}
}
// 完成加密处理
public static void zuc256EncryptFinish(ZUC256EncryptCtx ctx, byte[] out) {
if (ctx == null || out == null) return;
// 处理缓冲区中剩余的不足4字节数据
if (ctx.buflen > 0) {
int keystream = zuc256GenerateKeyword(ctx.state);
byte[] keystreamBytes = new byte[4];
putU32(keystreamBytes, 0, keystream);
// 逐字节异或
for (int i = 0; i < ctx.buflen; i++) {
out[i] = (byte) (ctx.buf[i] ^ keystreamBytes[i]);
}
}
// 清理上下文
Arrays.fill(ctx.buf, (byte) 0);
ctx.buflen = 0;
Arrays.fill(ctx.state.LFSR, 0);
ctx.state.R1 = 0;
ctx.state.R2 = 0;
}
// 一次性加密函数
public static void zuc256Crypt(ZUCState state, byte[] in, int inlen, byte[] out) {
if (state == null || in == null || out == null) return;
ZUC256EncryptCtx ctx = new ZUC256EncryptCtx();
// 复制状态
System.arraycopy(state.LFSR, 0, ctx.state.LFSR, 0, state.LFSR.length);
ctx.state.R1 = state.R1;
ctx.state.R2 = state.R2;
// 执行加解密
zuc256EncryptUpdate(ctx, in, inlen, out);
int remainingOffset = (inlen / 4) * 4;
byte[] finishOut = new byte[out.length - remainingOffset];
if (finishOut.length > 0) {
System.arraycopy(out, remainingOffset, finishOut, 0, finishOut.length);
}
zuc256EncryptFinish(ctx, finishOut);
System.arraycopy(finishOut, 0, out, remainingOffset, finishOut.length);
// 更新状态
System.arraycopy(ctx.state.LFSR, 0, state.LFSR, 0, ctx.state.LFSR.length);
state.R1 = ctx.state.R1;
state.R2 = ctx.state.R2;
}
// 提取IV
public static void extractIv(byte[] input25Byte, byte[] output23Byte) {
if (input25Byte == null || output23Byte == null) return;
// 复制前17字节
System.arraycopy(input25Byte, 0, output23Byte, 0, 17);
// 处理剩余8字节
byte[] src = new byte[8];
for (int 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]);
}
// 打印字节数组为十六进制
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();
}
// 主函数验证ZUC256加解密功能
public static void main(String[] args) {
// 1. 明文
byte[] plaintext = "ZUC256对称加解密测试:1234567890".getBytes();
int plaintextLen = plaintext.length;
System.out.println("明文: " + new String(plaintext));
printHex("明文(十六进制)", plaintext, plaintextLen);
// 2. 密钥(32字节ASCII)
byte[] key = "0123456789abcdef0123456789abcdef".getBytes();
printHex("密钥", key, 32);
// 3. 初始向量(25字节ASCII)
byte[] inputIv25Byte = "0123456789abcdefg01234567".getBytes();
byte[] iv = new byte[23];
extractIv(inputIv25Byte, iv);
printHex("提取后的IV", iv, 23);
// 4. 分配加密/解密缓冲区
byte[] ciphertext = new byte[plaintextLen];
byte[] decryptedtext = new byte[plaintextLen];
// 5. 加密
ZUCState state = new ZUCState();
zuc256Init(state, key, iv);
zuc256Crypt(state, plaintext, plaintextLen, ciphertext);
printHex("密文", ciphertext, plaintextLen);
// 6. 解密(重新初始化状态)
zuc256Init(state, key, iv);
zuc256Crypt(state, ciphertext, plaintextLen, decryptedtext);
printHex("解密后", decryptedtext, plaintextLen);
System.out.println("解密文本: " + new String(decryptedtext));
// 7. 验证结果
if (Arrays.equals(plaintext, decryptedtext)) {
System.out.println("=== 测试成功: 解密结果与明文一致 ===");
} else {
System.out.println("=== 测试失败: 解密结果与明文不一致 ===");
}
}
}