前些天在網上看到了一些關於OPENSSL的介紹,覺得很有意思,於是做了一個程序,基本實現了數字證書的制作、SSL安全通訊、加解密操作等功能,秉承OPENSSL開放的原則,拿出來共享,主要實現寫在了兩個DLL中。水平有限,請勿見笑。
首先感謝中國OPENSSL論壇(http://www.openssl.cn/)的幾位斑竹,感謝他們的辛勤勞動和默默付出。
程序是在一個電子鑰匙管理程序的基礎上作的,原來電子鑰匙的部分還保留著,需要電子鑰匙的支持。
代碼較多,筆者只介紹認為重要的三點。
程序要點:
(1)RA客戶端與服務器程序采用了ACCESS數據庫,SSL連接、非阻塞套接字,基本原理是客戶端發送命令請求,服務器查詢數據庫,然後查詢結果發給客戶端。非阻塞套接字是很靈活的,運用不當會事倍功半,這個程序而言:AsyncSelect函數是個關鍵。
林軍鼐的Winsock編程寶典中這樣寫道:
【FD_WRITE 事件】
系統會通知我們 FD_WRITE 事件的訊息,只有下列幾種情況:
(1)呼叫 WSAAsyncSelect() 來設定 FD_WRITE 事件時,Socket 已經可以傳送資料(TCP scoket 已經和對方連接成功了,或 UDP socket 已建立完成),且目前 output buffer 仍有空間可寫入資料。
(2)呼叫 WSAAsyncSelect() 來設定 FD_WRITE 事件時,Socket 尚不能傳送資料,不過一旦 Socket 與對方連接成功,馬上就會收到 FD_WRITE 的通知。
(3)呼叫 send() 或 sendto() 傳送資料時,系統告知錯誤,且錯誤碼為10035 WSAEWOULDBLOCK (呼叫 WSAGetLastError() 得知這項錯誤),這時表示 output buffer 已經滿了,無法再寫入任何資料(此時即令呼叫再多次的 send() 也都一定失敗);一旦系統將部份資料成功送抵對方,空出 output buffer 後,便會送一個 FD_WRITE 給使用者,告知可繼續傳送資料了。換句話說,讀者在呼叫 send() 傳送資料時,只要不是返回錯誤 10035 的話,便可一直繼續呼叫 send() 來傳送資料;一旦 send() 回返錯誤 10035,那麽便不要再呼叫 send() 傳送資料,而須等收到 FD_WRITE 後,再繼續傳送資料。
【FD_READ 事件】
我們會收到 FD_READ 事件通知我們去讀取資料的情況有 :
(1)呼叫 WSAAsyncSelect 函式來對此 Socket 設定 FD_READ 事件時,input buffer 中已有資料。
(2)原先系統的 input buffer 是空的,當系統再收到資料時,會通知我們。
(3)使用者呼叫 recv 或 recvfrom 函式,從 input buffer 讀取資料,但是並沒有一次將資料讀光,此時會再驅動一個 FD_READ 事件,表示仍有資料在 input buffer 中。
讀者必須注意:如果我們收到 FD_READ 事件通知的訊息,但是我們故意不呼叫 recv 或 recvfrom 來讀取資料的話,爾後系統又收到資料時,並不會再次通知我們,一定要等我們呼叫了 recv 或 recvfrom 後,才有可能再收到FD_READ 的事件通知。(林軍鼐)
(2)因為有些基本操作寫在動態庫中,動態庫中長時間操作(加解密)的進展情況,應該在主程序中體現出來,這樣比較友好。本程序采用了回調函數機制解決這個問題。
static void DrawProg(int i);
void CUsbEvpPage::DrawProg(int i)
{
((CUsbEvpPage *)((CPropertySheet *)AfxGetMainWnd())->GetPage(8))->
m_Progress.SetPos(i);//沒有引入this,因為這個函數在動態庫中調用。
}
動態庫在一定條件下調用了這個函數,指示了操作的進度。
(3)程序做完了,如果用一些諸如SMARTCHK的工具檢查一下,說不定會有收獲。
程序BUG:
1、不能再同一個程序中用SSL客戶端連接SSL服務器,否則……
2、由於對OPENSSL掌握的有限,部分代碼存在內存洩漏。
3、SSL客戶端連接SSL服務器,顯示亂碼是因為沒有處理半個漢字;如果用IE連接就沒有這個問題。
因為程序代碼較多,不再一一介紹,具體實現請參看源代碼。代碼中存在的錯誤請指出,以便在下一個版本中修正。
一些頭文件和lib采用了絕對路徑,需要重新配置。
CA和EVP動態庫的源代碼問題還很多,因此沒有發布,待完善了再拿出來獻丑。
關於數字證書和SSL的應用,可以在網絡上找一些介紹,這裡不再贅述。
程序在win2000 + vc6+ACCESS2000下面測試過。如有問題與我聯系。
本文配套源碼