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

相关问题