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

发布于 2024-10-17 23:28:41 字数 335 浏览 2 评论 0原文

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

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

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

好吧,在写这篇文章时,我发现使用自动递增 id 来对每条发送的消息进行编号可能是解决该问题的一个简单方法。客户端只需检查传入的消息 ID 是否小于他们存储的当前 ID。

I am creating a client-server application and I'd like to send data from server to client securely.

Using public/private key algorithms makes sense and in PHP we can use openssl_sign and openssl_verify functions to check that the data came by someone who has the private key.

Now imagine that one of the actions sent by server to client is destructive in nature. If somebody uses an HTTP sniffer to catch this command (which will be signed properly) how can I make sure that the command was executed only when our server sent it and not by a hacker simply reproducing the same command?

OK while writing this I figured out that using auto-increment id to number every sent message could be a simple solution to the problem. Client would just have to check that the incoming message ID is never smaller that the current ID they have stored.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

回忆那么伤 2024-10-24 23:28:41

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

Include a nonce (random value, unique for each message) to the message, and on the client keep track of used nonces. I.e. if the attacker takes the signed message and resends it later, the nonce is already used by the client, so the client won't handle the message for the second time.

久夏青 2024-10-24 23:28:41

如果有人使用 HTTP 嗅探器捕获此命令(该命令将被正确签名),我如何进一步保护通信以确保客户端只处理来自我们服务器的命令?

简而言之,您不能。如果有人可以嗅探网络流量,他们就能够获取您发送的任何内容。因此,除非您通过带外机制(例如电话)预先共享密钥,否则您无法可靠地做到这一点。如果您预先共享密钥,那么您需要执行以下操作:

服务器:

$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 攻击的人都能够绕过几乎任何你可以向他们发起的攻击……防范这种攻击的最佳方法是预先共享密钥-of-band 庄园(这样 HTTP 扫描器将无法检测到共享密钥)。然后只需使用该预共享密钥对任何消息进行 hmac 即可。

If somebody uses an HTTP sniffer to catch this command (which will be signed properly) how can I further protect the communication to ensure that only commands coming from our server get processed by the client?

In short, you can't. If someone can sniff the network traffic, they would be able to get anything that you send. So unless you pre-share a secret key via an out-of-band mechanism (such as a phone call), you can't reliably do this. If you pre-share the secret, then all you need to do this:

Server:

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

Client:

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

Note that this is 100% dependent on the shared key. If someone else got a hold of it, all your signed communication would be tampered with.

Another possible way of detecting a sniffer style attack is to use a syn-ack approach. Basically, you store a number on the server and on the client. Each request, you increment both numbers. You then include that number in a hmac calculation. Since the client and the server talk to each other, both counts should always be in sync. But if they are ever off, you know that either some communication failure has taken place, or someone has injected a command (hijacked) with the wrong count. So while it wouldn't "prevent" a replay attack directly, it would make it MUCH harder since the attacker would need to keep track of every single HTTP request between the server and the client.

But the bottom line is that anyone who's compromised the network to pull off a MITM attack will be able to get around almost anything you can throw at them... The best ways to secure against it are to pre-share secret keys in an out-of-band manor (such that a HTTP scanner wouldn't be able to detect the shared key). Then just hmac any message with that pre-shared key.

泪之魂 2024-10-24 23:28:41

听起来您需要对 PHP 中的“一次性密码”进行解释?

一次性便笺本
一次性密码本是一长串随机字母。这些字母与明文消息组合以产生密文。为了破译这条信息,一个人必须拥有一份一次性便笺簿的副本来逆转这一过程。一次性垫只能使用一次(因此得名),然后销毁。这是第一个也是唯一一个被证明牢不可破的加密算法。

要加密消息,您需要获取明文消息中的第一个字母,并将其添加到一次性密码本中的第一个随机字母中。例如,假设您正在加密字母 S(字母表中的第 19 个字母),一次性密码本会为您提供 C(字母表中的第 3 个字母)。将两个字母相加并减 1。当您将 S 和 C 加起来并减 1 时,您将得到 21,即 U。在此方法中对每个字母进行加密,如果相加结果超出数字,则字母表将绕到开头26(Z)。

要破译消息,您需要获取密文的第一个字母并从一次性密码本中减去第一个随机字母。如果数字为负数,则绕到字母表的末尾。

Sounds like you need an interpretation of the "One-Time Pad Cipher" in PHP?

One Time Pad
The one-time pad is a long sequence of random letters. These letters are combined with the plaintext message to produce the ciphertext. To decipher the message, a person must have a copy of the one-time pad to reverse the process. A one-time pad should be used only once (hence the name) and then destroyed. This is the first and only encryption algorithm that has been proven to be unbreakable.

To encipher a message, you take the first letter in the plaintext message and add it to the first random letter from the one-time pad. For example, suppose you are enciphering the letter S (the 19th letter of the alphabet) and the one-time pad gives you C (3rd letter of the alphabet). You add the two letters and subtract 1. When you add S and C and subtract 1, you get 21 which is U. Each letter is enciphered in this method, with the alphabet wrapping around to the begining if the addition results in a number beyond 26 (Z).

To decipher a message, you take the first letter of the ciphertext and subtract the first random letter from the one-time pad. If the number is negative you wrap around to the end of the alphabet.

智商已欠费 2024-10-24 23:28:41

对每条消息生成哈希值 (md5),并向其中添加微时间时间戳。

Make an hash (md5) out of each message and add the microtime timestamp to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文