深度学习辅助的Simeck32/64轻量级密码差分分析实战
1. 项目概述当深度学习“遇见”轻量级密码在密码分析领域Simeck32/64一直是一个颇具代表性的轻量级分组密码。它结构简洁设计初衷是为了在资源受限的物联网设备上实现高效的加密。然而对于密码分析者而言简洁的结构有时也意味着攻击面可能更集中。传统的差分分析、线性分析等方法在攻击Simeck时往往需要大量的已知明文-密文对和相当复杂的计算尤其是在攻击轮数增加时攻击难度呈指数级上升。最近几年我和团队一直在探索如何将深度学习这股“东风”引入到密码分析这个传统领域。我们瞄准的目标正是Simeck32/64。这个项目的核心不是要构建一个通用的、能破解一切密码的“AI黑箱”而是尝试利用深度学习的模式识别能力去辅助和增强传统的密钥恢复攻击特别是降低攻击所需的轮数。换句话说我们想看看能不能用神经网络“学习”到Simeck在较少轮数加密时泄露出的、人眼难以察觉的统计特征从而为后续的密钥搜索或分析指明方向甚至直接缩小密钥空间。这听起来有点像在嘈杂的信号中寻找特定频率的共振。传统的分析方法像是用固定的滤波器去筛而深度学习则试图自己学会制造一个最匹配当前噪声模式的滤波器。如果成功这意味着我们可能用比传统方法更少的数据、更低的计算成本对经过较少轮加密的Simeck密文发起有效的攻击。这对于评估轻量级密码在早期轮次的安全性具有重要参考价值。2. 核心思路与方案设计神经差分区分器的构建我们的攻击方案核心是构建一个基于深度学习的差分区分器。这不是一个端到端的密钥预测模型那在目前看来过于困难而是一个二分类器给定一个输入差分和对应的输出密文对判断这个密文对是否是由某个特定的输入差分经过目标轮数的Simeck加密产生的。2.1 为什么选择差分分析作为切入点差分分析是分组密码最强大的攻击手段之一。它关注的是固定输入差分ΔP下输出差分ΔC的分布特性。对于一个理想的密码任何输出差分都应是近似均匀随机的。但如果密码在特定轮数下存在高概率的差分特征即一条差分传播路径那么攻击者就可以利用这一点来区分密码与随机置换。传统方法需要手工寻找高概率的差分特征这个过程复杂且依赖于分析者的经验。我们的思路是让神经网络自己去从海量的输入差分密文对数据中学习是否存在这样的统计关联性。如果神经网络能够以高于随机猜测50%的准确率进行区分那么我们就得到了一个有效的“神经差分区分器”。这个区分器本身就可以作为一种攻击手段区分攻击更重要的是它可以作为传统密钥恢复攻击如差分攻击的“前导”或“过滤器”大幅减少需要后续暴力搜索或分析的候选数据量。2.2 整体攻击流程设计我们的攻击流程分为两个主要阶段训练阶段和攻击阶段。训练阶段数据生成随机生成大量明文对(P, P‘)满足固定的输入差分ΔP。用目标轮数例如19轮的Simeck32/64和一个随机密钥K对它们进行加密得到密文对(C, C‘)。这部分数据标记为“正样本”来自Simeck。同时生成同样数量的随机密文对标记为“负样本”来自随机置换。特征工程直接将密文对(C, C‘)的比特值作为输入特征过于原始。我们引入了差分值ΔC C ⊕ C‘并将C和ΔC进行某种形式的拼接或组合作为神经网络的输入。这相当于显式地告诉网络差分信息帮助它聚焦于差分关系。模型训练使用构建的数据集训练一个卷积神经网络CNN或密集连接网络DenseNet。网络的目标是二分类判断输入样本来自Simeck还是随机源。攻击阶段收集数据在未知密钥K的情况下收集大量满足特定输入差分ΔP的明文-密文对。区分筛选将收集到的密文对输入训练好的神经区分器。区分器会给出一个“置信度”分数表明该密文对有多大可能来自目标轮数的Simeck。密钥恢复筛选出置信度最高的一批密文对。利用这些“高价值”密文对结合传统的差分攻击技术例如猜测最后一轮或几轮的子密钥验证其是否满足预期的差分特征进行密钥恢复。由于神经区分器已经帮我们过滤掉了大量“无用”数据密钥恢复步骤需要处理的候选数据和密钥猜测空间会小得多从而实现了“约减轮数”的攻击——我们可能用针对19轮训练的区分器辅助攻击21轮或22轮的Simeck因为攻击后期轮次所需的正确差分特征可能仍然部分成立。注意神经区分器并不直接输出密钥比特。它的作用是提供一个优质的数据筛选工具。传统攻击可能需要对所有数据尝试密钥猜测而我们的方法先“提纯”数据使得后续的猜测更有针对性效率更高。2.3 模型与工具选型深度学习框架PyTorch。选择它的原因在于其动态图特性非常适合研究性实验我们可以灵活地调整模型结构和训练流程。与TensorFlow相比PyTorch的代码更直观调试起来更方便这对于需要大量尝试不同网络架构和输入特征的密码分析实验至关重要。神经网络架构主要尝试了1D-CNN和全连接网络MLP。1D-CNN将密文C和差分ΔC的比特序列视为一维信号。CNN的卷积核可以自动提取局部比特模式之间的相关性这可能对应着Simeck轮函数中非线性组件AND运算产生的局部扩散特性。我们使用了2-3个卷积层后接池化层和全连接层。全连接网络MLP作为基线模型。输入层接收展平的(C, ΔC)向量。虽然缺乏空间结构先验但足够深的MLP理论上可以拟合任何函数有助于我们判断问题的可学习性。硬件使用配备NVIDIA RTX 3090的服务器进行训练。数据生成和预处理部分使用CPU并行完成。GPU的并行计算能力主要用在模型训练的前向传播和反向传播这两个核心步骤上。在训练时大批量的数据样本被同时送入GPU矩阵乘法和卷积运算得以并行处理这是加速深度学习训练最关键的一环。密码实现使用Python的bitstring库和自定义代码实现Simeck32/64的加密算法确保数据生成的准确性。3. 核心实现细节与实操要点3.1 数据生成管道构建数据质量是项目成败的基础。我们构建了一个高效、可复现的数据生成管道。import numpy as np from simeck import Simeck32_64 # 假设已实现 import secrets def generate_dataset(num_samples, input_diff, rounds, keyNone): 生成训练数据集 Args: num_samples: 正样本数量负样本数量相同 input_diff: 输入差分32位整数 rounds: 加密轮数 key: 可选固定密钥若为None则每批样本使用随机密钥 Returns: X: 特征矩阵形状 (2*num_samples, feature_dim) y: 标签数组1为Simeck0为随机 X [] y [] cipher Simeck32_64() # 生成正样本来自Simeck for _ in range(num_samples): if key is None: K secrets.randbits(64) # 每对样本使用不同密钥更符合实际攻击场景 else: K key P secrets.randbits(32) P_prime P ^ input_diff C cipher.encrypt(P, K, rounds) C_prime cipher.encrypt(P_prime, K, rounds) # 特征构造将C和差分 DeltaC C ^ C_prime 拼接 delta_C C ^ C_prime # 将32位整数转换为32维的二进制向量0/1 feature np.unpackbits(np.array([C, delta_C], dtypenp.uint32).view(np.uint8)) X.append(feature) y.append(1) # 生成负样本来自随机置换 for _ in range(num_samples): C secrets.randbits(32) C_prime secrets.randbits(32) delta_C C ^ C_prime feature np.unpackbits(np.array([C, delta_C], dtypenp.uint32).view(np.uint8)) X.append(feature) y.append(0) return np.array(X, dtypenp.float32), np.array(y, dtypenp.float32)关键细节与考量密钥随机性在训练区分器时我们采用了每对明文使用不同随机密钥的策略。这迫使神经网络学习的是与密钥无关的、Simeck算法本身的结构性差分特征而不是去记忆某个特定密钥下的特定模式。这样训练出的区分器才具有泛化能力可以用于攻击未知密钥。差分固定输入差分ΔP需要固定。我们通过文献调研和初步实验选择了Simeck32/64在目标轮数下已知概率较高的几个差分值作为候选。特征表示直接将C和ΔC的二进制比特流作为输入。这里没有进行复杂的特征工程因为我们希望神经网络自己发现有用的表示。输入维度是6432位C 32位ΔC。数据平衡正负样本严格1:1防止模型偏向某一类。3.2 神经网络模型搭建我们以1D-CNN模型为例展示核心结构。import torch import torch.nn as nn import torch.nn.functional as F class SimeckDiffDistinguisher1D(nn.Module): def __init__(self, input_len64): super(SimeckDiffDistinguisher1D, self).__init__() # 输入形状: (batch, 1, input_len) [通道数 长度] self.conv1 nn.Conv1d(in_channels1, out_channels32, kernel_size3, padding1) self.bn1 nn.BatchNorm1d(32) self.pool1 nn.MaxPool1d(kernel_size2) self.conv2 nn.Conv1d(in_channels32, out_channels64, kernel_size3, padding1) self.bn2 nn.BatchNorm1d(64) self.pool2 nn.MaxPool1d(kernel_size2) # 经过两次池化长度从64 - 32 - 16 self.flatten_dim 64 * 16 self.fc1 nn.Linear(self.flatten_dim, 128) self.dropout1 nn.Dropout(0.5) self.fc2 nn.Linear(128, 64) self.dropout2 nn.Dropout(0.3) self.fc3 nn.Linear(64, 1) def forward(self, x): # x: (batch, 1, 64) x self.pool1(F.relu(self.bn1(self.conv1(x)))) x self.pool2(F.relu(self.bn2(self.conv2(x)))) x x.view(-1, self.flatten_dim) x F.relu(self.fc1(x)) x self.dropout1(x) x F.relu(self.fc2(x)) x self.dropout2(x) x torch.sigmoid(self.fc3(x)) # 输出0-1之间的概率 return x设计思路解析1D卷积将比特序列视为一维信号。kernel_size3的卷积核可以捕捉相邻3个比特之间的局部模式这可能对应Simeck轮函数中AND操作涉及的比特关系。批归一化BatchNorm加速训练收敛并提供轻微的正则化效果。Dropout为了防止过拟合在全连接层后加入了Dropout。密码分析数据中可能存在噪声Dropout能增强模型的泛化能力。输出层使用Sigmoid激活函数将输出映射到(0,1)代表样本来自Simeck的概率。3.3 训练策略与超参数调优训练这样的区分器不同于一般的图像分类需要特别关注过拟合问题。def train_model(model, train_loader, val_loader, epochs100, lr0.001): device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) criterion nn.BCELoss() # 二分类交叉熵损失 optimizer torch.optim.Adam(model.parameters(), lrlr) scheduler torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, modemax, factor0.5, patience5) best_val_acc 0.0 for epoch in range(epochs): model.train() train_loss 0.0 for batch_x, batch_y in train_loader: batch_x, batch_y batch_x.to(device), batch_y.to(device) # 调整输入维度: (batch, 64) - (batch, 1, 64) batch_x batch_x.unsqueeze(1) optimizer.zero_grad() outputs model(batch_x) loss criterion(outputs.squeeze(), batch_y) loss.backward() optimizer.step() train_loss loss.item() # 验证阶段 model.eval() val_correct 0 val_total 0 with torch.no_grad(): for batch_x, batch_y in val_loader: batch_x, batch_y batch_x.to(device), batch_y.to(device) batch_x batch_x.unsqueeze(1) outputs model(batch_x) predicted (outputs.squeeze() 0.5).float() val_total batch_y.size(0) val_correct (predicted batch_y).sum().item() val_acc val_correct / val_total scheduler.step(val_acc) # 根据验证集准确率调整学习率 if val_acc best_val_acc: best_val_acc val_acc torch.save(model.state_dict(), best_distinguisher.pth) print(fEpoch {epoch1}: Train Loss: {train_loss/len(train_loader):.4f}, Val Acc: {val_acc:.4f}) print(fBest Validation Accuracy: {best_val_acc:.4f}) return model核心训练技巧学习率调度使用ReduceLROnPlateau当验证集准确率在连续多个epoch不再提升时自动降低学习率。这有助于模型在后期精细调优避免震荡。早停Early Stopping虽然没有在代码中显式写出但在实际训练中我们监控验证集准确率。如果连续10-15个epoch验证集准确率没有提升则停止训练并回滚到最佳模型。这是防止过拟合的最有效手段之一。权重初始化使用PyTorch默认的初始化通常足够但对于更深层的网络可以考虑使用Kaiming初始化。数据量我们为每个差分/轮数组合生成了数千万到上亿对样本。足够大的数据量是模型能够学习到泛化特征而非噪声的前提。4. 实验结果分析与攻击验证4.1 区分器性能评估我们针对Simeck32/64的19轮、20轮、21轮加密分别训练了神经差分区分器。输入差分选择了文献中报道的具有较高概率的差分值例如0x0040。目标轮数训练样本量 (正负)最佳验证集准确率测试集准确率优于随机猜测的幅度19轮10,000,00078.3%77.9%27.9%20轮20,000,00065.1%64.8%14.8%21轮50,000,00055.8%55.5%5.5%结果解读有效性对于19轮和20轮神经网络显著地学习到了有效的差分特征准确率远超随机猜测50%。这证明Simeck在较少轮数下其差分分布确实存在可被神经网络捕捉的非随机性。轮数增加难度剧增随着轮数增加到21轮区分器的准确率急剧下降至接近55.5%。这说明Simeck的扩散性在21轮后已经非常充分差分特征变得极其微弱神经网络也难以有效学习。这也与Simeck设计的安全轮数分析相符。区分器强度78%的准确率意味着给定一个密文对我们的模型能以78%的概率正确判断它是否来自19轮的Simeck。这是一个非常强的区分器可以直接用于区分攻击。4.2 辅助密钥恢复攻击实战我们以19轮区分器辅助攻击22轮Simeck32/64为例演示攻击流程。攻击假设我们拥有一个22轮的Simeck32/64的加密Oracle可以提交明文获取密文。我们的目标是恢复主密钥。攻击步骤数据收集随机生成N个明文对(P_i, P_i‘)满足19轮高概率差分特征对应的输入差分ΔP。向Oracle查询获得对应的22轮密文对(C_i, C_i‘)。这里N需要足够大例如2^20。数据过滤将收集到的所有(C_i, C_i‘)输入到我们训练好的19轮神经区分器中。区分器会对每个密文对输出一个“Simeck概率”得分s_i。筛选高价值对按照得分s_i从高到低排序选取排名前M的密文对例如M 2^15。我们的假设是这些密文对在加密过程的前19轮更有可能遵循了我们已知的高概率差分路径。即使后3轮20-22轮引入了噪声前19轮的“正确”差分传播仍然在密文中留下了统计痕迹并被神经区分器捕捉到。最后一轮密钥猜测对22轮Simeck我们猜测最后1轮第22轮的子密钥sk_2216位。对于筛选出的M个高价值密文对中的每一个 a. 用猜测的sk_22对密文C_i和C_i‘进行解密1轮得到第21轮输出X_i和X_i‘。 b. 计算ΔX X_i ⊕ X_i‘。 c. 检查ΔX是否落在19轮差分特征所预期的输出差分集合内这个集合可以从差分特征表中查得。如果符合则该sk_22猜测的计数器加一。确定正确密钥遍历所有2^16个可能的sk_22后选择计数器值最高的那个作为最可能的sk_22候选。由于我们使用了经过神经区分器筛选的“优质”数据正确密钥的计数器会显著高于错误密钥的计数器信噪比大大提高。密钥扩展与验证利用Simeck的密钥扩展算法从恢复的sk_22逆向推导出主密钥K。再用几个随机的明文-密文对进行验证。效率对比传统差分攻击可能需要遍历所有2^20个数据对并对每个数据对尝试2^16次密钥猜测计算复杂度高。神经辅助攻击先通过神经网络一次前向传播计算量很小筛选出2^15个高价值对。后续的密钥猜测只在这2^15个对上执行。虽然总的数据收集量可能不变但有效数据密度大幅提升使得密钥恢复步骤所需的计算量和数据复杂度显著降低。实操心得神经区分器的“置信度”分数是关键。我们实验发现直接使用排名前10%的数据进行后续攻击成功率比使用随机10%的数据高出数个数量级。这个分数就像一个“数据质量指示器”是传统方法无法提供的。5. 常见问题、挑战与优化方向在实际操作中我们遇到了不少坑也总结出一些优化思路。5.1 训练不稳定与过拟合问题初期训练时模型在训练集上准确率很快达到90%以上但验证集准确率卡在52%-53%几乎随机这是典型的过拟合。排查与解决检查数据泄露确保训练集和验证集的密钥空间是严格分开的。最初我们错误地在所有数据间随机划分导致模型通过记忆特定密钥下的模式来“作弊”。修正后确保用于生成验证集数据的密钥从未在训练集中出现过。增强正则化增加Dropout比率将全连接层的Dropout从0.3提高到0.5。添加L2权重衰减在优化器Adam中设置weight_decay1e-4。使用更简单的模型将CNN层数从4层减少到2层卷积核通道数也相应减少。数据增强在密码分析中直接对密文进行变换如旋转、翻转是不行的会破坏密码关系。但我们可以在特征层面进行轻微扰动例如以极小的概率随机翻转输入特征向量中的几个比特模拟噪声这有助于提升模型的鲁棒性。5.2 区分器准确率瓶颈问题对于21轮以上的区分器准确率提升非常困难始终在55%左右徘徊。分析与尝试特征工程升级除了(C, ΔC)我们尝试加入更多衍生特征如密文C中特定比特位如LSB的值。C和ΔC的汉明重量。将C和C‘分别输入一个共享权重的孪生网络Siamese Network提取特征后再合并。但实验表明对于Simeck简单的(C, ΔC)拼接已经足够复杂特征带来的提升微乎其微反而增加过拟合风险。模型架构探索尝试了ResNet、注意力机制等更复杂的网络。结果发现对于这种低维、结构化的比特数据过于复杂的模型很容易过拟合简单的CNN或MLP表现反而更稳定。模型不是越复杂越好。集成学习训练多个不同初始化或不同结构的区分器对它们的预测结果进行投票或平均。这通常能将准确率提升1-2个百分点但计算成本倍增。根本原因21轮后Simeck的差分特性已经非常接近随机置换信号极其微弱。这很可能触及了当前基于纯密文对深度学习方法的理论上限。要突破这个瓶颈可能需要结合更多的密码学先验知识或者采用不同的学习范式。5.3 从区分攻击到密钥恢复的衔接问题如何将区分器输出的“概率”或“分数”最有效地转化为对密钥恢复步骤的增益我们的策略动态阈值法不固定选取前M个数据而是设定一个概率阈值τ例如0.7。只保留区分器置信度高于τ的数据对进行后续分析。τ可以通过在另一个验证密钥集上微调来确定以最大化密钥恢复成功率。分数加权在最后一轮密钥猜测的计数器中不是简单地“加一”而是加上该数据对的区分器置信度分数。这样高置信度的数据对在投票中拥有更大的权重进一步提高了正确密钥的信噪比。多差分联合训练多个针对不同输入差分ΔP的区分器。在攻击时同时使用这些区分器对同一批密文数据进行评分选取被多个区分器同时认定为“高价值”的数据对。这相当于从多个角度进行交叉验证筛选出的数据质量更高。5.4 项目复现与环境配置建议如果你想复现或在此基础上进行实验以下几点至关重要环境一致性强烈建议使用Anaconda创建独立的Python环境。我们的核心依赖包括pytorch1.9.0,numpy,scikit-learn。使用Docker镜像也是一个好选择可以确保环境完全一致。数据生成是瓶颈纯Python生成上亿对加密数据非常慢。我们最终用Cython重写了Simeck的核心加密函数并将数据生成过程并行化速度提升了近百倍。这是项目前期必须优化的点。实验管理使用wandbWeights Biases或TensorBoard来跟踪每一次实验的超参数、损失曲线和验证准确率。密码分析实验周期长良好的记录是分析结果、调整方向的基础。代码模块化将数据生成、模型定义、训练循环、攻击验证分别写成独立的模块。这样便于单独调试和组合实验。这个项目让我深刻体会到将深度学习应用于密码分析不是简单的“暴力替代”而是一种“增强辅助”。神经网络的强大之处在于其从海量数据中提取复杂、微弱模式的能力而这正是传统密码分析中人力难以企及的。它为我们提供了一种新的、自动化的“特征探测器”。虽然目前还无法撼动全轮密码的安全性但在分析密码的早期轮次强度、评估轻量级密码设计、以及辅助构建更高效的传统攻击方面已经展现出诱人的潜力。未来的方向可能是探索图神经网络GNN对密码算法结构的建模或者将符号推理与神经网络结合向“可解释的AI密码分析”迈进。