我正在构建一个具有客户端/服务器基础结构的应用程序,并希望使用公钥/私钥方法实现身份验证机制。
假设客户端拥有私钥,而服务器只有公钥。在身份验证期间,客户端使用私钥签署消息,将其发送到使用公钥验证的服务器。如果验证成功,则客户端通过身份验证。
这是一些 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));
}
当然,为了使其正常工作,服务器和客户端都必须拥有明文消息(摘要)。
现在我的问题是:什么是用于签名的好消息(摘要)?例如,这可以是一个静态的、硬编码的字符串(用于所有 客户端),或者这是否会给这个概念带来某种安全问题?如果静态字符串不好,在身份验证之前协商一些随机字符串是个好主意吗?例如,这个随机字符串可以用作“ session ” key ,并在一段时间后失效。
最佳答案
静态字符串会很糟糕,因为它容易受到重复攻击(签名字符串每次都相同)。
尽管如此,您似乎正在重新发明以前做过的事情。使用证书是值得信赖的方式。有关更多信息,请参阅此示例:Java HTTPS client certificate authentication
如果您想自己实现它,您可能需要阅读 SSL 的工作原理并模仿它。任何其他解决方案都可能存在一些缺陷,除非它是非常定制的(例如,您的客户端将保留 1000 个它从未重复使用的共享静态字符串的列表,并且服务器具有相同的列表并跟踪已更改的内容使用。或者,跟踪一个递增的共享数字,如以下评论中所建议的。)
关于java - 使用公钥/私钥签名进行身份验证 : What's a good message (digest)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10288521/