側信道分析中的簡單模板攻擊(TA)Python實現(帶測試)

一、模板攻擊原理

模板攻擊(Template Attacks, TA)是一種高效的側信道分析方法,利用密碼設備運行時的物理泄漏信息(如功耗)恢復密鑰。其核心思想是通過建模密鑰相關中間值的泄漏特征,構建攻擊模板。模板攻擊分為兩個階段:
模板構建:在已知密鑰條件下,采集大量功耗曲線并計算中間值(如S盒輸出的漢明重量)。針對每個可能的中間值(0-8),計算其對應的平均功耗曲線作為模板。這些模板表征了不同中間值在硬件上的獨特功耗特征,形成"指紋庫"。
模板匹配:攻擊未知密鑰時,采集目標設備的功耗曲線。對于每條新曲線,計算其與所有模板的歐氏距離。通過最大似然估計,選擇最匹配的模板對應的中間值,進而推導出密鑰字節。此過程實質是將實測功耗與預存模板進行模式匹配。

相較于CPA等分析方法,模板攻擊直接建立中間值與原始功耗的映射關系,避免了對泄漏模型的線性假設。它通過多變量統計分析捕獲更復雜的功耗特征,在相同曲線數量下通常具有更高的攻擊效率,尤其適合對抗防護措施較強的設備。

二、Python實現

運行代碼前先激活Python環境,并執行pip install numpy tqdm trsfile matplotlib安裝需要的庫。另外保存能量跡數據的trsfile文件可以在采集自AES算法無防護純軟件實現的功耗曲線?免費下載。

1. 數據加載與預處理

load_trs_to_dict()函數負責解析.trs格式的功耗文件。該格式專用于存儲側信道數據,包含曲線采樣點和加密參數(如明文)。函數讀取文件頭信息后,按指定范圍提取曲線數據,同時將關聯的明文參數結構化存儲。

get_intermediate_values()計算攻擊所需的中間值矩陣。基于漢明重量泄漏模型,對每條曲線的目標字節位置,計算真實密鑰(已知)和256種假設密鑰的S盒輸出值。通過預計算的漢明重量查找表(HW_ARRAY)高效生成中間值向量,避免重復計算S盒操作。

2. 模板構建與概率計算

build_template()實現核心模板構建邏輯。按漢明重量值0-8分組曲線,計算每組的平均功耗曲線。該函數輸出9×N的模板矩陣(N為采樣點數),每行代表特定中間值對應的功耗特征向量。

ProbCalculator類管理密鑰概率計算。其update()方法計算新曲線與所有模板的歐氏距離平方和(即似然度),累加到密鑰假設向量。隨著曲線增加,正確密鑰的累積似然度將顯著低于錯誤假設。

3. 攻擊執行與評估

single_attack()執行單次模板攻擊。采用分批處理策略,每新增若干曲線即更新密鑰概率。通過np.argsort計算真實密鑰的當前排名(Guess Entropy),排名為0時表示成功恢復密鑰。

guess_entropy()進行魯棒性評估。通過1000次隨機排列實驗,統計不同曲線數量下的成功率(SR)和猜測熵(GE)。關鍵指標包括:SR>0.9所需曲線數、GE降為0所需曲線數,結果自動保存至文本文件。

具體代碼如下:

"""
對AES算法的軟件實現進行簡單模板攻擊(TA)的Python代碼
泄漏模型:S盒輸出的漢明重量
運行前先激活Python環境,執行pip install numpy tqdm trsfile matplotlib命令安裝所需的庫
'AES_POWER_STM32F_NO-PROTECT_60000.trs'是功耗曲線文件,請點擊https://download.csdn.net/download/weixin_43261410/91057055免費下載
查看.trs格式文件介紹請瀏覽https://blog.csdn.net/weixin_43261410/article/details/148737286?fromshare=blogdetail&sharetype=blogdetail&sharerId=148737286&sharerefer=PC&sharesource=weixin_43261410&sharefrom=from_link
"""import os
import numpy as np
from tqdm import tqdm  # 用于顯示進度條
from trsfile import trs_open  # 用于讀取.trs格式的側信道數據文件
import matplotlib.pyplot as plt  # 用于畫圖AES_SBOX = np.array([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
], dtype=np.uint8)# 漢明重量查找表,用于快速計算一個字節的漢明重量(二進制中1的個數)
HW_ARRAY = np.array([0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
])def load_trs_to_dict(trs_file_path: str, start_trace: int = None, end_trace: int = None):"""加載.trs文件到字典結構中參數:trs_file_path: .trs文件路徑start_trace: 起始能量曲線索引(可選)end_trace: 結束能量曲線索引(可選)返回:包含頭信息、能量曲線數據和額外參數的字典"""header, traces, param = {}, [], {}with trs_open(trs_file_path, 'r') as trs_file:# 讀取文件頭信息for key, value in trs_file.get_headers().items():header[key.name] = value# 處理能量曲線范圍number_traces = header['NUMBER_TRACES']start_trace = 0 if start_trace is None else min(start_trace, number_traces - 1)end_trace = number_traces if end_trace is None else min(end_trace, number_traces)header['NUMBER_TRACES'] = end_trace - start_trace# 初始化能量曲線數據數組traces = np.zeros((header['NUMBER_TRACES'], header['NUMBER_SAMPLES']), dtype=np.float32)# 初始化參數數組param = {}for key in trs_file[0].parameters:param_len = len(trs_file[0].parameters[key].value)param[key] = np.zeros((header['NUMBER_TRACES'], param_len), dtype=np.uint8)# 讀取能量曲線數據和參數for i, trace in enumerate(trs_file[start_trace:end_trace]):for key in trace.parameters:param[key][i] = trace.parameters[key].valuetraces[i] = np.array(trace.samples)# 返回結構化數據trs_dict = {"HEADER": header,"TRACES": traces,"PARAM": param}return trs_dictdef get_intermediate_values(plaintext, target_byte, real_key):"""生成中間值矩陣(基于漢明重量模型)參數:plaintext: 明文數組 (N x 16)target_byte: 目標字節位置(0-15)real_key: 真實密鑰字節返回:actual: 真實中間值向量(長度等于能量曲線數量)hypo: 假設中間值矩陣(能量曲線數量 × 256種密鑰假設)"""# 計算真實的S盒輸入actual_sbox_in = plaintext[:, target_byte] ^ real_key# 計算S盒輸出actual_sbox_out = AES_SBOX[actual_sbox_in]# 計算漢明重量作為功耗模型actual = HW_ARRAY[actual_sbox_out]# 生成256種可能的密鑰假設hypo_key = np.array(range(256), np.uint8)# 計算S盒輸入hypo_sbox_in = np.array([pt ^ hypo_key for pt in plaintext[:, target_byte]], np.uint8)# 計算S盒輸出hypo_sbox_out = AES_SBOX[hypo_sbox_in]# 將漢明重量作為功耗模型hypo = HW_ARRAY[hypo_sbox_out]return actual, hypoclass ProbCalculator():"""計算密鑰假設的似然概率"""def __init__(self):# 初始化密鑰假設的似然累加器self.guess_key_likelihood = np.zeros((256))def update(self, traces, hypo, template):"""更新似然值參數:traces: 當前批次的能量曲線hypo: 當前批次的假設中間值template: 構建的模板(9個漢明重量對應的平均功耗曲線)"""# 轉置模板以便后續計算template = template.transpose()# 計算所有密鑰假設的平方差ln_likelihood = np.sum((traces[:, :, None] - template) ** 2, axis=1)# 累加每個密鑰假設的似然值guess_key_likelihood = np.sum([ln_likelihood[i, hypo[i]] for i in range(traces.shape[0])], axis=0)self.guess_key_likelihood = self.guess_key_likelihood + guess_key_likelihooddef __call__(self):"""返回當前似然值向量"""return self.guess_key_likelihooddef build_template(traces, actual):"""構建模板:計算每個漢明重量(0-8)對應的平均功耗曲線參數:traces: 用于構建模板的能量曲線actual: 每條曲線對應的真實漢明重量返回:template: 模板矩陣(9 x 曲線長度)"""template = np.zeros((9, traces.shape[1]))for i in range(9):# 找到所有漢明重量為i的曲線索引index = np.where(actual == i)[0]# 計算這些曲線的平均功耗template[i] = np.mean(traces[index], axis=0)return templatedef single_attack(traces, hypo, template, real_key, index):"""執行單次TA攻擊參數:traces: 能量曲線數據hypo: 假設中間值數據template: 構建的模板real_key: 真實密鑰字節(用于評估攻擊效果)index: 分批處理的索引列表返回:key_rank_list: 每次更新后真實密鑰的排名列表"""# 初始化概率計算器probability = ProbCalculator()key_rank_list = []# 分批處理能量曲線數據for i in range(len(index) - 1):# 獲取當前批次的曲線和中間值start_idx = index[i]end_idx = index[i + 1]current_traces = traces[start_idx:end_idx]current_hypo = hypo[start_idx:end_idx]# 更新密鑰似然值probability.update(current_traces, current_hypo, template)# 獲取當前所有密鑰假設的似然值prob = probability()# 計算密鑰排名(似然值越小排名越高)prob_sort = np.argsort(np.argsort(prob))# 記錄真實密鑰的當前排名key_rank = prob_sort[real_key]key_rank_list.append(key_rank)return key_rank_listdef guess_entropy(traces, hypo, template, real_key, result_path='result.txt', repeat_n=100, sample=500, header='', step=1):"""計算猜測熵和成功率參數:traces: 能量曲線數據hypo: 假設中間值數據template: 構建的模板real_key: 真實密鑰字節result_path: 結果保存路徑repeat_n: 重復實驗次數sample: 每次實驗使用的能量曲線數量header: 結果文件頭部信息step: 能量曲線數量增加的步長"""def get_value_n(arr, value, traces_number, less):"""輔助函數: 獲取達到特定值所需的最少能量曲線數量"""if less:mask = arr <= valueelse:mask = arr >= valuevalid_index = np.cumprod(mask[::-1])[::-1]valid_index = np.where(valid_index)[0]return traces_number[valid_index[0]] if len(valid_index) > 0 else None# 設置分批索引列表index = [i for i in range(0, sample, step)]index.append(sample)# 準備隨機排列key_rank_arr = []permutations = np.zeros((repeat_n, sample), dtype=int)for i in range(repeat_n):permutations[i] = np.random.permutation(traces.shape[0])[:sample]# 多次重復實驗for i in tqdm(range(repeat_n)):traces_random = traces[permutations[i]]hypo_random = hypo[permutations[i]]key_rank_list = single_attack(traces_random, hypo_random, template, real_key, index)key_rank_arr.append(key_rank_list)key_rank_arr = np.array(key_rank_arr)traces_number = np.array(index[1:])# 計算猜測熵guess_entropy = np.mean(key_rank_arr, axis=0)guess_entropy_10 = get_value_n(guess_entropy, 10, traces_number, True)guess_entropy_1 = get_value_n(guess_entropy, 1, traces_number, True)guess_entropy_0 = get_value_n(guess_entropy, 0, traces_number, True)# 計算成功率success_rate = np.mean(key_rank_arr < 10, axis=0)  # 排名小于10被認為攻擊成功success_rate_p9 = get_value_n(success_rate, 0.9, traces_number, False)success_rate_p99 = get_value_n(success_rate, 0.99, traces_number, False)success_rate_1 = get_value_n(success_rate, 1, traces_number, False)# 保存結果到文件mode = 'a' if os.path.exists(result_path) else 'w'with open(result_path, mode, encoding='utf-8') as f:f.write(header)trs_n = ' '.join(f"{int(x)}" for x in traces_number)f.write('traces number: ' + trs_n + '\n')success_rate = ' '.join(f"{x:.2f}" for x in success_rate)f.write('success rate: ' + success_rate + '\n')guess_entropy = ' '.join(f"{x:.2f}" for x in guess_entropy)f.write('guess entropy: ' + guess_entropy + '\n')f.write(f'tips: When guess entropy equals 10, 1, or 0, the corresponding traces number are {guess_entropy_10}, {guess_entropy_1}, and {guess_entropy_0}.\n')f.write(f'tips: When success rate equals 0.9, 0.99, or 1, the corresponding traces number are {success_rate_p9}, {success_rate_p99}, and {success_rate_1}.\n\n')def show_result():"""可視化攻擊結果從result.txt文件中讀取數據并繪制成功率與猜測熵曲線"""result_path = 'result.txt'# 讀取結果文件with open(result_path, 'r', encoding='utf-8') as f:lines = f.readlines()# 初始化數據列表traces = []success_rate = []guess_entropy = []# 解析結果文件for line in lines:if line.startswith('traces number:'):traces = list(map(int, line.split(':')[1].strip().split()))elif line.startswith('success rate:'):success_rate = list(map(float, line.split(':')[1].strip().split()))elif line.startswith('guess entropy:'):guess_entropy = list(map(float, line.split(':')[1].strip().split()))# 檢查是否成功讀取數據if not traces or not success_rate or not guess_entropy:print("Error: Could not find valid data in result file.")return# 創建圖形和雙軸fig, ax1 = plt.subplots(figsize=(12, 6))# 繪制成功率曲線(左軸,藍色)color = 'tab:blue'ax1.set_xlabel('Number of Traces', fontsize=12)ax1.set_ylabel('Success Rate', color=color, fontsize=12)ax1.plot(traces, success_rate, color=color, label='Success Rate', linewidth=2)ax1.tick_params(axis='y', labelcolor=color)ax1.grid(True, linestyle='--', alpha=0.7)ax1.set_ylim(0, 1.05)  # 設置成功率y軸范圍# 創建第二個y軸用于猜測熵ax2 = ax1.twinx()color = 'tab:red'ax2.set_ylabel('Guess Entropy', color=color, fontsize=12)ax2.plot(traces, guess_entropy, color=color, label='Guess Entropy', linewidth=2)ax2.tick_params(axis='y', labelcolor=color)ax2.set_ylim(0, 256)  # 固定猜測熵y軸范圍為0-256# 添加圖例lines1, labels1 = ax1.get_legend_handles_labels()lines2, labels2 = ax2.get_legend_handles_labels()ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper right', fontsize=10)# 添加標題plt.title('TA Attack Performance: Success Rate and Guess Entropy', fontsize=14, pad=20)# 調整布局并保存圖像(同時保存svg格式和png格式)fig.tight_layout()plt.savefig('result.svg', format='svg', bbox_inches='tight')plt.savefig('result.png', dpi=600, bbox_inches='tight')plt.show()def test():"""測試函數:執行完整的模板攻擊流程"""target_byte = 0  # 攻擊的字節位置(0表示第一個字節)traces_build_n = 50000  # 用于構建模板的曲線數量# 主密鑰(16字節)mkey = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10]# 加載能量曲線數據trs_path = 'AES_POWER_STM32F_NO-PROTECT_60000.trs'trs_dict = load_trs_to_dict(trs_path)traces, plaintext = trs_dict['TRACES'], trs_dict['PARAM']['plaintext']# 生成真實中間值向量和假設中間值矩陣actual, hypo = get_intermediate_values(plaintext, target_byte, mkey[target_byte])# 分割數據集:構建模板和攻擊評估traces_build, traces_match = traces[:traces_build_n], traces[traces_build_n:]actual_build, hypo_match = actual[:traces_build_n], hypo[traces_build_n:]# 構建模板template = build_template(traces_build, actual_build)# 設置實驗參數repeat_n = 1000  # 重復次數sample = 100     # 每次實驗使用的能量曲線數量step = 1         # 能量曲線數量增加的步長# 執行猜測熵分析guess_entropy(traces_match, hypo_match, template, mkey[target_byte], repeat_n=repeat_n, sample=sample, step=step)# 可視化結果show_result()if __name__ == '__main__':test()

三、實現結果

攻擊目標為AES首字節密鑰(真實值0x01),使用STM32F3設備的60,000條功耗曲線。前50,000條構建模板,后10,000條用于評估。實驗顯示:當使用17條曲線時,成功率已達90%;當曲線增至26條時,猜測熵降為1,成功率99%以上。

可視化結果呈現兩條關鍵曲線:藍色成功率曲線呈對數增長,40條曲線內趨近100%;紅色猜測熵曲線快速下降,30條曲線后趨近0。這表明模板攻擊對未防護設備極其高效,驗證了漢明重量模型的適用性。

四、總結

本文通過Python實現了針對AES算法的模板攻擊(TA),成功驗證了該方法的有效性。實驗基于STM32F3設備的60,000條功耗曲線,以S盒輸出的漢明重量作為泄漏模型,在32條攻擊曲線內即可完全恢復目標密鑰字節。結果表明,模板攻擊在已知密鑰建模階段充分學習設備的物理泄漏特征后,對未知密鑰的攻擊效率高于DPA、CPA等傳統方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/909774.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/909774.shtml
英文地址,請注明出處:http://en.pswp.cn/news/909774.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AI集群全光交換網絡技術原理與發展趨勢研究

? 引言 隨著人工智能技術的飛速發展&#xff0c;AI訓練集群對網絡互連的帶寬、延遲和能效提出了前所未有的挑戰。全光交換網絡作為一種新興技術&#xff0c;正在成為解決這些挑戰的關鍵方案。 全光交換網絡的基本概念 全光交換網絡(Optical Circuit Switch, OCS)是一種利用…

PHP Swoft2 框架精華系列:Validator 校驗器詳解

文章目錄 校驗器校驗器類型@Validate 注解屬性說明校驗器校驗主要流程系統校驗器每個屬性存儲結構校驗器規則定義,注解、注解解析器定義校驗器注解使用實現一個自定義的校驗器校驗器注解校驗器注解解析器校驗器規則系統校驗器Controller/Action 綁定校驗器校驗器 校驗器是 sw…

MySQL 類型轉換與加密函數深度解析

MySQL 類型轉換與加密函數深度解析 一、類型轉換函數詳解 1. 顯式類型轉換 CAST 函數 CAST(expression AS type)支持類型&#xff1a;BINARY, CHAR, DATE, DATETIME, TIME, DECIMAL, SIGNED [INTEGER], UNSIGNED [INTEGER]示例&#xff1a;SELECT CAST(2023-08-15 AS DATE);…

FPGA基礎 -- Verilog 行為級建模之條件語句

Verilog 的行為級建模&#xff08;Behavioral Modeling&#xff09;中的條件語句&#xff08;Conditional Statements&#xff09;&#xff0c;逐步從基礎到實際工程應用&#xff0c;適合有RTL開發基礎但希望深入行為建模的人。 一、行為級建模簡介 行為級建模&#xff08;Beh…

linux618 NFS web.cn NFS.cn backup.cn

權限問題 推測 ssh root登錄失敗 root192.168.235.100s password: ???????? root192.168.235.100s password: ???????? root192.168.235.100s password: ???????? root192.168.235.100s password: ???????? root192.168.235.100s password: …

氧化鐿:稀土科技的“夜視高手”

氧化鐿&#xff08;Yb?O?&#xff09;是一種重要的稀土氧化物&#xff0c;這種略帶黃色的粉末&#xff0c;既不像黃金那樣耀眼&#xff0c;也不像稀土家族里的“明星”如釹、鋱那樣廣為人知&#xff0c;卻在背后默默支撐著許多高科技產業&#xff0c;特別是在紅外技術領域&am…

class對象【C#】2025復習

對象 西方思想是&#xff1a;復雜的事讓秘書去做就行。老板只需簡單的下達命令。 代碼格式如下 秘書類型 秘書A new 秘書類型(); . 秘書A.開始工作(); // 調用實例對象的方法。 特別注意的是&#xff0c;程序只會用到 秘書A&#xff0c;秘書B&…

Qt程序啟動動畫

一、Qt有3種方式實現程序啟動動畫&#xff08;介紹&#xff09; 1、QSplashScreen 靜態圖片(png、jpg等格式) 2、QMovie 動態圖片(gif格式) 3、QAxWidget 視頻(swf格式) 1.QSplashScreen 靜態圖片(png、jpg等格式) //創建啟動動畫類實例 QSplashScreen splash(QPixmap(&qu…

貪心算法經典問題

目錄 貪心思想 一、Dijkstra最短路問題 問題描述&#xff1a; 貪心策略&#xff1a; 二、Prim 和 Kruskal 最小生成樹問題 Prim 算法&#xff1a; Kruskal 算法&#xff1a; 三、Huffman樹問題 問題描述&#xff1a; 貪心策略&#xff1a; 四、背包問題 問題描述&a…

零知開源——STM32F4實現ILI9486顯示屏UI界面系列教程(一):電子書閱讀器功能

本教程將詳細介紹如何在零知增強板上使用3.5寸ILI9486顯示屏實現電子書閱讀器功能。我們將使用LVGL庫構建用戶界面&#xff0c;并實現翻頁、進度顯示等核心功能。 目錄 一、硬件連接 二、軟件UI組件實現 三、零知IDE配置 四、演示效果 五、常見問題解決 六、總結與擴展 一…

支持selenium的chrome driver更新到137.0.7151.119

最近chrome釋放新版本&#xff1a;137.0.7151.119 如果運行selenium自動化測試出現以下問題&#xff0c;是需要升級chromedriver才可以解決的。 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only s…

架構下的最終瓶頸:數據庫如何破局?

在分布式系統和云原生架構逐漸成熟的當下&#xff0c;我們已能夠靈活擴展計算資源、水平擴展服務節點、拆分業務模塊等。然而&#xff0c;在經歷過多輪架構優化之后&#xff0c;數據庫常常成為系統的“最后瓶頸”。尤其當數據量、并發量、實時性要求劇增時&#xff0c;數據庫即…

湖北理元理律師事務所小微企業債務重組方案:司法與經營的共生邏輯

小微企業債務問題常陷入“救企業還是保老板”的困局。湖北理元理律師事務所為某汽車零部件供應商設計的“經營性債務重組”方案&#xff0c;提供了創新解題思路。 核心矛盾拆解 該企業面臨三重困境&#xff1a; 矛盾類型 具體表現 法律風險等級 擔保鏈危機 老板個人擔保牽…

FastAdmin退出登錄不提示的修改方法

修改退出登錄后的提示行為 在FastAdmin中&#xff0c;默認退出登錄后會顯示"退出成功"的提示信息并跳轉頁面。要實現不顯示提示信息直接跳轉&#xff0c;可以通過以下方式修改&#xff1a; 方法一&#xff1a;修改控制器邏輯 找到application/admin/controller/Log…

工信部發布《中國工業軟件產業發展研究報告(2025)》:PLM壟斷加劇,Ai為國產PLM軟件發展契機

在6月17日上午舉行的2025南京軟件大會開幕式上&#xff0c;工信部電子第五研究所現場發布《中國工業軟件產業發展研究報告&#xff08;2025&#xff09;》&#xff08;以下簡稱《研究報告》&#xff09;&#xff0c;并從工業軟件產業發展現狀、產業發展趨勢&#xff0c;以及我國…

Flutter JSON解析全攻略:使用json_serializable實現高效序列化

引言&#xff1a;為什么我們需要JSON序列化工具&#xff1f; 在現代移動應用開發中&#xff0c;與服務器進行數據交互是必不可少的功能。JSON&#xff08;JavaScript Object Notation&#xff09;作為一種輕量級的數據交換格式&#xff0c;因其易讀性、簡潔性和廣泛支持性&…

shelve模塊的使用

shelve模塊的使用 1. 什么是Shelve2. Shelve模塊的數據存儲與讀取3. Shelve的讀取數據4. Shelve模塊的高級操作_ Shelve的數據更新和刪除5. 刪除操作可以使用del語句&#xff1a;6. Shelve的數據查詢和處理_使用for循環來遍歷Shelve對象中的所有鍵值對&#xff1a;7. Shelve模塊…

python大學校園舊物捐贈系統

目錄 技術棧介紹具體實現截圖系統設計研究方法&#xff1a;設計步驟設計流程核心代碼部分展示研究方法詳細視頻演示試驗方案論文大綱源碼獲取/詳細視頻演示 技術棧介紹 Django-SpringBoot-php-Node.js-flask 本課題的研究方法和研究步驟基本合理&#xff0c;難度適中&#xf…

Python爬蟲實戰:研究eventlet庫相關技術

1. 引言 在當今信息爆炸的時代,網絡上的數據量呈現出指數級增長的趨勢。從海量的網絡信息中獲取有價值的數據并進行分析,對于企業決策、學術研究以及個人興趣等方面都具有重要意義。網絡爬蟲作為一種自動化獲取網頁內容的技術手段,應運而生并得到了廣泛的應用。 網絡爬蟲(…

文字識別接口-智能文本處理-文字提取技術

文字識別接口&#xff0c;顧名思義&#xff0c;就是一種將圖像文字或手寫文字轉換為可編輯文本的技術。文字識別接口&#xff0c;基于深度學習算法與自主ocr核心實現多種場景字符的高精度識別與結構化信息提取&#xff0c;現已被廣泛應用于銀行、醫療、財會、教育等多個領域。 …