ZUC流密码加密解密工具
基于Python实现的ZUC流密码加密解密工具。ZUC是中国自主研发的流密码算法,已被采纳为4G移动通信加密标准。该工具通过Streamlit构建了用户友好的Web界面,提供文本加密和解密功能。核心功能包括:支持128位密钥和IV输入、UTF-8文本加密、十六进制格式结果显示、加密详情展示和字节对比。文章详细说明了ZUC算法的实现要点,包括S盒置换、线性变换函数和密钥流生成过程。工具还包含算法说明、安全提示和使用示例,帮助用户正确使用该加密工具。该实现严格遵循ZUC算法规范,为保护数据安全提供了便捷的解决方案。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import streamlit as st
import binascii# ZUC算法实现 - 修正了S0和S1数组中的错误
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
]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 = [0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF,0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC
]def addition_uint31(a, b):c = a + breturn (c & 0x7FFFFFFF) + (c >> 31)def rotl_uint31(a, shift):return ((a << shift) | (a >> (31 - shift))) & 0x7FFFFFFFdef rotl_uint32(a, shift):return ((a << shift) | (a >> (32 - shift))) & 0xFFFFFFFFdef l1(x):return (x ^ rotl_uint32(x, 2) ^ rotl_uint32(x, 10) ^ rotl_uint32(x, 18) ^ rotl_uint32(x, 24))def l2(x):return (x ^ rotl_uint32(x, 8) ^ rotl_uint32(x, 14) ^ rotl_uint32(x, 22) ^ rotl_uint32(x, 30))def make_uint32(a, b, c, d):return ((a << 24) & 0xffffffff) | ((b << 16) & 0xffffffff) | ((c << 8) & 0xffffffff) | ddef make_uint31(a, b, c):return (a << 23) | (b << 8) | cclass ZUC:def __init__(self, key, iv):self.r = [0, 0]self.lfsr = [0 for _ in range(16)]self.x = [0, 0, 0, 0]self.zuc_init(key, iv)def bit_reorganization(self):self.x[0] = ((self.lfsr[15] & 0x7FFF8000) << 1) | (self.lfsr[14] & 0xFFFF)self.x[1] = ((self.lfsr[11] & 0xFFFF) << 16) | (self.lfsr[9] >> 15)self.x[2] = ((self.lfsr[7] & 0xFFFF) << 16) | (self.lfsr[5] >> 15)self.x[3] = ((self.lfsr[2] & 0xFFFF) << 16) | (self.lfsr[0] >> 15)def lfsr_next(self):f = self.lfsr[0]v = rotl_uint31(self.lfsr[0], 8)f = addition_uint31(f, v)v = rotl_uint31(self.lfsr[4], 20)f = addition_uint31(f, v)v = rotl_uint31(self.lfsr[10], 21)f = addition_uint31(f, v)v = rotl_uint31(self.lfsr[13], 17)f = addition_uint31(f, v)v = rotl_uint31(self.lfsr[15], 15)f = addition_uint31(f, v)return fdef lfsr_append(self, f):self.lfsr.append(f)if len(self.lfsr) > 16:self.lfsr.pop(0)def lfsr_init(self, u):self.lfsr_append(addition_uint31(self.lfsr_next(), u))def lfsr_shift(self):self.lfsr_append(self.lfsr_next())def f(self):W = ((self.x[0] ^ self.r[0]) + self.r[1]) & 0xffffffffW1 = (self.r[0] + self.x[1]) & 0xffffffffW2 = self.r[1] ^ self.x[2]u = l1(((W1 & 0x0000ffff) << 16) | (W2 >> 16))v = l2(((W2 & 0x0000ffff) << 16) | (W1 >> 16))self.r = [make_uint32(S0[u >> 24], S1[(u >> 16) & 0xFF],S0[(u >> 8) & 0xFF], S1[u & 0xFF]),make_uint32(S0[v >> 24], S1[(v >> 16) & 0xFF],S0[(v >> 8) & 0xFF], S1[v & 0xFF])]return Wdef zuc_init(self, key, iv):# Expand key.self.lfsr = [make_uint31(key[i], D[i] & 0x7FFF, iv[i]) for i in range(16)]self.r = [0, 0]for i in range(32):self.bit_reorganization()w = self.f()self.lfsr_init(w >> 1)def zuc_generate_keystream(self, length):keystream_buffer = []self.bit_reorganization()self.f() # Discard the output of F.def itor():self.lfsr_shift()self.bit_reorganization()return self.f() ^ self.x[-1]keystream_buffer = [itor() for _ in range(length)]self.lfsr_shift()return keystream_bufferdef zuc_encrypt(self, input):length = len(input)# 计算需要多少个32位字num_words = (length + 3) // 4key_stream_words = self.zuc_generate_keystream(num_words)# 将密钥流字转换为字节列表key_stream_bytes = []for word in key_stream_words:key_stream_bytes.append((word >> 24) & 0xFF)key_stream_bytes.append((word >> 16) & 0xFF)key_stream_bytes.append((word >> 8) & 0xFF)key_stream_bytes.append(word & 0xFF)# 取前length个字节key_stream_bytes = key_stream_bytes[:length]# 逐字节异或return [input[i] ^ key_stream_bytes[i] for i in range(length)]# Streamlit应用界面
def main():st.set_page_config(page_title="ZUC加密解密工具", page_icon="🔒", layout="wide")st.title("🔐 ZUC流密码加密解密工具")st.markdown("""**ZUC算法**是中国自主研发的流密码算法,已被国际组织3GPP采纳为4G移动通信加密标准。本工具使用Python实现的ZUC算法进行文本加密和解密。""")# 创建选项卡tab1, tab2 = st.tabs(["加密", "解密"])with tab1:st.subheader("文本加密")col1, col2 = st.columns(2)with col1:st.markdown("### 输入参数")message = st.text_area("输入要加密的文本:", height=150,placeholder="在此输入要加密的文本...")key_input = st.text_input("密钥 (16字节):", value="0" * 32,help="请输入32个十六进制字符(0-9, A-F)")iv_input = st.text_input("初始化向量 (16字节):", value="0" * 32,help="请输入32个十六进制字符(0-9, A-F)")if st.button("加密文本", use_container_width=True):if not message:st.warning("请输入要加密的文本")elif len(key_input) != 32 or len(iv_input) != 32:st.error("密钥和IV必须是32个十六进制字符(16字节)")else:try:# 将十六进制字符串转换为字节列表key = [int(key_input[i:i + 2], 16) for i in range(0, 32, 2)]iv = [int(iv_input[i:i + 2], 16) for i in range(0, 32, 2)]# 将消息转换为字节列表message_bytes = list(message.encode('utf-8'))# 初始化ZUC并加密zuc = ZUC(key, iv)encrypted = zuc.zuc_encrypt(message_bytes)# 将加密结果转换为十六进制字符串encrypted_hex = ''.join([f"{x:02x}" for x in encrypted])# 显示结果with col2:st.markdown("### 加密结果")st.success("文本加密成功!")st.code(encrypted_hex, language="hex")# 添加复制按钮if st.button("复制加密结果", key="copy_encrypted"):st.session_state.copied_text = encrypted_hexst.success("已复制到剪贴板!")# 显示加密详情with st.expander("加密详情"):st.write(f"原始文本长度: {len(message)} 字符")st.write(f"加密后长度: {len(encrypted_hex) // 2} 字节")st.write(f"密钥: {key_input}")st.write(f"IV: {iv_input}")# 显示字节对比st.markdown("**字节对比:**")col_a, col_b = st.columns(2)with col_a:st.markdown("**原始字节:**")st.code(' '.join([f"{b:02x}" for b in message_bytes]))with col_b:st.markdown("**加密字节:**")st.code(' '.join([f"{x:02x}" for x in encrypted]))except Exception as e:st.error(f"加密过程中发生错误: {str(e)}")with tab2:st.subheader("文本解密")col1, col2 = st.columns(2)with col1:st.markdown("### 输入参数")encrypted_hex = st.text_area("输入要解密的密文 (十六进制):", height=150,placeholder="在此输入十六进制密文...")key_input = st.text_input("解密密钥 (16字节):", value="0" * 32,help="请输入32个十六进制字符(0-9, A-F)")iv_input = st.text_input("解密IV (16字节):", value="0" * 32,help="请输入32个十六进制字符(0-9, A-F)")if st.button("解密文本", use_container_width=True):if not encrypted_hex:st.warning("请输入要解密的密文")elif len(key_input) != 32 or len(iv_input) != 32:st.error("密钥和IV必须是32个十六进制字符(16字节)")else:try:# 清理输入的十六进制字符串(移除空格等)clean_hex = ''.join(filter(str.isalnum, encrypted_hex))# 验证十六进制字符串长度if len(clean_hex) % 2 != 0:st.error("十六进制密文长度必须为偶数")return# 将十六进制字符串转换为字节列表key = [int(key_input[i:i + 2], 16) for i in range(0, 32, 2)]iv = [int(iv_input[i:i + 2], 16) for i in range(0, 32, 2)]# 将十六进制密文转换为整数列表encrypted_bytes = []for i in range(0, len(clean_hex), 2):byte_str = clean_hex[i:i + 2]if len(byte_str) != 2:continuetry:byte_val = int(byte_str, 16)if byte_val < 0 or byte_val > 255:st.error(f"无效的字节值: {byte_str}")returnencrypted_bytes.append(byte_val)except ValueError:st.error(f"无效的十六进制字符: {byte_str}")return# 初始化ZUC并解密zuc = ZUC(key, iv)decrypted_bytes = zuc.zuc_encrypt(encrypted_bytes)# 尝试将解密结果转换为字符串try:decrypted_text = bytes(decrypted_bytes).decode('utf-8')except UnicodeDecodeError:decrypted_text = "<二进制数据>"st.warning("解密结果包含非UTF-8字符,可能不是文本数据")# 显示结果with col2:st.markdown("### 解密结果")st.success("文本解密成功!")st.code(decrypted_text, language="text")# 添加复制按钮if st.button("复制解密结果", key="copy_decrypted"):st.session_state.copied_text = decrypted_textst.success("已复制到剪贴板!")# 显示解密详情with st.expander("解密详情"):st.write(f"密文长度: {len(encrypted_bytes)} 字节")st.write(f"解密后长度: {len(decrypted_bytes)} 字节")st.write(f"密钥: {key_input}")st.write(f"IV: {iv_input}")# 显示字节对比st.markdown("**字节对比:**")col_a, col_b = st.columns(2)with col_a:st.markdown("**加密字节:**")st.code(' '.join([f"{b:02x}" for b in encrypted_bytes]))with col_b:st.markdown("**解密字节:**")st.code(' '.join([f"{b:02x}" for b in decrypted_bytes]))except Exception as e:st.error(f"解密过程中发生错误: {str(e)}")# 添加算法说明st.markdown("---")st.subheader("关于ZUC算法")st.markdown("""**ZUC算法**是中国自主研发的流密码算法,具有以下特点:- 使用128位密钥和128位初始化向量(IV)- 基于线性反馈移位寄存器(LFSR)和非线性函数- 已被采纳为4G移动通信(LTE)的国际加密标准- 提供高安全性和高效的硬件实现### 算法流程1. **初始化阶段**:使用密钥和IV初始化LFSR2. **工作阶段**:生成密钥流3. **加密/解密**:将密钥流与明文/密文进行异或操作### 安全提示- 请使用强密钥(随机生成的32个十六进制字符)- 每次加密都应使用不同的IV- 不要重复使用相同的密钥和IV组合""")# 添加示例部分st.markdown("---")st.subheader("使用示例")st.markdown("""### 加密示例1. 在"加密"选项卡中输入文本:"Hello ZUC!"2. 输入密钥:`0123456789ABCDEFFEDCBA9876543210`3. 输入IV:`FEDCBA98765432100123456789ABCDEF`4. 点击"加密文本"按钮5. 复制加密结果### 解密示例1. 在"解密"选项卡中粘贴加密结果2. 输入相同的密钥和IV3. 点击"解密文本"按钮4. 查看解密后的原始文本""")if __name__ == "__main__":main()