輕量級密碼算法PRESENT的C語言實現(無第三方庫)

一、PRESENT算法介紹

PRESENT是一種超輕量級分組密碼算法,由Bogdanov等人在2007年提出,專門為資源受限環境如RFID標簽和傳感器網絡設計。該算法在硬件實現上僅需1570個門等效電路(GE),在保持較高安全性的同時實現了極小的硬件占用空間。PRESENT標準文檔下載地址為:PRESENT: An Ultra-Lightweight Block Cipher。

PRESENT采用SPN結構,分組長度為64位,支持80位和128位兩種密鑰長度。算法包含31輪加密操作,每輪由輪密鑰加、S盒替換和P盒置換三個步驟組成。其中S盒是一個4位輸入輸出的非線性變換,P盒則是一個64位的線性置換層。這種簡潔的結構使得PRESENT在硬件實現上非常高效。

安全性方面,PRESENT設計時充分考慮了差分分析和線性分析等攻擊方法。通過理論證明,任何5輪差分特征至少包含10個活躍S盒,25輪差分特征的概率上限為\frac{1}{2^{100}},線性分析則需約2^{84}個已知明文才能成功攻擊,這些安全指標完全滿足輕量級應用場景的需求。

二、C語言實現

我們提供的C代碼完整實現了PRESENT-80算法,包括加密、解密和密鑰擴展功能。實現中定義了幾個關鍵組件:

首先定義了算法核心的S盒和P盒置換表。S盒是一個16元素的查找表,實現非線性變換;P盒則定義了64位狀態的置換規則。代碼中同時包含了正向和反向的S盒/P盒,分別用于加密和解密過程。

present_permutation函數實現了通用的置換操作,根據傳入的置換規則表對輸入數據進行重排。這個函數被P盒置換(PSub)和逆P盒置換(InvPSub)復用,通過不同的置換規則表實現不同的置換效果。

密鑰擴展部分(present_key_expansionkeyUpdate)實現了80位主密鑰到32個輪密鑰的派生過程。每輪密鑰通過旋轉、S盒變換和輪計數器異或等操作生成,確保了密鑰材料的充分混淆。

加密過程(present_encrypt_block)遵循算法標準結構:31輪迭代處理,每輪包含輪密鑰加、S盒替換和P盒置換,最后再進行一次輪密鑰加作為后處理。解密過程(present_decrypt_block)則逆向執行這些操作。

代碼中還包含了四個測試用例,驗證了實現與標準測試向量的正確性。這些測試用例來自于標準文檔,覆蓋了全零、全一的明文和密鑰組合,能夠有效驗證算法的基本功能。

#include<stdio.h>
#include<stdint.h>static const uint8_t present_sbox[16] = {0xC, 0x5, 0x6, 0xB, 0x9, 0x0, 0xA, 0xD, 0x3, 0xE, 0xF, 0x8, 0x4, 0x7, 0x1,0x2};
static const uint8_t present_inv_sbox[16] = {0x5, 0xE, 0xF, 0x8, 0xC, 0x1, 0x2, 0xD, 0xB, 0x4, 0x6, 0x3, 0x0, 0x7, 0x9,0xA};static const uint8_t present_pbox[64] = {0, 4, 8, 12, 16, 20, 24, 28,32, 36, 40, 44, 48, 52, 56, 60,1, 5, 9, 13, 17, 21, 25, 29,33, 37, 41, 45, 49, 53, 57, 61,2, 6, 10, 14, 18, 22, 26, 30,34, 38, 42, 46, 50, 54, 58, 62,3, 7, 11, 15, 19, 23, 27, 31,35, 39, 43, 47, 51, 55, 59, 63
};static const uint8_t present_inv_pbox[64] = {0, 16, 32, 48, 1, 17, 33, 49,2, 18, 34, 50, 3, 19, 35, 51,4, 20, 36, 52, 5, 21, 37, 53,6, 22, 38, 54, 7, 23, 39, 55,8, 24, 40, 56, 9, 25, 41, 57,10, 26, 42, 58, 11, 27, 43, 59,12, 28, 44, 60, 13, 29, 45, 61,14, 30, 46, 62, 15, 31, 47, 63
};void present_permutation(const uint8_t *src, uint8_t *res, const uint8_t *rule, uint8_t len) {uint8_t dest_pos, dest_bit;for (uint8_t i = 0; i < len; i++) {res[i] = 0;for (uint8_t j = 0; j < 8; j++) {dest_pos = rule[8 * i + j];dest_bit = (src[dest_pos >> 3] >> (7 - (dest_pos & 0x07))) & 0x01;res[i] = res[i] | (dest_bit << (7 - j));}}
}void addRoundKey(uint8_t *state, const uint8_t *ikey, uint8_t r) {for (uint8_t i = 0; i < 8; i++) {state[i] ^= ikey[8 * r + i];}
}void SubByte(uint8_t *state) {for (int i = 0; i < 8; i++) {uint8_t s0 = present_sbox[state[i] & 0xf];uint8_t s1 = present_sbox[state[i] >> 4];state[i] = s0 | s1 << 4;}
}void InvSubByte(uint8_t *state) {for (int i = 0; i < 8; i++) {uint8_t s0 = present_inv_sbox[state[i] & 0xf];uint8_t s1 = present_inv_sbox[state[i] >> 4];state[i] = s0 | s1 << 4;}
}void PSub(uint8_t *state) {uint8_t tmp[8] = {0};for (uint8_t i = 0; i < 8; i++) {tmp[i] = state[i];}present_permutation(tmp, state, present_pbox, 8);
}void InvPSub(uint8_t *state) {uint8_t tmp[8] = {0};for (uint8_t i = 0; i < 8; i++) {tmp[i] = state[i];}present_permutation(tmp, state, present_inv_pbox, 8);
}void keyUpdate(uint8_t *key, uint8_t rc) {uint8_t k[10] = {key[7] << 5 | key[8] >> 3, key[8] << 5 | key[9] >> 3, key[9] << 5 | key[0] >> 3, key[0] << 5 | key[1] >> 3,key[1] << 5 | key[2] >> 3,key[2] << 5 | key[3] >> 3, key[3] << 5 | key[4] >> 3, key[4] << 5 | key[5] >> 3, key[5] << 5 | key[6] >> 3,key[6] << 5 | key[7] >> 3};k[0] = (k[0] & 0xf) | (present_sbox[k[0] >> 4] << 4);rc = rc & 0x1f;k[7] ^= rc >> 1;k[8] ^= rc << 7;for (uint8_t i = 0; i < 10; i++) {key[i] = k[i];}
}void present_key_expansion(const uint8_t *mkey, uint8_t *ikey) {uint8_t mk[10];for (uint8_t i = 0; i < 10; i++) {mk[i] = mkey[i];ikey[i] = mkey[i];}for (uint8_t i = 1; i < 32; i++) {keyUpdate(mk, i);for (uint8_t j = 0; j < 8; j++) {ikey[8 * i + j] = mk[j];}}
}void present_encrypt_block(const uint8_t *plain, uint8_t *cipher, uint8_t *ikey) {uint8_t state[8];for (uint8_t i = 0; i < 8; i++) {state[i] = plain[i];}for (int r = 1; r < 32; r++) {addRoundKey(state, ikey, r - 1);SubByte(state);PSub(state);}addRoundKey(state, ikey, 31);for (uint8_t i = 0; i < 8; i++) {cipher[i] = state[i];}
}void present_decrypt_block(const uint8_t *cipher, uint8_t *plain, uint8_t *ikey) {uint8_t state[8];for (uint8_t i = 0; i < 4; i++) {state[i] = cipher[3 - i];state[i + 4] = cipher[7 - i];}for (int i = 31; i >= 1; i--) {addRoundKey(state, ikey, i);InvPSub(state);InvSubByte(state);}addRoundKey(state, ikey, 0);for (uint8_t i = 0; i < 4; i++) {plain[i] = state[3 - i];plain[i + 4] = state[7 - i];}
}void print_data(uint8_t *data, int data_len, const char *name) {printf("\t%s: ", name);for (int i = 0; i < data_len; i++) {printf("%02x ", data[i]);}printf("\n");
}void test_case1() {printf("test case 1:\n");uint8_t mkey[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};uint8_t plain[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};uint8_t ikey[256] = {0};uint8_t cipher[8] = {0};print_data(plain, 10, "plaintext");print_data(mkey, 8, "mkey");present_key_expansion(mkey, ikey);present_encrypt_block(plain, cipher, ikey);print_data(cipher, 8, "ciphertext");
}void test_case2() {printf("test case 2:\n");uint8_t mkey[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};uint8_t plain[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};uint8_t ikey[256] = {0};uint8_t cipher[8] = {0};print_data(plain, 10, "plaintext");print_data(mkey, 8, "mkey");present_key_expansion(mkey, ikey);present_encrypt_block(plain, cipher, ikey);print_data(cipher, 8, "ciphertext");
}void test_case3() {printf("test case 3:\n");uint8_t mkey[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};uint8_t plain[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};uint8_t ikey[256] = {0};uint8_t cipher[8] = {0};print_data(plain, 10, "plaintext");print_data(mkey, 8, "mkey");present_key_expansion(mkey, ikey);present_encrypt_block(plain, cipher, ikey);print_data(cipher, 8, "ciphertext");
}void test_case4() {printf("test case 4:\n");uint8_t mkey[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};uint8_t plain[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};uint8_t ikey[256] = {0};uint8_t cipher[8] = {0};print_data(plain, 10, "plaintext");print_data(mkey, 8, "mkey");present_key_expansion(mkey, ikey);present_encrypt_block(plain, cipher, ikey);print_data(cipher, 8, "ciphertext");
}int main() {test_case1();test_case2();test_case3();test_case4();return 0;
}

?

三、總結

PRESENT算法通過精心設計的簡潔結構,在資源受限環境中實現了安全性與效率的良好平衡。其硬件友好的特性使其成為物聯網安全領域的理想選擇。提供的C語言實現完整展現了算法的工作流程,模塊化設計清晰,便于理解和移植。

這種輕量級密碼算法代表了密碼學在物聯網時代的發展方向,即在有限資源下提供足夠的安全保障。隨著物聯網設備的普及,類似PRESENT這樣的高效密碼算法將發揮越來越重要的作用。我們的代碼實現不僅可用于學術研究,也可應用于實際的嵌入式安全解決方案中。

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

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

相關文章

if的簡化書寫,提高執行效率

很多時候可能有下面判斷 if(a0) {b1;} else if(a1) {b0;} 就是ba的反向值&#xff1a; a0;b1&#xff1b; a1;b0; 這時&#xff0c;可以簡化如下&#xff1a; ba^1 使用異或&#xff0c;程序更簡潔&#xff0c;執行效率也更高 其他的也可以類似使用按位異或優化代碼

Vim 調用外部命令學習筆記

Vim 外部命令集成完全指南 文章目錄 Vim 外部命令集成完全指南核心概念理解命令語法解析語法對比 常用外部命令詳解文本排序與去重文本篩選與搜索高級 grep 搜索技巧文本替換與編輯字符處理高級文本處理編程語言處理其他實用命令 范圍操作示例指定行范圍處理復合命令示例 實用技…

bash挖礦木馬事件全景復盤與企業級防御實戰20250612

&#x1f427; CentOS “-bash 挖礦木馬” 事件全景復盤與企業級防御實戰 ?? 作者&#xff1a;Narutolxy | &#x1f4c5; 日期&#xff1a;2025-06-12 | &#x1f3f7;? 標簽&#xff1a;Linux 安全、應急響應、運維加固、實戰復盤 &#x1f4d8; 內容簡介 本文是一場真實…

「Linux中Shell命令」Shell命令基礎

知識點詳細解析 Shell簡介 Shell是Linux操作系統系統中用戶與操作系統內核交互的接口。它既是命令解釋器,負責接收用戶輸入的命令并將其轉換為內核能夠理解的指令,也是一種腳本編程語言。作為Linux操作系統的重要組成部分,Shell扮演著用戶與系統內核之間的"中間人"…

202557讀書筆記|《夢里花落知多少(輕經典)》——有你在的地方才最美

《夢里花落知多少&#xff08;輕經典&#xff09;》作者三毛&#xff0c;物極必反&#xff0c;陰晴圓缺&#xff0c;小滿即萬全么&#xff1f;因為幸福過于滿溢。所以幸福被收走了。 沒有看過太多三毛的作品&#xff0c;給我的感覺她是很敏感&#xff0c;多愁善感及沒有安全感…

對象映射 C# 中 Mapster 和 AutoMapper 的比較

Mapster和AutoMapper是C#領域兩大主流對象映射庫&#xff0c;各具特色。Mapster以高性能著稱&#xff0c;使用表達式樹實現零反射映射&#xff0c;首次編譯后執行效率極高&#xff0c;適合對性能敏感的場景&#xff1b;AutoMapper則提供更豐富的功能集&#xff0c;如條件映射和…

QEMU源碼全解析 —— 塊設備虛擬化(26)

接前一篇文章:QEMU源碼全解析 —— 塊設備虛擬化(25) 本文內容參考: 《趣談Linux操作系統》 —— 劉超,極客時間 《QEMU/KVM源碼解析與應用》 —— 李強,機械工業出版社 Virt

微軟PowerBI考試 PL300-選擇 Power BI 模型框架【附練習數據】

微軟PowerBI考試 PL300-選擇 Power BI 模型框架 20 多年來&#xff0c;Microsoft 持續對企業商業智能 (BI) 進行大量投資。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于無數企業使用的成熟的 BI 數據建模技術。 同樣的技術也是 Power BI 數據…

RED DA認證-EN18031網絡安全常見問題以及解答

Q&#xff1a;RED DA是否對所有無線模塊和設備強制要求&#xff1f; A&#xff1a;是的&#xff0c;RED DA適用于歐盟境內銷售的所有無線設備&#xff0c;包括WWAN、藍牙或Wi-Fi模塊。唯一例外是GNSS模塊&#xff08;僅支持接收功能&#xff0c;無需認證&#xff09;。 Q&…

騰訊開源 ovCompose 跨平臺框架:實現一次跨三端(Android/iOS/鴻蒙)

在移動應用開發領域&#xff0c;跨平臺技術一直是開發者們追求的目標&#xff0c;它能夠幫助企業降低開發成本、提高開發效率&#xff0c;同時保證應用在不同平臺上的一致性體驗。2025 年 6 月 3 日&#xff0c;騰訊視頻團隊迎來了一個重要的里程碑 —— 正式發布 ovCompose 跨…

對3D對象進行形變分析

1&#xff0c;目的 分析3D實例對象相對標準參照物的形變。 一般用于質地較軟的材質&#xff08;例如橡膠&#xff0c;布料&#xff09;查找&#xff0c;檢查等。 標準參考模型 需匹配的實例&#xff1a; 形變后的模型&#xff1a;* 形變后的模型&#xff1a; 實例形變后的…

寶塔面板WordPress中使用Contact Form 7插件收不到郵件的解決方法

如果是寶塔面板的環境下&#xff0c;在WordPress中使用Contact Form 7插件提交表單時顯示成功&#xff0c;但郵箱未收到郵件&#xff0c;可能是由于服務器郵件功能配置問題。以下是幾種常見解決方法&#xff1a; 1. 檢查郵件發送方式 默認情況下&#xff0c;Contact Form 7 使…

Android中的DX、D8、R8

Kotlin 版本所需的 AGP、D8 和 R8 版本 :https://developer.android.google.cn/build/kotlin-support?hlzh_cn R8&#xff1a;https://developer.android.google.cn/tools/retrace?hlzh_cn D8&#xff1a;https://developer.android.google.cn/tools/d8?hlzh_cn 如上圖&…

通義靈碼 AI IDE 上線!智能體+MCP 從手動調用工具過渡到“AI 主動調度資源”

告訴大家一個好消息&#xff0c;通義靈碼發布了 AI 編程 IDE &#xff1a;Lingma IDE &#xff0c;你沒看錯&#xff0c;通義靈碼也推出了自己的 AI IDE 客戶端&#xff0c;不是 AI 編程插件&#xff0c;是 IDE 。 Lingma IDE 是基于 VS Code 開源版本構建的智能代碼編輯器&am…

快速解決軟件測試的邏輯方法運用

在軟件測試過程中&#xff0c;遇到復雜問題時&#xff0c;如何快速定位和解決&#xff1f;關鍵在于運用邏輯方法&#xff0c;系統化地分析問題、設計測試用例、優化測試流程。本文將介紹幾種高效的邏輯方法&#xff0c;幫助測試工程師提升效率&#xff0c;減少盲測和重復勞動。…

楓清科技攜手中化信息挖掘實現AI高價值場景應用,打通智能化“最后一公里”

近日&#xff0c;中國中化控股有限責任公司&#xff08;以下簡稱“中國中化”&#xff09;發布“人工智能”專項行動推進方案&#xff0c;標志著其全面深化人工智能戰略布局、全力支撐“數智中化”建設進入加速落地階段。作為集團智能化轉型的核心支撐單位&#xff0c;中國中化…

Yolov5.6增加注意力機制+ByterTrack:目標檢測與跟蹤

簡介&#xff1a;本項目使用ESP32-CAM采集圖像上傳至上位機進行手部目標檢測與追蹤&#xff0c;使用了YOLOv5.6&#xff08;注意力機制ECA,CBAM&#xff09;ByteTrack 博主同款迅雷鏈接&#xff1a; 鏈接&#xff1a;https://pan.xunlei.com/s/VOSO1EIzmXhBb_BIKM58cM5cA1# 提…

C++進階—C++中的繼承

第一章&#xff1a;繼承的概念及定義 1.1繼承的概念 繼承(inheritance)機制是面向對象程序設計使代碼可以復用的最重要的手段&#xff0c;它允許程序員在保持原有類特性的基礎上進行擴展&#xff0c;增加功能&#xff0c;這樣產生新的類&#xff0c;稱派生類。繼承呈現了面向…

力扣Hot100每日N題(11~14)

200. 島嶼數量 BFS或DFS class Solution {private int[] dx {0, 0, 1, -1};private int[] dy {1, -1, 0, 0};int ans 0, n, m;void dfs(char[][] grid, int x, int y){if(x < 0 || y < 0 || x > n || y > m || grid[x][y] 0) return;grid[x][y] 0;for(int i…

人工智能 倒底是 智能 還是 智障?

假設有如下哈希運算的過程和結果&#xff0c;然后讓人工智能根據初始條件和最終結果的最后幾個字符推理出中間過程。 yw "123456" salt "a1b2c3d4e5f6" sda256(saltsha1(md5(yw.encode)salt)) 1c5852fa5d3c450621c17b9ba87ffdab8d336b16f015b4a10cffc945…