3

我正在构建一个具有客户端/服务器基础架构的应用程序,并希望使用公钥/私钥方法实现身份验证机制。

假设客户端拥有私钥,而服务器只有公钥。在身份验证期间,客户端使用私钥对消息进行签名,然后将其发送到使用公钥对其进行验证的服务器。如果验证成功,则客户端通过身份验证。

这是一些 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));
}

当然,为了使其工作,服务器和客户端都必须拥有纯消息(摘要)。

现在我的问题是:用于签名的好消息(摘要)是什么?例如,这可以是一个静态的、硬编码的字符串(用于所有客户端)还是会给这个概念带来某种安全问题?如果静态字符串不好,在身份验证之前协商一些随机字符串是个好主意吗?例如,这个随机字符串可以用作“会话”密钥,并在一段时间后失效。

4

1 回答 1

3

静态字符串会很糟糕,因为它容易受到重复攻击(签名字符串每次都相同)。

虽然,您似乎正在重新发明以前所做的事情。使用证书是值得信赖的方式。有关详细信息,请参阅此示例:Java HTTPS 客户端证书身份验证

如果您想自己实现它,您可能需要阅读 SSL 的工作原理并模仿它。任何其他解决方案都可能存在一些缺陷,除非它是非常定制的(例如,您的客户端将保留 1000 个共享静态字符串的列表,它从未重用过,并且服务器具有相同的列表并跟踪已使用过。或者,按照以下评论中的建议,跟踪递增的共享数字。)

于 2012-04-23T21:50:47.487 回答