WG-8 轻量级序列密码算法

一、概述

WG-8(Welch-Gong-8)是一种基于 GF(2⁸) 有限域的轻量级序列密码,由 Nawaz 和 Gong 提出,适用于资源受限环境(如物联网设备)。其核心设计围绕线性反馈移位寄存器(LFSR)Welch-Gong 置换(WGP) 展开,每时钟周期输出 1 比特密钥流。

主要参数

参数
有限域 GF(2⁸), p(x)=x⁸+x⁴+x³+x+1 (0x11B)
LFSR 级数 20 级(每级 8 比特)
密钥长度 80 比特
IV 长度 80 比特
初始化时钟 40 个周期
抽取因子 d 19
输出率 1 比特/时钟

二、有限域 GF(2⁸)

2.1 域的定义

WG-8 工作在 GF(2⁸) 上,即包含 256 个元素的有限域。域中的元素可以表示为 0x00–0xFF 的字节。

不可约多项式p(x) = x⁸ + x⁴ + x³ + x + 1 = 0x11B

本原元ω = 0x02(即多项式 x

2.2 加法

GF(2⁸) 中的加法即为按位异或(XOR):

def gf256_add(a: int, b: int) -> int:
    return a ^ b

2.3 乘法

乘法使用标准的「移位加」算法,当左移产生进位(x⁸ 项)时,通过异或 0x1B(不可约多项式的低 8 位)进行模约减:

def gf256_mul(a: int, b: int) -> int:
    result = 0
    for _ in range(8):
        if b & 1:
            result ^= a
        carry = a & 0x80
        a = (a << 1) & 0xFF
        if carry:
            a ^= 0x1B   # x⁴ + x³ + x + 1
        b >>= 1
    return result

原理:当 a 的最高位(x⁷)为 1 时,左移一位会产生 x⁸ 项。根据不可约多项式 x⁸ = x⁴ + x³ + x + 1,将 0x1B 异或回去完成约减。

2.4 幂运算

使用快速幂(指数平方)算法:

def gf256_pow(a: int, exp: int) -> int:
    if a == 0:
        return 0 if exp > 0 else 1
    result = 1
    base = a
    while exp > 0:
        if exp & 1:
            result = gf256_mul(result, base)
        base = gf256_mul(base, base)
        exp >>= 1
    return result

在 GF(2⁸) 中,对所有非零元素有 x²⁵⁵ = 1(费马小定理),但快速幂算法自然兼容大指数。

2.5 迹函数(Trace)

迹函数将 GF(2⁸) 中的元素映射到 GF(2)(即 0 或 1):

Tr(x) = x + x² + x⁴ + x⁸ + x¹⁶ + x³² + x⁶⁴ + x¹²⁸
def gf256_trace(a: int) -> int:
    result = a
    val = a
    for _ in range(7):
        val = gf256_mul(val, val)  # 重复平方
        result ^= val
    return result & 1

由于迹函数的结果属于 GF(2),返回值仅为 0 或 1。


三、WGP-8(Welch-Gong 置换)

3.1 定义

WGP-8 使用抽取因子 d=19,定义为:

WGP-8(x) = x¹⁹

由于 gcd(19, 255) = 1,映射 x → x¹⁹ 是 GF(2⁸) 上的一个置换(双射),即 256 个输入值对应 256 个互不相同的输出值。

3.2 查表实现

为了高效实现,预先计算 256 字节的查找表(LUT):

WGP8_LUT = [gf256_pow(x, 19) for x in range(256)]

def wgp8(x: int) -> int:
    return WGP8_LUT[x]

预计算只需执行一次(模块加载时),后续查询为 O(1)。

3.3 置换验证

排序后检查 LUT 是否恰好包含 [0, 1, 2, ..., 255]:

sorted_lut = sorted(WGP8_LUT)
assert sorted_lut == list(range(256))  # 确认为置换

四、WGT-8(Welch-Gong 变换)

WGT-8 将 WGP-8 的结果通过迹函数映射为 1 个比特:

WGT-8(x) = Tr(WGP-8(x)) = Tr(x¹⁹)
def wgt8(x: int) -> int:
    return gf256_trace(WGP8_LUT[x])

这一比特就是最终的密钥流输出。


五、LFSR(线性反馈移位寄存器)

5.1 结构

WG-8 使用 20 级 Fibonacci 型 LFSR,每级存储 8 比特:

S₀, S₁, ..., S₁₉    每个 Sᵢ ∈ GF(2⁸)

5.2 反馈多项式

l(x) = x²⁰ + x⁹ + x⁸ + x⁷ + x⁴ + x³ + x² + x + ω

对应的线性反馈函数:

feedback = ω·S₀ ⊕ S₁ ⊕ S₂ ⊕ S₃ ⊕ S₄ ⊕ S₇ ⊕ S₈ ⊕ S₉

注意 S₅、S₆ 及其他级不在反馈中,这是由多项式的系数决定的。

5.3 运行阶段时钟

运行阶段每时钟执行:

  1. 计算线性反馈值
  2. 状态左移:[S₁, S₂, ..., S₁₉, feedback]
  3. 将 WGT-8(S₁₉) 作为密钥流输出
def clock_run(self):
    fb = self._linear_feedback()
    self.state.pop(0)
    self.state.append(fb)

# 密钥流比特
bit = wgt8(self.state[19])

5.4 初始化阶段时钟

初始化阶段的反馈包含非线性项 WGP-8(S₁₉):

def clock_init(self):
    fb = self._linear_feedback() ^ wgp8(self.state[19])
    self.state.pop(0)
    self.state.append(fb)

这 40 个初始化时钟周期将密钥和 IV 充分混合到 LFSR 状态中。


六、密钥/IV 加载

80 比特密钥 K 和 80 比特 IV 分别表示为 10 字节数组:

K = K₀, K₁, ..., K₉   (每字节 8 比特)
IV = IV₀, IV₁, ..., IV₉

加载方式为半字节交错:

S₂ᵢ   = (Kᵢ & 0x0F) << 4 | (IVᵢ & 0x0F)
S₂ᵢ₊₁ = (Kᵢ & 0xF0)       | ((IVᵢ >> 4) & 0x0F)

直观理解:每个 S 字节的高半字节来自密钥,低半字节来自 IV。

示例:K₀ = 0xAB, IV₀ = 0xCD
  S₀ = 0xB0 | 0x0D = 0xBD   (K的低4位 || IV的低4位)
  S₁ = 0xA0 | 0x0C = 0xAC   (K的高4位 || IV的高4位)

七、加密与解密

7.1 密钥流生成

初始化 40 时钟后,WG-8 进入运行阶段。对于每个需要输出的比特:

  1. clock_run() —— 更新 LFSR 状态
  2. wgt8(S[19]) —— 从最后一级提取 1 比特密钥流

生成指定比特数的密钥流,打包为字节(MSB 优先):

def generate_keystream(self, num_bits):
    num_bytes = (num_bits + 7) // 8
    result = bytearray(num_bytes)
    for i in range(num_bits):
        bit = self._generate_bit()       # clock_run + wgt8
        byte_idx = i // 8
        bit_idx = 7 - (i % 8)
        result[byte_idx] |= bit << bit_idx
    return bytes(result)

7.2 加密/解密

WG-8 是对称流密码,加密和解密均为 XOR 操作:

def encrypt(self, plaintext):
    keystream = self.generate_keystream(len(plaintext) * 8)
    return bytes(p ^ k for p, k in zip(plaintext, keystream))

def decrypt(self, ciphertext):
    return self.encrypt(ciphertext)  # XOR 对称性

八、完整流程图

密钥 K(80 bit) ─┐
                 ├──→ 密钥/IV加载 ──→ LFSR (S₀...S₁₉)
IV (80 bit)  ───┘                           │
                                             │
                           ┌─────────────────┘
                           ▼
                ┌──────────────────────┐
                │   初始化 (40 时钟)    │
                │  反馈 ⊕ WGP-8(S₁₉)   │
                └──────────┬───────────┘
                           │
                           ▼
                ┌──────────────────────┐
                │   运行阶段            │
                │  线性反馈             │
                │  每时钟: wgt8(S₁₉)   │──→ 密钥流比特
                └──────────────────────┘
                           │
                           ▼
                明文 ──→ ⊕ ──→ 密文

九、安全性说明

  1. 全零密钥/IV 弱密钥:LFSR 的固有数学性质导致全零输入产生全零状态。这是因为 ω·0 = 00 ⊕ 0 = 0,状态永远无法脱离全零状态。实际使用中应避免。

  2. WGP-8 置换x¹⁹ 是 GF(2⁸) 上的置换,确保了输出的均匀分布。

  3. 迹函数的非线性:迹函数将 GF(2⁸) 压缩到 1 比特,提供了密码所需的非线性特性。

  4. 80 比特安全性:密钥长度为 80 比特,提供 80 比特的安全强度,适用于轻量级应用场景。

posted @ 2026-07-09 14:14  lumiere_nebula  阅读(14)  评论(0)    收藏  举报