赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三

admin 2025年6月28日11:25:31评论2 views字数 10401阅读34分40秒阅读模式

零、发过了咋又发一遍,没活硬整是吧

最近后台有不少朋友在问,第九届密码数学挑战赛那篇文章里的某些细节能不能讲清楚一点,比如实验环境是怎么搭的、数据怎么选的、降噪处理用的具体方法是什么等等。

其实最初发这篇文章的时候,我们刚做完比赛,还处在那种“终于交了稿”的状态,很多过程是照着实验记录顺手整理的,没想着写得多细。现在距离那场比赛也过去一阵了,刚好最近第十届挑战赛报名临近,看到有很多同学在准备,也确实有不少人来问,就想着把那篇文章重新整理一下。

这次没有大改,只是把原来没讲清楚的部分补了一下。比如实验时用的硬件规格、降噪是怎么做的(我们用的是基于明文类别的均值滤波),以及一些中间数据的补全,还有部分图表也统一格式重新排了版。虽然是同一个题目,但这版的内容比原来更完整、也更容易复现。

如果你已经读过之前的版本,可以直接跳到你关心的部分看看有没有更新;如果你是第一次看到,希望这篇补充过的内容能对你有点帮助。不管你是准备比赛,还是单纯对侧信道分析感兴趣,都欢迎来交流。

一、密码数学挑战赛题目分析

赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三

二、赛题描述

给定采集得到关于 AES 密码芯片运行过程中的泄露样本与对应的明文信息,该泄露样本对应于 AES密码芯片执行第一轮第一个 S盒输出值。该 AES密码芯片信息泄露无法使用汉明重量模型准确刻画其信息泄露特征。问题:基于给定泄露样本与对应明文信息编写能能量分析攻击代码恢复 AES 密码芯片所使用密钥第一字节值。提示:该问题主要考察参赛人员利用统计工具准确挖掘给定数据的信息特征的能力,参赛人员可以借助概率密度函数、相关系数、互信息、KS 检测等统计工具或深度学习领域 CNN自动识别工具实现特征提取与密钥恢复的目标。

三、赛题分析

赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三

题目给了六组三对数据,分别对应低中高噪的plain和leakage。其中:

Plain:在AES加密过程中,"plain"通常指的是明文数据,即在加密之前原始的、未经加密的数据。在侧信道攻击中,攻击者的目标是尝试从加密过程中的物理或电磁泄漏中恢复出明文信息。

Leakage:在侧信道攻击中,"leakage"指的是加密设备在执行加密操作时无意中泄露的信息。这种泄露可能包括功耗、电磁辐射、计算时间等,它们可以被攻击者用来推断加密密钥或明文数据。"Leakage"可以进一步细分为不同的级别,如"high"、"medium"和"low"。

因本人知识背景局限性,只针对AES侧信道攻击恢复明文的方法做CPA攻击、DPA攻击、互信息代码演示,以求恢复明文信息。

3.1.赛题数据

赛题数据可通过全国高校密码数学挑战赛官方网站获取。

3.2.赛题代码及结果

3.2.1.CPA攻击

CPA攻击,全称为Correlation Power Analysis(相关功耗分析),是一种侧信道攻击技术,主要用于分析加密设备在执行加密算法时的功耗模式。通过测量设备在处理不同数据时的功耗变化,攻击者可以推断出加密密钥或其他敏感信息。

import numpy as np
from scipy.io import loadmat
from scipy.stats import pearsonr
import matplotlib.pyplot as plt
# 加载低噪声数据
plain_low = loadmat('plain_low.mat')['plain']
leakage_low = loadmat('leakage_low.mat')['leakage']
# 确保数据在0到255范围内
plain_low = plain_low % 256
# AES S盒
sbox = [
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
]
# 汉明重量函数
def hamming_weight(n):
return bin(n).count("1")
# 构建假设功耗函数
def hypothetical_leakage(plain, key_guess):
    num_traces = plain.shape[0]
    hypothetical = np.zeros(num_traces)

for i in range(num_traces):
        index = (plain[i, 0] ^ key_guess) % 256  # 确保索引在0-255范围内
        intermediate_value = sbox[index]
        hypothetical[i] = hamming_weight(intermediate_value)

return hypothetical
# 计算相关性函数
def calculate_correlation(leakage, hypothetical):
    num_samples = leakage.shape[1]  # 获取每条功耗曲线的采样点数量
    correlation = np.zeros(num_samples)  # 初始化相关系数数组

for i in range(num_samples):
# 计算每个采样点的相关系数
        correlation[i] = pearsonr(leakage[:, i], hypothetical)[0]

return correlation
# 绘制相关系数曲线函数
def plot_correlation(keys, correlations, title):
    plt.figure(figsize=(10, 6))
    plt.plot(keys, correlations)
    plt.title(title)
    plt.xlabel('Key Guess')
    plt.ylabel('Max Correlation')
    plt.grid(True)
    plt.show()
# 恢复密钥字节函数
def cpa_attack(plain, leakage):
    num_guesses = 256
    max_correlation = np.zeros(num_guesses)

for key_guess in range(num_guesses):
        hypothetical = hypothetical_leakage(plain, key_guess)
        correlation = calculate_correlation(leakage, hypothetical)
        max_correlation[key_guess] = np.max(np.abs(correlation))

    best_guess = np.argmax(max_correlation)
    keys = np.arange(num_guesses)
    plot_correlation(keys, max_correlation, 'Correlation vs Key Guess')
return best_guess
# 执行CPA攻击(低噪声)
recovered_key_low = cpa_attack(plain_low, leakage_low)
print(f'恢复的密钥字节(低噪声):{recovered_key_low}')
# 加载中噪声数据
plain_medium = loadmat('plain_medium.mat')['plain']
leakage_medium = loadmat('leakage_medium.mat')['leakage']
# 确保数据在0到255范围内
plain_medium = plain_medium % 256
# 执行CPA攻击(中噪声)
recovered_key_medium = cpa_attack(plain_medium, leakage_medium)
print(f'恢复的密钥字节(中噪声):{recovered_key_medium}')
# 加载高噪声数据
plain_high = loadmat('plain_high.mat')['plain']
leakage_high = loadmat('leakage_high.mat')['leakage']
# 确保数据在0到255范围内
plain_high = plain_high % 256
# 执行CPA攻击(高噪声)
recovered_key_high = cpa_attack(plain_high, leakage_high)
print(f'恢复的密钥字节(高噪声):{recovered_key_high}')
赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三
赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三
赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三

3.2.2.互信息

使用互信息进行能量分析攻击

互信息(Mutual Information)是一种衡量两个随机变量之间相互依赖程度的统计量。在侧信道分析中,我们可以使用互信息来衡量假设密钥和泄漏样本之间的关系,从而恢复密钥。

密钥恢复:在具体实施过程中,攻击者基于初始密钥的每一个可能值,使用选择函数计算相应的中间值,并将泄漏信息和中间值进行离散化处理。然后计算不同密钥猜测下泄漏信息和中间值之间的互信息。互信息值最大的密钥猜测即为攻击者推断的真实密钥。

import numpy as np
from scipy.io import loadmat
from sklearn.metrics import mutual_info_score
from sklearn.preprocessing import KBinsDiscretizer
import matplotlib.pyplot as plt

# 加载数据
plain_low = loadmat('plain_low.mat')['plain']
leakage_low = loadmat('leakage_low.mat')['leakage']
plain_medium = loadmat('plain_medium.mat')['plain']
leakage_medium = loadmat('leakage_medium.mat')['leakage']
plain_high = loadmat('plain_high.mat')['plain']
leakage_high = loadmat('leakage_high.mat')['leakage']

# 确保数据在0到255范围内
plain_low = plain_low % 256
plain_medium = plain_medium % 256
plain_high = plain_high % 256

# 确保数据形状正确
if plain_low.ndim == 1:
    plain_low = plain_low.reshape(-1, 1)
if plain_medium.ndim == 1:
    plain_medium = plain_medium.reshape(-1, 1)
if plain_high.ndim == 1:
    plain_high = plain_high.reshape(-1, 1)

# AES S盒
sbox = [
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
]

# 汉明重量函数
def hamming_weight(n):
return bin(n).count("1")

# 构建假设功耗函数
def hypothetical_leakage(plain, key_guess):
    num_traces = plain.shape[0]
    hypothetical = np.zeros(num_traces)

for i in range(num_traces):
        intermediate_value = sbox[plain[i, 0] ^ key_guess]
        hypothetical[i] = hamming_weight(intermediate_value)

return hypothetical

# 计算互信息
def calculate_mutual_information(leakage, hypothetical):
    num_samples = leakage.shape[1]  # 获取每条功耗曲线的采样点数量
    mutual_information = np.zeros(num_samples)  # 初始化互信息数组

# 使用KBinsDiscretizer对泄露样本进行离散化处理
    discretizer = KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='uniform', subsample=None)
    leakage_discrete = discretizer.fit_transform(leakage)

for i in range(num_samples):
# 计算每个采样点的互信息
        mutual_information[i] = mutual_info_score(leakage_discrete[:, i], hypothetical)

return mutual_information

# 绘制互信息曲线函数
def plot_mutual_information(keys, mutual_informations, title):
    plt.figure(figsize=(10, 6))
    plt.plot(keys, mutual_informations)
    plt.title(title)
    plt.xlabel('Key Guess')
    plt.ylabel('Max Mutual Information')
    plt.grid(True)
    plt.show()

# 恢复密钥字节函数
def mia_attack(plain, leakage):
    num_guesses = 256
    max_mutual_information = np.zeros(num_guesses)

for key_guess in range(num_guesses):
        hypothetical = hypothetical_leakage(plain, key_guess)
        mutual_information = calculate_mutual_information(leakage, hypothetical)
        max_mutual_information[key_guess] = np.max(mutual_information)

    best_guess = np.argmax(max_mutual_information)
    keys = np.arange(num_guesses)
    plot_mutual_information(keys, max_mutual_information, 'Mutual Information vs Key Guess')
return best_guess

# 执行MIA攻击(低噪声)
recovered_key_low = mia_attack(plain_low, leakage_low)
print(f'恢复的密钥字节(低噪声):{recovered_key_low}')

# 执行MIA攻击(中噪声)
recovered_key_medium = mia_attack(plain_medium, leakage_medium)
print(f'恢复的密钥字节(中噪声):{recovered_key_medium}')

# 执行MIA攻击(高噪声)
recovered_key_high = mia_attack(plain_high, leakage_high)
print(f'恢复的密钥字节(高噪声):{recovered_key_high}')

赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三
赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三
赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三

4.实验结果分析

实验运行环境如下: Windows 10 Pycharm 2024.1 Intel Core i7-9700 RAM:16G ROM:512G 初步实验时,我们首先对CPA、DPA、MIA和PDF分三种方式都进行了尝试,经过证明4种方式在不考虑选取条数的情况下都可以成功攻击出密钥,对于每种方法,我们选取不同的条数分别进行若干次,下面是我们分别从能量迹使用数量、破解密钥速度分析实验结果。首先是对于低噪声破解不同的方法选取不同的条数进行1000时的成功率(表格中第一个数据为成功率,第二个数据为平均一次攻击的时间):

表1 低噪下不同的方法选取不同的条数实验结果

CPA
DPA(随机选取 m*n 条)
MIA
PDF
m=90
85.90%
57.30%
2.30%
0.80%
n=3
0.1860 秒
0.0307 秒
0.6193 秒
0.3004 秒
m=91
85.30%
55.80%
2.30%
1.10%
n=3
0.1846 秒
0.0302 秒
0.6270 秒
0.6093 秒
m=92
87.70%
55.70%
3.30%
1.20%
n=3
0.1869 秒
0.0308 秒
0.6365 秒
0.4806 秒
m=93
90.20%
58.60%
3.70%
1.20%
n=3
0.1870 秒
0.0309 秒
0.6299 秒
0.5702 秒

表2 中噪下不同的方法选取不同的条数实验结果

CPA
DPA(随机选取 m*n 条)
MIA
PDF
m=110
81.20%
53.70%
1.30%
0.30%
n=4
0.2016 秒
0.0462 秒
0.8261 秒
4.2723 秒
m=120
86.60%
58.80%
1.60%
0.30%
n=4
0.2029 秒
0.0496 秒
0.9163 秒
4.8732 秒
m=130
89.60%
62.50%
1.80%
0.040%
n=4
0.2093 秒
0.0524 秒
0.9075 秒
5.1960 秒
m=140
91.50%
62.50%
1.80%
0.50%
n=4
0.2141 秒
0.0540 秒
0.9851 秒
5.3591 秒

表3 高噪下不同的方法选取不同的条数实验结果

CPA
DPA(随机选取 m*n 条)
MIA
PDF
m=160
86.50%
46.60%
1.50%
0.40%
n=10
0.2910 秒
0.1371 秒
2.2840 秒
10.9931 秒
m=170
87.20%
48.40%
1.50%
0.50%
n=10
0.3009 秒
0.1447 秒
2.5422 秒
13.3591 秒
m=175
89.00%
52.20%
1.60%
0.50%
n=10
0.3058 秒
0.1484 秒
2.8413 秒
15.6790 秒
m=180
90.70%
52.80%
1.70%
0.60%
n=10
0.3068 秒
0.1543 秒
3.6823 秒
16.3692 秒
m=190
93.30%
56.60%
1.80%
0.50%
n=10
0.3166 秒
0.1596 秒
3.9538 秒
17.5860 秒

从中我们可以发现,采用这种数据处理方法之后,CPA的实现效果在四种方法中达到最好,因此对于CPA我们还进行了多次数据尝试,具体结果如下图所示:

表 4 固定 n=2 时 CPA 所得成功率

m
n
num
成功率
130
2
260
86.6
135
2
270
86.7
140
2
280
89.2
145
2
290
90.3
150
2
300
90.4
155
2
310
91.6

表 5 固定 n=3 时 CPA 所得成功率

m
n
num
成功率
90
3
270
85.9
95
3
285
88.1
100
3
300
90.1
105
3
315
90.1
115
3
345
95

表 6 固定 n=4 时 CPA 所得成功率

m
n
num
成功率
70
4
280
82.7
74
4
296
85.9
76
4
304
87
78
4
312
89.6
80
4
320
90.5
82
4
328
90.9

表 7 固定 n=5 时 CPA 所得成功率

m
n
num
成功率
60
5
300
85.4
65
5
325
88.8
67
5
335
89
68
5
340
90.8
70
5
350
91.7

原文始发于微信公众号(攻防SRC):赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月28日11:25:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   赛题解析之第九届(2024)全国高校密码数学挑战赛赛题三https://cn-sec.com/archives/4206550.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息