使用公钥/私钥签名进行身份验证:什么是好消息(摘要)?

时间:2012-04-23 21:21:30

标签: java security authentication digital-signature public-key-encryption

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

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

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

当然,为了使其能够正常工作,服务器和客户端必须拥有简单的消息(摘要)。

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

1 个答案:

答案 0 :(得分:2)

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

虽然,你似乎正在重塑以前所做的事情。使用证书是值得信赖的方式。有关详细信息,请参阅此示例:Java HTTPS client certificate authentication

如果您想自己实现它,您可能需要了解SSL的工作原理并模仿它。任何其他解决方案都可能存在一些缺陷,除非它是非常定制的(例如,您的客户端将保留1000个共享静态字符串的列表,它永远不会重复使用,并且服务器具有相同的列表并跟踪已经存在的内容或者,如下面的评论中所建议的那样,跟踪共享的增量号码。)