使用C 開發HTTP伺服器之支援HTTPS

2021-07-28 15:00:34 字數 3063 閱讀 4795

https,即hyper text transfer protocol over secure socket layer的簡稱,是指以安全為目標的http協議。我們可以將其理解為在http協議的基礎上增加了安全機制,這裡的安全機制是指ssl,簡單來講https協議依然採用http協議,不過它在http和tcp間增加了加密/身份驗證層,因此在保證資料傳輸安全的同時,為伺服器提供了身份校驗機制。任何採用https協議的**,均可通過瀏覽器位址列中的「鎖」標誌來檢視**的認證資訊,或者是通過ca機構頒發的數字證書來查詢。下圖展示的是https協議中客戶端和伺服器端通訊過程:

從圖中我們可以看出,在https協議中客戶端和伺服器端分為六步:

這恰恰印證了我們最初的觀點,即https協議依然採用http協議(三次握手)進行通訊,不同的地方在於中間環節增加了加密處理,例如在客戶端和伺服器端相互驗證的環節採用的是非對稱加密,在客戶端驗證通過以後雙方採用隨機數作為金鑰是對稱加密,而三次握手以後驗證訊息是否被篡改則是採用hash演算法。所以我們應該可以注意到,http協議和https協議的乙個顯著的區別是,前者採用明文來傳輸訊息,而後者採用密文來傳輸訊息,因此https協議比http協議在通訊上更為安全。而詳細來說,兩者的區別主要有:

好了,現在我們對https協議有了乙個基本的認識:https協議相比http協議增加了身份驗證和訊息加密的機制,因此https協議能夠保證通訊過程中的資料傳輸安全。在今天這樣乙個數字時代,當個人隱私安全徹底地暴露在瀏覽器、應用程式面前,能夠提供更安全的網際網路服務無疑會讓人更有安全感,我想這是蘋果和谷歌這樣的科技巨頭公司,之所以要去努力推廣https協議的原因吧!因為客戶端需要對伺服器的證書進行驗證,所以這意味著在客戶端擁有訪問所有受信證書的能力,例如我們在使用傳統網銀產品時都需要安裝網銀證書,這其實就是為了讓客戶端在向伺服器端發起請求時方便對伺服器進行驗證,因此如果客戶端請求的url遭遇劫持,被重定向到某個不被信任的站點上,那麼客戶端發起的請求就會被攔截。同樣的道理,伺服器端會對客戶端的請求進行驗證,所以這裡就不再詳細展開去說啦。

這篇文章的核心是開發乙個伺服器,所以在保證這些基礎設施完備的前提下,讓我們將關注點落實到**上面來。我們提到,https除了證書以外關鍵點是ssl,而在.net中提供ssl相關的api,所以這裡我們直接使用這些api就可以完成證書的建立、載入等工作。下面是相關的**示例:

// 使用openssl.net生成金鑰

rsa rsa = new rsa();

bignumber number = openssl.core

.random

.next(10, 10, 1);

rsa.generatekeys(1024, number, null, null);

cryptokey key = new cryptokey(rsa);

//建立x509證書,subject和issuer相同

x509certificate x509 = new x509certificate();

x509.serialnumber = (int)datetime.now

.ticks

;x509.subject = new x509name("cn=domain"); //domain為站點網域名稱

x509.issuer = new x509name("cn=domain");

x509.publickey = key; //指定公鑰

x509.notbefore = convert.todatetime("2011-1-1"); //起始時間

x509.notafter = convert.todatetime("2050-1-1"); //失效時間

x509.version = 2

;//使用私鑰簽名

x509.sign(key, messagedigest.md5);

//生成crt證書

bio x509bio = bio.file("ca.crt", "w");

x509.write(x509bio);

//生成pfx證書

var certs = new openssl.core

.stack

();pkcs12 p12 = new pkcs12("password", key, x509, certs); //password為保護金鑰

bio p12bio = bio.file("ca.pfx", "w");

p12.write(p12bio);

//載入證書

var certifiate = x509certificate.createfromcertfile("ca.crt");

在我們獲得證書以後,我們就可以通過ssl對socket通訊過程中傳遞的訊息進行加密了,乙個基本的示例**如下:

sslstream sslstream = new sslstream(clientstream);

sslstream.authenticateasserver(servercertificate, false, sslprotocols.tls, true);

sslstream.readtimeout = 10000;

sslstream.writetimeout = 10000;

return sslstream;

個人感覺加密相關的問題深奧而晦澀,這篇文章中涉及到的相關概念和技術,都大大地超出了我目前的認知範圍。不過既然這位朋友熱心地提交了這個pr,我就將這個過程視為向別人的一次學習吧!我會繼續去完善這個專案:這篇部落格終於算是寫完了,週末開心!

* 參考文章 *

* zery - https原理解析

* 阮一峰 - ssl/tls協議執行機制的概述

* 維基百科 - 超文字傳輸安全協議

* 貓尾部落格 - https工作原理

* msdn - 如何在 iis 中設定 https 服務

* dudu - 給iis新增ca證書以支援https

* 溫柔易淡 - apache配置https功能

使用C REST SDK開發HTTP伺服器

做windows開發的大家可能都已經知道了微軟開源的 c rest sdk。對於這個sdk的簡介我就不多提了,度娘上很多。根據這個名字,大家應該就知道,這個sdk主要是給客戶端開發的,網上也有很多客戶端開發實用的例子。然而對於伺服器的開發,網上的資料卻少之又少。下面我們著重來介紹下使用c rest ...

使用 HTTP2 做開發伺服器 上

筆者所在專案使用的前端技術比較老舊,在開發的過程中需要先啟動乙個後端專案 tomcat mysql redis 來做為靜態伺服器 然後使用的是乙個公司內部的類amd模組載入工具,每次重新整理頁面都要載入1000 的檔案,頁面的響應時間接近20s,導致開發的過程非常痛苦 所以決定使用 http 2 來...

C 伺服器開發之筆記三

為什麼需要原子性操作?若是有兩個執行緒同時對同乙個變數 就會出現問題,如下 time thread 1 thread 2 0 load eax,x 1 load eax,x 2 add eax,1 3 add eax,1 4 store x,eax 5 store x,eax 我們希望的結果是x 2...