pubnub,如何识别发件人?

pubnub, how to identify the sender?

从pubnub 收到消息时,没有发件人信息。如何知道这是来自 visitorA 还是 visitorB 的消息?网络上有发件人在邮件中发送他的名字的例子,但如何知道他没有冒用别人的身份?

这里是一个聊天界面的例子:

<html>
  <body>
    <form id="message_form">
      <input id="message_input" type="text"/>
    </form>
    <div id="chat"></div>
    <script src="http://cdn.pubnub.com/pubnub-3.7.1.min.js"></script>
    <script>
      var pubnub = PUBNUB.init({
        publish_key: 'demo',
        subscribe_key: 'demo'
      });

      pubnub.subscribe({
        channel: 'chat',
        message: function(message){
          var div = document.createElement("div");
          div.textContent = message;
          var chat = document.getElementById("chat");
          chat.appendChild(div);
        }
      });

      var form = document.getElementById("message_form");
      form.onsubmit = function(e) {
        var input = document.getElementById("message_input");
        pubnub.publish({
          channel: 'chat',
          message: input.value
        });
        input.value = '';
        e.preventDefault();
      };
    </script>
  </body>
</html>

聊天用户识别

您可以通过创建唯一 ID 以及 姓名识别发件人附加到聊天对话的消息负载。这类似于 IRC 策略,但更简单一些。

var user_id      = PUBNUB.uuid();
var user_name    = name.value;
var user_message = input.vaule;

这是一个完整的示例,其中包括用于 UserName 输入的 HTML 元素。另请注意,我添加了一个 safe_text() 方法来防止 XSS 攻击。

<form id="message_form">
  Name: <input id="name_input" value="John" type="text"/><br>
  Message: <input id="message_input" value="Hi" type="text"/><br>
  <input type="submit" value="send">
</form>
<div id="chat"></div>
<script src="http://cdn.pubnub.com/pubnub-dev.js"></script>
<script>
  var userid = PUBNUB.uuid();
  var pubnub  = PUBNUB({
    publish_key   : 'demo',
    subscribe_key : 'demo',
    uuid          : userid
  });

  function safe_text(text) {
    return (''+text).replace( /[<>]/g, '' );
  }
  pubnub.subscribe({
    channel: 'chat',
    message: function(message){
      var div = document.createElement("div");
      div.textContent =
        safe_text(message.name) + ": " +
        safe_text(message.text);

      var chat = document.getElementById("chat");
      chat.appendChild(div);
    }
  });

  var form = document.getElementById("message_form");
  form.onsubmit = function(e) {
    var input = document.getElementById("message_input");
    var name  = document.getElementById("name_input"); 

    pubnub.publish({
      channel: 'chat',
      message: { name : name.value, text : input.value, userid :userid }
    });
    input.value = '';
    e.preventDefault();
  };
</script>

虽然此演示为您提供了一个快速简单的入门应用程序,但您还需要添加更多 enhanced chat security and chat authentication systems

有关构建聊天应用程序的其他资源,请查看 Build Real-time Chat Apps in 10 Lines of Code guide and also Building A Basic Chat Application

聊天访问控制层 ACL

您需要添加 Security ACL Access Control Layer。使用 PubNub 访问管理器 (PAM),您可以通过使用访问令牌授予用户权限来控制谁可以访问。

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Grant Chat Access to Secured Conversations
// All server-side data is stored according to defined security policies.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
var pubnub = PUBNUB({ 
    publish_key:   "PUBLISH_KEY", 
    subscribe_key: "SUBSCRIBE_KEY", 
    secret_key:    "SECRET_KEY"
})
pubnub.grant({
    channel  : "CHANNEL",
    callback : receiver,
    error    : receiver,
    ttl      : 60, // Minutes
    read     : true,
    write    : true,
    auth_key : "AUTH_KEY"
});

建议运行在您自己的数据中心服务器等可信系统上使用此级别的ACL代码。

Sending/Receiving 安全加密消息

PubNub 客户端库提供 built-in 高级加密标准 (AES) 256 位加密。要使用消息加密,只需在初始化时使用 cipher_key。

使用 TLS 和 ssl 标志启用传输层加密。

然后照常publish/subscribe。

var pubnub = PUBNUB({
    subscribe_key: 'sub-c-f762fb78-...',
    publish_key: 'pub-c-156a6d5f-...',
    ssl: true,
    cipher_key: 'my_cipherkey'
});

消息发件人身份验证

将用户信息附加到每条消息中是一种高效的方法,并在您的应用程序中提供了非常强大的灵活性。然而,恶意用户可能会试图欺骗用户的身份并因此冒充其他用户。在示例应用程序中,我们展示了通过更改 "message_form" 字段中的姓名很容易冒充任何人。这与您在电子邮件和 SMTP 中遇到的情况相同,在这种情况下,任意电子邮件 header 模拟都是可能的,除非您提供一种方法来验证发件人的身份。有解决办法!

数字签名是带有消息有效负载关键组件的嵌入式安全加密散列的指纹,可选地包括盐(有时是时间戳),然后 signing/encrypting 带有用于验证身份的非对称密钥寄件人。此过程用于阻止欺骗者和冒充者。

A digital signature is a mathematical scheme for demonstrating the authenticity of a digital message or document.

聊天应用程序的消息验证

首先假设只有聊天用户被授予访问权限,并且他们可以使用 PubNub 访问管理器实现中可用的 grantrevoke 技术发布和订阅聊天频道。 这里的挑战是,在群聊室中,您的聊天用户已被授予 auth_tokens 但他们仍然可以冒充频道上的其他聊天用户。

这里的目标是在客户端收到消息时验证两件事。

  1. 发件人身份。
  2. 消息的完整性。

使用非对称加密,您可以通过创建数字签名 为用户的消息提供一层验证和安全保护。有效的数字签名使收件人有理由相信消息是由已知发件人创建的,发件人不能否认已发送消息(身份验证和 non-repudiation),并且消息在传输过程中未被更改(完整性) ).数字签名通常用于金融交易和面向消息的通信,例如电子邮件和 聊天 以及在检测伪造或篡改很重要的其他情况下。

您将首先向每个聊天用户发出一组密钥,服务器生成,使用public-key(非对称)算法,例如ECC/RSA 用户登录后通过您的服务器。我推荐 ECC,因为密钥大小比具有相当加密强度的 RSA 小得多。聊天室中的每个聊天用户都会通过安全的只读 side-channel 通知其他聊天用户的 public 密钥。您的用户只能从您的服务器的受信任和安全环境控制的 public READ-ONLY 通道接收 Public 密钥。您的服务器将能够将每个用户的 Public 密钥写入此 READ-ONLY 频道。您的用户将从该频道阅读。

您的用户可以在加入聊天室之前通过 PubNub 历史调用接收彼此的 Public 密钥。他们还应该打开对同一频道的订阅,以获取加入聊天室的新聊天用户的 public 密钥。

除经过验证的所有者外,用户的私钥不得暴露给任何人。这可以在 email/password sign-on 上完成,您可以在他们 log-in.

后立即将私钥发送给经过验证的用户

发送带有附加数字签名的聊天消息

{ userId: 123456,
profilePic: "http://www.chats.com/user1234.jpg",
message: "Hello World",
signature: "tnnArxj06cWHq44gCs1OSKk/jLY" }

您将通过连接以下基本字符串 (userId+profilePic+message) 来创建签名。接下来您需要使用 SHA1(signature_base_string)SHA256(signature_base_string) 计算消息摘要。现在哟可以使用此加密生成的散列通过 ECC/RSA 非对称算法使用用户的私钥进行签名。

现在如上例所示将此数字签名附加到聊天消息,然后进入 聊天室消息验证的最后阶段

聊天室消息验证

订阅聊天室频道后,您将收到用户发送的带有数字签名的聊天消息。您将使用此签名来验证聊天消息的真实性。如果该消息是企图欺骗,您将完全删除该消息。

// Digitally Signed Chat Message
{ userId: 123456,
profilePic: "http://www.chats.com/user1234.jpg",
message: "Hello World",
signature: "tnnArxj06cWHq44gCs1OSKk/jLY" }

要验证签名,您将通过连接以下基本字符串 (userId+profilePic+message) 来创建签名。接下来您需要使用 SHA1(signature_base_string)SHA256(signature_base_string) 计算消息摘要。现在使用聊天用户的 public 您已经拥有的用户 ID 123456 密钥,您可以 Verify/Decrypt 数字签名来获取您刚刚生成的原始消息摘要,这也是由发件人创建的。

比较当前消息摘要和原始消息摘要。如果它们相同,则消息是真实的,并且您已通过数字签名使用 消息验证 成功验证了发件人的消息。如果摘要不匹配,则为虚假消息,您可以忽略冒充者。

创建 PKI Public 使用 PubNub 的密钥基础设施

您需要一种通过 read-only PKI 安全传输 public 密钥 的方法。 PubNub 为您提供了一种为您的聊天用户公开 secure read-only PKI 列表的方法。重要的是要注意 PKI 需要非对称密钥算法,如 ECC 或 RSA。此外,我们正在使用这些加密算法来创建数字签名而不是加密数据。这意味着我们将能够通过使用 public 密钥成功解密签名并验证加盐签名字符串匹配来识别和验证发件人。

  1. Public 密钥 用作解密密钥验证密钥 .
  2. 私钥用作加密密钥签名密钥.

请务必注意,您应该只打印从 Public 密钥可信来源检索到的用户名,而不是从消息内容中检索到的用户名。消息内容仅用于签名和验证身份。如果更改了身份,则必须使用 PubNub 的广播机制以及用于安全授权的存储和回放通过 PKI 进行中继。

Access tokens, Identity Name/Photo and Asymmetric Keys must only be generated from trusted execution environments on your servers and relayed over PubNub's Authorized Read-only PKI data channels.

在最新的 PubNub SDK (v4) 中,发布者 UUID 现在包含在订阅响应中。

{
    actualChannel: null,
    channel: "my_channel_1",
    message: "Hello World!",
    publisher: "pn-58e1a647-3e8a-4c7f-bfa4-e007ea4b2073",
    subscribedChannel: "my_channel_1",
    subscription: null,
    timetoken: "14966804541029440"
}