如何创建不能用于重现消息两次的数字签名

时间:2011-02-18 15:19:15

标签: php encryption digital-signature

我正在创建一个客户端 - 服务器应用程序,我想安全地从服务器向客户端发送数据。

使用公钥/私钥算法是有意义的,在PHP中我们可以使用openssl_sign和openssl_verify函数来检查数据来自拥有私钥的人。

现在想象一下,服务器发送给客户端的其中一个操作本质上是破坏性的。如果某人使用HTTP嗅探器捕获此命令(将正确签名),我如何确保该命令仅在我们的服务器发送时执行而不是由黑客简单地再现相同的命令?

确定在写这篇文章时我发现使用自动增量id来编号每个发送的消息可能是解决问题的简单方法。客户端只需要检查传入的消息ID是否永远不会小于它们存储的当前ID。

4 个答案:

答案 0 :(得分:4)

在消息中包含随机数(随机值,每条消息的唯一值),并在客户端上跟踪已使用的随机数。即如果攻击者获取签名的消息并在以后重新发送,则该随机数已被客户端使用,因此客户端将不会再次处理该消息。

答案 1 :(得分:3)

如果有人使用HTTP嗅探器捕获此命令(将正确签名),我如何进一步保护通信以确保只有来自我们服务器的命令才能被客户端处理? < / p> 总之,你不能。如果有人可以嗅探网络流量,他们就可以获得您发送的任何内容。因此,除非您通过带外机制(例如电话呼叫)预先共享密钥,否则您无法可靠地执行此操作。如果你预先分享这个秘密,那么你需要做的就是:

服务器:

$message = 'foomessage';
$message .= ':' . hash_hmac('md5', $message, $sharedSecret);

客户端:

list ($message, $hmac) = explode(':', $message, 2);
if ($hmac != hash_hmac('md5', $message, $sharedSecret)) {
    die('invalid signature');
}

请注意,这100%依赖于共享密钥。如果其他人掌握了它,您所签署的所有通信都将被篡改。

检测嗅探器式攻击的另一种可能方法是使用syn-ack方法。基本上,您在服务器和客户端上存储一个数字。每个请求,您都会增加两个数字。然后在hmac计算中包含该数字。由于客户端和服务器相互通信,因此两个计数应始终保持同步。但是,如果它们一直处于关闭状态,你就知道发生了一些通信故障,或者有人注入了一个错误计数的命令(被劫持)。因此,虽然它不会直接“阻止”重放攻击,但由于攻击者需要跟踪服务器和客户端之间的每个HTTP请求,因此会更加困难。

但最重要的是,任何破坏网络以实现MITM攻击的人都能够绕过几乎任何可以攻击他们的东西......防范它的最佳方法是预先分享密钥在带外庄园中(这样HTTP扫描器将无法检测到共享密钥)。然后只需使用该预共享密钥hmac任何消息。

答案 2 :(得分:2)

听起来你需要解释PHP中的“One-Time Pad Cipher”吗?

一次性垫 一次性垫是一长串随机字母。这些字母与明文消息组合以产生密文。要破译消息,一个人必须拥有一次性密码的副本才能撤消该过程。一次性垫只能使用一次(因此名称),然后销毁。这是第一个也是唯一一个被证明是不可破解的加密算法。

要加密邮件,请使用明文消息中的第一个字母,然后将其添加到来自一次性邮件的第一个随机字母中。例如,假设您正在加密字母S(字母表中的第19个字母),而一次性键盘会给您C(字母表的第3个字母)。你添加两个字母并减去1.当你添加S和C并减去1时,你得到21就是U.每个字母都用这种方法加密,如果加法结果超出数字,则字母将包围到开头26(Z)。

要解密一条消息,请取密文的第一个字母,并从一次性密码中减去第一个随机字母。如果数字为负数,则将其环绕到字母表的末尾。

答案 3 :(得分:0)

从每条消息中创建一个哈希值(md5)并将微量时间戳添加到其中。