2

我正在構建一個客戶端/服務器基礎結構的應用程序,並希望使用公鑰/私鑰方法實現驗證機制。使用公鑰/私鑰簽名進行身份驗證:什麼是好消息(摘要)?

我們假設客戶端擁有私鑰並且服務器只有公鑰。在認證期間,客戶端用私鑰簽名消息,將其發送到使用公鑰驗證的服務器。如果驗證成功,則客戶端通過身份驗證。

下面是一些JUnit測試代碼,我自己做了熟悉的概念:

@Test 
public void testSignature() throws Exception { 
    final String message = "Hello world is a stupid message to be signed"; 

    final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); 

    final Signature privSig = Signature.getInstance("SHA1withRSA"); 

    privSig.initSign(keyPair.getPrivate()); 
    privSig.update(message.getBytes()); 

    byte[] signature = privSig.sign(); 

    final Signature pubSig = Signature.getInstance("SHA1withRSA"); 

    pubSig.initVerify(keyPair.getPublic()); 
    pubSig.update(message.getBytes()); 

    assertTrue(pubSig.verify(signature)); 
} 

當然,爲了這個工作服務器和客戶端必須持有平原消息(摘要)中。

現在我的問題是:什麼是用於簽名的好消息(摘要)?例如,這可能是一個靜態的硬編碼字符串(用於所有客戶端),還是會對此概念施加某種安全問題?如果靜態字符串不好,在認證之前協商一些隨機字符串會是一個好主意嗎?這個隨機字符串可以用作例如「會話」鍵,並在一段時間後失效。

+2

是否有原因讓您不想使用客戶端證書進行標準的SSL/TLS握手? – stinkymatt 2012-04-23 21:26:44

+0

沒理由。我正在評估不同的選項。不過,我也想使用私鑰進行加密。具有相同密鑰(相同用戶)的客戶端應該能夠發送/接收加密消息,而服務器不能解碼它們。 – 2012-04-23 21:44:53

+0

如果您不介意拉入廚房水槽,您可以嘗試使用支持中介(例如您的服務器似乎是)的SOAP,並允許進行消息級別的身份驗證和加密。 http://www.ibm.com/developerworks/cn/webservices/library/ws-soapbase/ – artbristol 2012-04-24 07:40:08

回答

3

靜態字符串會很差,因爲它容易受到重複攻擊(每次簽名的字符串都是相同的)。

雖然,你似乎在重塑之前做過的事情。使用證書是值得信賴的方式。看到這個例子的更多信息:Java HTTPS client certificate authentication

如果你想自己實現它,你可能需要閱讀SSL如何工作和模仿。任何其他解決方案都可能存在一些缺陷,除非它是非常定製的(例如,您的客戶端將保留1000個共享靜態字符串的列表,它永遠不會被重用,並且服務器擁有相同的列表並記錄已經或者跟蹤一個共享號碼,如下面的評論所示)

+0

繞過重播問題的簡單變體是僅使用每次認證發生時都會遞增的大數字。然後客戶端/服務器只需要保留最後一個使用。 – TJD 2012-04-23 22:01:19

+0

我通常試圖不重新發明輪子:)客戶端/服務器通過HTTP REST API進行通信。服務器將成爲一個將被部署到應用服務器的WAR文件。所以我不能認爲應用程序服務器啓用了HTTPS,因爲它不在我的控制範圍之內。你有什麼建議? – 2012-04-24 05:29:37

+0

這是真正的TJD。這將是一個非常簡單的想法,而不是如果字符串很多。 – 2012-04-24 06:45:30

相關問題