李若曦
(華東理工大學(xué) 上海市 200237)
當(dāng)今世界處于網(wǎng)絡(luò)全球化的時(shí)代,互聯(lián)網(wǎng)時(shí)代最顯著、最重要的特征就是信息的發(fā)送、傳輸和獲取。傳輸過程中,信息面臨著信息泄露、完整性破壞、拒絕服務(wù)、未授權(quán)訪問[1]等重重安全威脅,每一種潛在威脅都會使信息的傳輸出現(xiàn)錯(cuò)誤進(jìn)而傳輸失敗。網(wǎng)絡(luò)使用者冒充其他使用者,對文件進(jìn)行收發(fā),對所收到的信息進(jìn)行更改。此種問題一旦出現(xiàn)會影響網(wǎng)絡(luò)整體安全性,出現(xiàn)混亂現(xiàn)象,尤其是在銀行、政府機(jī)關(guān)等社會大型服務(wù)系統(tǒng)中,任何節(jié)點(diǎn)數(shù)據(jù)的錯(cuò)誤都會導(dǎo)致無可估量的損失。怎樣確保信息安全、完整就成為了亟待解決的關(guān)鍵問題。借助數(shù)字簽名技術(shù),可以有效解決驗(yàn)證數(shù)據(jù)完整性的問題。
數(shù)字簽名技術(shù)主要用于證實(shí)消息的真正來源,也是解決一個(gè)消息的發(fā)送者和接收者之間的爭端的基礎(chǔ)。基于對稱密碼體制和非對稱密碼體制(公鑰密碼體制)都可以設(shè)計(jì)數(shù)字簽名方案。使用對稱密碼體制,需要引入第三方作為可信方,將數(shù)字簽名過程與可信方控制的硬件器件相結(jié)合,接收者通過一個(gè)防竄擾器件能確保消息來自于發(fā)送者。密鑰被儲存在防竄擾器件內(nèi),接收者無法訪問,在可信方的控制下管理密鑰。基于非對稱密碼體制可以設(shè)計(jì)出更強(qiáng)大的數(shù)字簽名方案。該方案包含簽名、驗(yàn)證兩部分內(nèi)容。數(shù)字簽名在現(xiàn)代Web 商務(wù)中具有重要意義。多數(shù)國家已經(jīng)把數(shù)字簽名看成與手工簽名具有相同法律效力的授權(quán)機(jī)制[2]。
數(shù)字簽名固然好,但沒有解決非對稱加密算法的速度慢和密文大的問題(因?yàn)橛冒l(fā)送方的私鑰加密整個(gè)明文消息時(shí),由于明文消息很大,可能導(dǎo)致加密過程很慢)。基于此問題,專家學(xué)者提出了消息摘要機(jī)制。消息摘要類似于縱向冗余校驗(yàn),用于驗(yàn)證數(shù)據(jù)完整性。消息摘要通常占128 位以上,這樣任意兩個(gè)消息摘要相同的機(jī)會小于大大提高了可靠性。
在信息安全技術(shù)中,經(jīng)常需要驗(yàn)證消息的完整性,散列函數(shù)提供了這一服務(wù),它對不同長度的輸入消息,產(chǎn)生固定長度的輸出。散列函數(shù)是算法的核心。現(xiàn)存機(jī)制大致可分為兩種,即MD5 類和SHA 類。
本文以SHA-512 算法為核心介紹消息摘要體制的原理,描述實(shí)現(xiàn)計(jì)算文件的哈希值生成對應(yīng)的消息摘要,并把文件的消息摘要進(jìn)行比較的損毀檢測系統(tǒng)。此次開發(fā)的環(huán)境為Code::Blocks,使用C++語言進(jìn)行編程。
SHA-512 算法所用的輸入是最大長度小于2128位的消息,輸出是512 位的信息摘要,輸出消息以1024 位的分組為單位進(jìn)行處理。SHA-512 嚴(yán)格按照SHA-1 模型,而SHA-1 是在MD4 基礎(chǔ)上修改而成的,故SHA-512 與MD5 有相似之處。
在初始消息中增加填充位,使消息長度模1024 與896 同余,即使已滿足仍然需要繼續(xù)填充。填充由一個(gè)1 和后續(xù)的0 組成。

表1:初始化鏈接變量的值

表2:80 個(gè)常數(shù)K 的值
計(jì)算不包括填充位的消息長度,并把它作為一個(gè)128 位的無符號整數(shù)塊附加到填充位的后面,這樣消息長度正好是1024 位的倍數(shù)。如果消息長度超過128 位,則只取后128 位,即等于計(jì)算length mod 128。
把消息分解,每個(gè)塊長度為1024 位,這些塊就是消息摘要處理邏輯的輸入。[3]
Hash 函數(shù)的中間結(jié)果和最終結(jié)果保存在512 位的鏈接變量中。鏈接變量用8 個(gè)64 位的寄存器表示,并將這些寄存器初始化為64位的整數(shù)(十六進(jìn)制值)。這些字的獲取方式為前8 個(gè)素?cái)?shù)取平方根,取小數(shù)部分的前64 位。初始化鏈接變量的值如表1 所示。
2.5.1 字分塊
將當(dāng)前的1024 位數(shù)據(jù)塊分解成16 個(gè)字塊,每個(gè)字塊長度為64 位;
2.5.2 字?jǐn)U展
擴(kuò)展每一個(gè)消息分組,要把16 個(gè)字?jǐn)U展為80 個(gè)字。原1024位塊的16 個(gè)字組成了前面16 個(gè)字(W0-W15),后面64 個(gè)字(W16-W79),每個(gè)按如下公式迭代求出:

2.5.3 壓縮函數(shù)輪變換
對數(shù)據(jù)每個(gè)分組的處理包含80 個(gè)輪。每一輪的輸入包含三個(gè)參數(shù):8 個(gè)之前的緩沖(鏈接變量),擴(kuò)展后的字(Wi),一個(gè)64位的常數(shù)Kt。開始處理時(shí),把8 個(gè)緩沖值保存在8 個(gè)臨時(shí)變量中,經(jīng)過79 輪處理結(jié)束后再把這些值加到從第79 步創(chuàng)建的值上。
每輪64 位緩沖的8 個(gè)值都是前一輪的緩沖值所創(chuàng)建的。輪函數(shù)每輪的8 個(gè)輸入字如圖1 所示。
有兩個(gè)混合器、三個(gè)函數(shù)。每個(gè)混合器把兩個(gè)函數(shù)組合起來。[4]輪函數(shù)的結(jié)構(gòu)如圖2 所示。
其中,A 與E 的值由如下公式求出:
其中,

XOR 指模264加法。
有80 個(gè)常數(shù)K,每個(gè)十六進(jìn)制64 位。與8 個(gè)緩沖區(qū)的初值算法相同。80 個(gè)常數(shù)K 的值如表2 所示。
綜上,sha-512 中的壓縮函數(shù)總覽如圖3,經(jīng)過每一字塊的80輪變換產(chǎn)生一512 位的消息摘要。
3.1.1 Code::Blocks 環(huán)境
Code::Blocks 是一個(gè)由The Code::Blocks Team 由C++語言開發(fā)的開放源碼的全功能的集成開發(fā)環(huán)境,主要支持c 和c++語言。使用了著名的圖形界面庫wxWidgets 庫,捆綁了MinGW 編譯器。跨編譯器包括gcc/g++、Visual C++、Borland C++、Intel C++等超過20 多款編譯器。同時(shí)它也支持多種語言的編譯,包括D 語言等。它是一個(gè)跨平臺的集成開發(fā)環(huán)境,可以在Windows、GNU/Linux、MacOS X 平臺上使用。Code::Blocks 提供了多種工程模板,這包括:控制臺應(yīng)用、DirectX 應(yīng)用、動態(tài)連接庫、OpenGL 應(yīng)用、QT 應(yīng)用等,還支持用戶自己定義的工程模板。具有便利的語法高亮、代碼覆蓋、分析和自動完成等工具,支持工程管理、項(xiàng)目構(gòu)建、調(diào)試。
3.1.2 C++
對廣泛流行的C 語言進(jìn)行擴(kuò)充的C++語言,是典型的面向?qū)ο笳Z言。它解決了C 語言不支持代碼重用、類型檢查機(jī)制弱、面向過程對大型軟件開發(fā)的缺陷等問題,是一種優(yōu)秀的既支持面向過程、又支持面向?qū)ο蟮幕旌闲偷某绦蛟O(shè)計(jì)語言。
C++保持與C 的兼容,用C 語言編寫的眾多函數(shù)庫可以用于C++中。C++保持了C 的簡潔、高效、接近匯編語言的特點(diǎn),在運(yùn)行效率上接近C 語言,而且增加面向?qū)ο蟮臋C(jī)制,包括抽象數(shù)據(jù)類型、封裝和信息隱藏、繼承和派生、函數(shù)運(yùn)算符重載、虛函數(shù)、模板,這些機(jī)制的存在為大中型軟件的開發(fā)變得更加容易。

圖1:輪函數(shù)每輪的8 個(gè)輸入字

圖2:輪函數(shù)的結(jié)構(gòu)

圖3:SHA-512 壓縮函數(shù)(輪變換)
unsigned long long data[0x2000000]讀入文件數(shù)據(jù)
unsigned long long T1 混合器2(設(shè)計(jì)時(shí)與原理中的混合器編號相反)
unsigned long long T2 混合器1
unsigned long longW[80]擴(kuò)展后的一個(gè)字
unsigned long longHashI_1[8]中間結(jié)果
unsigned long longHashI[8]最終結(jié)果
const unsigned long longKt[80]80 個(gè)常數(shù)
string filename 輸入的文件名或文件地址

圖4:計(jì)算文件的初始哈希值

圖5:檢驗(yàn)文件是否損毀-文件未損毀

圖6:檢驗(yàn)文件是否損毀-文件已損毀
string hashstring 文件的哈希值(消息摘要)
struct file{
char address[180];
charhashstr[550];
};結(jié)構(gòu)體:文件名/地址和它的哈希值
算法設(shè)計(jì)為一個(gè)sha512 類,兩個(gè)功能函數(shù)main1、main2 分別進(jìn)行計(jì)算文件初始的哈希值、檢驗(yàn)損毀操作,一個(gè)主函數(shù)實(shí)現(xiàn)由用戶的界面操作得到的指令執(zhí)行不同的功能函數(shù)。
sha512 類中的函數(shù):
sha512(string f);構(gòu)造函數(shù)
void InitializeHash();緩沖區(qū)初始化
unsigned long long ROTR(unsigned long longx,int n); 單步輪變換
void SHA_512(int N);輪變換
void sha512main(); 輸入文件的處理
void savehash();保存文件的哈希值到指定txt 文件
void printhash();屏幕輸出文件的哈希值
char* gethashstr(); 將哈希值數(shù)組轉(zhuǎn)換為字符串
外部函數(shù):
功能函數(shù)main1:計(jì)算文件的初始哈希值
功能函數(shù)main2:檢驗(yàn)文件是否損毀
主函數(shù)main:系統(tǒng)循環(huán)
本系統(tǒng)功能簡單,使用命令行模式界面,由用戶選擇對應(yīng)數(shù)字的對應(yīng)功能實(shí)現(xiàn)功能函數(shù)的調(diào)用。
4.2.1 計(jì)算文件的初始哈希值
用戶選擇選項(xiàng)1 后,根據(jù)提示輸入文件的地址即可顯示出該文件的哈希值。如圖4 所示。
4.2.2 檢驗(yàn)文件是否損毀
用戶選擇選項(xiàng)2,根據(jù)提示輸入曾經(jīng)計(jì)算過哈希值的文件地址即可顯示出是否損毀。
文件修改前,輸出文件的哈希值并提示未損毀。如圖5 所示。
文件修改后,顯示出新的哈希值并提示已損毀。如圖6 所示。
4.2.3 退出系統(tǒng)
用戶選擇選項(xiàng)3 后,退出系統(tǒng)。
程序最終可以實(shí)現(xiàn)計(jì)算哈希值,保存每一次文件的哈希值到本地?cái)?shù)據(jù)文件(txt)中,當(dāng)再次輸入文件地址進(jìn)行檢驗(yàn)時(shí),系統(tǒng)通過比對輸入文件當(dāng)前的哈希值和數(shù)據(jù)文件中的哈希值,檢驗(yàn)文件是否損毀。