2016-09-29 142 views
0

我有一箇中央Web服務器(Node.js),並且還有幾個客戶端計算機(也運行Node)。這些客戶端將把數據推送到Web服務器,因此,爲了安全起見,客戶端將首先向主服務器註冊 - 生成它自己的唯一SSL私鑰/公鑰並將公鑰存儲在服務器上。Node.js:使用唯一公鑰對客戶端進行身份驗證(與Github SSH密鑰身份驗證類似)

現在,註冊後,客戶端每次嘗試與服務器通信時,都需要顯示其公鑰(?)來驗證自己。

我想了解如何去做這件事。我應該將客戶端的所有公鑰的內容存儲在常規數據庫集合中嗎?

我該如何讓客戶將他們的證書與他們的數據一起「呈現」?我看過幾個軟件包,比如client-certificate-auth,但我認爲這不會對我的用例有所幫助。

編輯:我忘了提及,我將通過HTTPS(端口443)進行通信,所以我認爲需要照顧實際的安全部分。我只是想確保沒有流氓的,未註冊的客戶端使用pub/private加密/ SSL證書將數據推入服務器。

+0

您是否打算使用微妙的網絡加密API?我想我明白你想要什麼。我可以爲你寫一個例子...你希望javascript中生成的私鑰在客戶端保密,公鑰在服務器上安全地發送和存儲... – TylerY86

+0

在認證過程中,客戶端說公鑰是由一個唯一的標識符標記。然後,服務器發出一個挑戰消息,使用用戶的公鑰加密消息。用戶用他的私鑰解密該消息,然後正確響應。這提供* no *安全性,您必須通過已建立的SSL連接執行此操作。它是傳統cookie和會話令牌的替代品,它只是不同的,更難的,而不是更好的。私鑰永遠不會到達服務器。 – TylerY86

回答

1

如果您要走此路徑,請使用Subtle Crypto API。最有可能的是,你不應該這樣做。

您希望在javascript中生成的私鑰在客戶端保持祕密,並且公鑰在服務器上安全地發送和存儲。

鑑別過程中,客戶說什麼這是公鑰是與它相關的一些唯一標識符的公鑰,例如ID或通用名稱或用戶名稱。

然後,服務器發出挑戰消息,並使用客戶端的公鑰公鑰加密。

用戶用他的私鑰解密消息,然後用正確的解密響應進行響應。

這不提供安全性,您必須通過已建立的SSL連接執行此操作。

這是傳統的cookie和會話令牌的替代方案,它只是不同,更難,而不是更好。

私鑰永遠不會隨時到達服務器。客戶端不使用私鑰進行加密,這不是公鑰密碼學的工作原理。

但它可以發送數字簽名,服務器可以驗證。這是唯一標識符的替代方案;確保你指定一個真正的足夠長的nonce來簽名。

要進行數字簽名的挑戰,服務器會發送一個質詢字符串給客戶端,客戶端使用它的私鑰並響應服務器簽署的挑戰,然後服務器驗證使用公鑰簽名。 公鑰必須是簽名的一部分,並且服務器必須知道信任公鑰,因此它必須能夠快速查找它。

另一種選擇是依靠用戶建立自己的客戶端證書的知識,在這種情況下,Paul的答案中提到的passport-client-cert可以處理該問題。

1

我強烈建議您自己不要這樣做,如果您沒有正確實施,會出現很多錯誤。

那說,這種東西工程建築是以「目前的客戶端的公鑰」,而是讓客戶端加密的東西用自己的私鑰和加密的數據發送到服務器,然後一路用客戶的公鑰解密。如果能夠這樣做的話,它就知道客戶端就是它聲稱的客戶端(理論上,它的可靠性可能會因您的密鑰空間而異)。

客戶端加密了什麼?那麼,這很大程度上取決於你想要成爲多麼安全/你是多麼偏執。一種方式(準kerberos)可以讓客戶端向服務器發送請求以加密信息。這是通過SSL完成的,因此客戶端可以確保服務器是它所說的(並且可以檢查CA等)。傳回的東西是一些數據,包括隨機值,到期時間,可能還有某種類型的隨機數。它也存儲在服務器中,以便稍後驗證,並且當然會按時驅逐。客戶端通常會使用該確切的對象(可能是JSON對象)並使用其私鑰對其進行加密,然後將其發送回服務器以訪問某個登錄端點。正如我之前所說的那樣,服務器會根據客戶端的ID檢查其對象的存儲位置,然後進行比較,看看兩個對象是否相同。如果是,那麼它可以接受客戶是誰說的。

正常情況下,此握手僅用於交換客戶端可用於加密其所有流量的會話密鑰,因爲CPU上的對稱密鑰加密通常比PKI更容易。老實說,雖然我只是抓了表面。您可能會更好地瞭解PassportJS爲策略提供哪些策略並選擇其中之一。也許passport-api-keypassport-client-cert將做你所需要的。

+0

我認爲你倒退了PKI挑戰...客戶端不用私鑰加密。 – TylerY86

+0

您可能正在考慮數字簽名挑戰。 – TylerY86

+0

從技術上講,在這種情況下稱爲簽名,但該過程仍然用於加密一些已知字節。 – Paul