你能验证事件的发送者没有被伪造吗?
Can you verify that the sender of an event hasn't been faked?
假设我有一个聊天室并且每个人都订阅了频道:private-chatroom
任何人都可以发送事件 client-message
,其中包含如下数据:
{
sender_user_id: 1,
text: "Hello everyone!"
}
其他用户会收到该事件并显示该消息及其收到的 sender_user_id
(按面值计算)。
你如何验证它真的是由 user #1
发送的,而不必在每次有人发送消息时都涉及我的服务器。
P.S。我正在使用 auth,它只允许登录用户发送消息,但之后没有进一步验证来验证伪造的用户 ID
在你的场景中,你不能。即使添加身份验证签名也无济于事,因为我可以伪装成某个尚未登录的用户(例如,如果用户 ID 是可预测的)。再一次,我需要考虑重放攻击之类的事情,所以我还需要在身份验证过程中包含一个时间戳。
为了能够信任系统,我需要一个额外的服务来映射发件人 ID 及其 public 密钥。然后,每当我收到来自用户 X 的消息并且我没有他的 public 密钥时,我可以通过发送 id=X 并获取带有到期日期的 public 密钥来询问受信任的服务器(我可以缓存之后),并使用它来验证消息体和时间戳,并验证时间戳是否大于上次从 X:
接收到的时间戳
1234567: X: hash=0xdeadbeef: "Debit me USD 50,74"
1234511: Y: hash=0xdeafd00d: "OK, thanks"
1234567: X: hash=0xdeadbeef: "Debit me USD 50,74"
1234515: Y: hash=0xbaadf00d: "Wait, what?"
(这里 X 和 Y 的时钟故意不同步 - 重要的是它们都是单调递增的)。
因此您需要修改服务器行为或添加一个辅助的、受信任的身份验证服务器,以及修改客户端协议(时间戳、哈希)和行为(密钥验证, 签名...)。两台服务器之间的连接并非微不足道:密钥服务器必须从主服务器访问身份验证数据,并且 信任 连接到它的任何人。
在我看来,最简单的方法是聊天服务器根据用户身份验证覆盖发件人 ID。这应该是微不足道的,实际上我希望事情从一开始就以这种方式工作。
请注意,为了使身份验证服务器能够提供可靠信息,聊天服务器上的必要工作不可忽略 - 即,辅助服务器根本不是 "zero intervention on the chat server"。实际上,它比仅在聊天服务器部分的消息中注入经过身份验证的用户 ID 更复杂。主要区别是现在您只与身份验证模块交互,在某些情况下,可能更容易做到:
How could you verify it was really sent by user #1 without having to involve my server every time someone sends a message.
当用户首次在主聊天服务器上创建帐户时(因此在该用户的生命周期中只有 一次),聊天服务器通过可信连接与密钥服务器连接,并且请求用户 12345 的密钥对。密钥服务器创建密钥对并将私钥发送到聊天服务器,聊天服务器将其提供给用户。聊天服务器不需要做任何进一步的事情。客户端现在可以为每条消息添加时间戳和签名哈希。谁想要验证消息,谁只需要与密钥服务器交互,并且每个发送者只需要一次。
假设我有一个聊天室并且每个人都订阅了频道:private-chatroom
任何人都可以发送事件 client-message
,其中包含如下数据:
{
sender_user_id: 1,
text: "Hello everyone!"
}
其他用户会收到该事件并显示该消息及其收到的 sender_user_id
(按面值计算)。
你如何验证它真的是由 user #1
发送的,而不必在每次有人发送消息时都涉及我的服务器。
P.S。我正在使用 auth,它只允许登录用户发送消息,但之后没有进一步验证来验证伪造的用户 ID
在你的场景中,你不能。即使添加身份验证签名也无济于事,因为我可以伪装成某个尚未登录的用户(例如,如果用户 ID 是可预测的)。再一次,我需要考虑重放攻击之类的事情,所以我还需要在身份验证过程中包含一个时间戳。
为了能够信任系统,我需要一个额外的服务来映射发件人 ID 及其 public 密钥。然后,每当我收到来自用户 X 的消息并且我没有他的 public 密钥时,我可以通过发送 id=X 并获取带有到期日期的 public 密钥来询问受信任的服务器(我可以缓存之后),并使用它来验证消息体和时间戳,并验证时间戳是否大于上次从 X:
接收到的时间戳1234567: X: hash=0xdeadbeef: "Debit me USD 50,74"
1234511: Y: hash=0xdeafd00d: "OK, thanks"
1234567: X: hash=0xdeadbeef: "Debit me USD 50,74"
1234515: Y: hash=0xbaadf00d: "Wait, what?"
(这里 X 和 Y 的时钟故意不同步 - 重要的是它们都是单调递增的)。
因此您需要修改服务器行为或添加一个辅助的、受信任的身份验证服务器,以及修改客户端协议(时间戳、哈希)和行为(密钥验证, 签名...)。两台服务器之间的连接并非微不足道:密钥服务器必须从主服务器访问身份验证数据,并且 信任 连接到它的任何人。
在我看来,最简单的方法是聊天服务器根据用户身份验证覆盖发件人 ID。这应该是微不足道的,实际上我希望事情从一开始就以这种方式工作。
请注意,为了使身份验证服务器能够提供可靠信息,聊天服务器上的必要工作不可忽略 - 即,辅助服务器根本不是 "zero intervention on the chat server"。实际上,它比仅在聊天服务器部分的消息中注入经过身份验证的用户 ID 更复杂。主要区别是现在您只与身份验证模块交互,在某些情况下,可能更容易做到:
How could you verify it was really sent by user #1 without having to involve my server every time someone sends a message.
当用户首次在主聊天服务器上创建帐户时(因此在该用户的生命周期中只有 一次),聊天服务器通过可信连接与密钥服务器连接,并且请求用户 12345 的密钥对。密钥服务器创建密钥对并将私钥发送到聊天服务器,聊天服务器将其提供给用户。聊天服务器不需要做任何进一步的事情。客户端现在可以为每条消息添加时间戳和签名哈希。谁想要验证消息,谁只需要与密钥服务器交互,并且每个发送者只需要一次。