openssl簡介
openssl是一個功能豐富且自包含的開源安全工具箱。它提供的主要功能有:SSL協議實現(包括SSLv2、SSLv3和TLSv1)、大量軟算法(對稱/非對稱/摘要)、大數運算、非對稱算法密鑰生成、ASN.1編解碼庫、證書請求(PKCS10)編解碼、數字證書編解碼、CRL編解碼、OCSP協議、數字證書驗證、PKCS7標準實現和PKCS12個人數字證書格式實現等功能。
openssl采用C語言作為開發語言,這使得它具有優秀的跨平臺性能。openssl支持Linux、UNIX、windows、Mac等平臺。openssl目前最新的版本是openssl-1.0.1i。
更多的相關知識請參閱鋪天蓋地的各種官方非官方文檔。今天來實現怎樣將一個新算法添加進openssl中。
問題描述
openssl中雖然集成了很多經典算法,對稱算法、非對稱算法、摘要算法等等,但有時候我們需要用到自定義的算法,比如要實現一個自定義的摘要算法,需要借助openssl帶的大數庫來實現,同時又希望將自己實現的算法封裝到openssl里面,以便統一調用或者方便項目改造和替換。最具現實意義的案例就是國密SM2等的改造。本例將用國密中的摘要算法SM3作為添加對象,在windows下面進行編譯調試,僅描述添加步驟,所以本文的前提是已經完成了基于openssl大數庫的SM3的c語言實現。本文僅供依葫蘆畫瓢,要理解原理請自行查閱別的資料或者自己解讀源碼,或者等我的下一篇文章。
具體步驟
一、準備工作
1、 下載openssl源碼,openssl目前最新的版本是openssl-1.0.1i。下載地址:
2、 sm3的c語言實現。
3、 windows下perl、vc的安裝配置。
4、 熟悉openssl的編譯過程。
二、SM3代碼改造【這個步驟涉及到的文件全部新建,存放目錄關系如圖】
1、 涉及到的文件7個:
1、 【新建文件】sm3.h
這是最重要的一個頭文件,里面定義了算法可以導出的算法,也就是里面聲明的每一個函數最后都會生成對應的libeay.num(將在第五章中具體講),能夠導出到dll中供外部調用。幾個主要的聲明如下:
定義sm3的摘要長度:
#define SM3_DIGEST_LENGTH 32 /* sm3 摘要長度為256位 32字節,md5的摘要長度128位 not sure*/
定義SM3_CTX,這個結構其實就是對應evp封裝中EVP_MD_CTX的md_data:
聲明函數,包括init、update、final,這幾個函數會在封裝的時候被內部調用,當然在dll中導出了也可以外部調用:
2、 【新建文件】sm3_locl.h
這個頭文件中包含一些要用到的宏定義。主要定義了本算法實現中需要用到的內部函數,不能被導出到dll中供外部調用。
宏定義:
3、 【新建文件】sm3_dgst.c
實現sm3.h和sm3_locl中聲明的函數,除了函數SM3(將在sm3_one.c中實現)。
4、 【新建文件】sm3_one.c
實現sm3.h中聲明的函數SM3。
5、 【新建文件】sm3.c
實現對文件的摘要,如用在openssl作為命令行工具,文件名和摘要算法名作為選項參數實現使用算法對文件進行摘要。
6、 【新建文件】sm3test.c
算法的test文件。
7、 【新建文件】Makefile
編譯的Makefile文件。里面描述在編譯的時候以上的幾個文件的角色、編譯過程、依賴關系等。
三、EVP封裝相關代碼
1、 涉及到的文件4個:
2、 【手動修改】evp.h
evp在openssl里面的主要做的是封裝的事情,因此首先在evp.h頭文件中添加新算法sm3:說明:EVP_sm3()函數將返回返回一個sm3的EVP_MD的結構,這個結構以及EVP_sm3()函數都在m_sm3.c中定義。
3、 【新建文件】m_sm3.c
這是放在EVP目錄中關于新算法的一個重要文件,定義sm3的EVP_MD結構,EVP_MD結構原型在evp.h中:
sm3的EVP_MD結構:
4、 【手動修改】c_alld.c
openssl的算法封裝之后使用時需要加載算法,實現SM3的添加:
5、 【手動修改】Makefile
將編譯時候的LIBSRC、LIBOBJ中加入SM3新算法,并且添加sm3各種頭文件的依賴關系。
四、OID生成
1、 涉及到的文件7個:
2、 【手動修改】objects.txt
添加sm3的OID,特別說明:此處僅作示例,sm3的實際OID是:
添加sm3WithRSAEncryption,這個是對應PKCS1的,只是為了讓sm3的EVP_MD結構有值填充,實際添加sm3的本意不用于RSA,這里僅作示例。
3、 【執行命令自動更新】obj_mac.h和obj_mac.num
打開cmd,切換到目錄下源碼的cryptoobjects所在的目錄下,
執行命令:perl objects.pl objects.txt obj_mac.num obj_mac.h
obj_mac.h和obj_mac.num這兩個文件都會因為objects.txt的修改而更新。增加的內容如:
4、 【手動修改】objects.h
將obj_mac.h中新增的內容同步到objects.h中。(其實這一步不做也沒有影響,因為之后不用這個文件來生成obj_dat.h。objects.h的內容沒有obj_mac.h的內容全面,千萬不能用objects.h來obj_dat.h,一定要用obj_mac.h來生成才是正確的。切記,血的教訓!)
5、 【執行命令自動更新】obj_dat.h
執行命令:perl obj_dat.pl obj_mac.h obj_dat.h
將會自動更新obj_dat.h這個文件,新增的內容如下:
注意看圖上最后兩排
最后帶的一串數字本來是算法的OID,因為上面第2步的objects.txt中是亂填的,所以這個不是真實的OID。僅作示例。
6、 【手動修改】obj_xref.txt
添加:7、 【執行命令自動更新】obj_xref.h
執行命令:perl objxref.pl obj_xref.txt obj_xref.h
obj_xref.h更新后的添加的內容如:
五、make相關設置
1、 涉及到的文件util下面5個:
2、 【手動修改】mkfiles.pl
添加:
添加上包含sm3的算法源碼的目錄,這個目錄中包含sm3的Makefile文件。之后就會按照Makefile進行編譯。
3、 【手動修改】mkdef.pl
添加內容如圖:
加上新算法的頭文件等,可以在dll中導出算法函數。
4、 【執行命令自動更新】libeay.num
執行命令:perl util/mkdef.pl crypto update
Libeay.num更新后增加的內容如:
5、 【手動修改】mk1mf.pl
添加內容如:
6、 【手動修改】sp-diff.pl
添加內容如:
7、 涉及到的文件crypto下面2個:
8、 【手動修改】crypto-lib.com
添加內容如:
9、 【手動修改】install-crypto.com
添加內容如:
10、 涉及到的文件根目錄下面5個:
11、 【手動修改】
添加內容如圖:Makefile、Makefile.bak、Makefile.org、makevms.com、INSTALL.VMS
到這里,源碼需要添加和修改的就結束了,下面將介紹編譯和測試。
六、編譯
1、 在cmd下,首先設置VC環境,執行VC目錄下的vcvars32.BAT文件,如:
2、 cmd下進入openssl源碼所在的目錄,依次執行命令【編32位,如果64位可能缺ml64.exe】:
1)執行命令:perl Configure VC-WIN32 no-asm
2) 執行命令:msdo_ms
3)執行命令:nmake-f ms tdll.mak:這個是動態庫:如果編譯成功,最后的輸出都在out32dll目錄下: 包括可執行文件 、兩個dll和兩個lib文件【nmake -fms t.mak
這是靜態庫的編譯命令,輸出在out32目錄下】。編譯成功如圖:
4) 執行命令:nmake -fms tdll.mak test
5)執行命令:nmake -f ms tdll.mak install
七、測試
1、 API編程測試,在vs建工程,將openssl目錄下生成的out32dll文件夾下的libeay32.dll和libeay32.lib到工程。
2、 設置工程的附加庫和附加包含目錄:
右鍵工程->屬性-> C/C++ ->常規->附加包含目錄
右鍵工程->屬性-> 鏈接器 ->常規->附加庫目錄
3、 sm3test.c源碼如:
sm3test.c
4、 sm3test.c運行使用sm3算法對“abc”進行摘要后的結果如圖:
和國密標準的附錄示例一致:
八、總結
本例以摘要算法為例,具體介紹了一下通過直接添加源碼的方式怎樣在openssl里面添加新算法,而非engine方式。當然如果認為engine方式更方便,則請忽略本文。本文只是在描述怎么做,但是沒有講為什么。因為例如openssl本身的封裝機制是需要解讀源碼才能更好地理解上述文中為什么需要做那些步驟,因為這些步驟已經夠復雜了,所以解讀源碼將另起一篇文章。本文僅供依葫蘆畫瓢,要理解原理請自行查閱別的資料或者自己解讀源碼,或者等我的下一篇文章。
任何疑問或者指正請聯系我,謝謝!
小伙伴們加油!GOOD LUCK!