【问题标题】:How to encrypt messages with NEAR's account system如何使用 NEAR 的账户系统加密消息
【发布时间】:2021-07-13 09:31:08
【问题描述】:

NEAR 的帐户可以有许多不同的密钥对访问同一个帐户。按键也可以更改和旋转。这意味着使用特定用户的公钥加密消息的默认方式不起作用。

为特定用户加密消息的最佳模式是什么?

【问题讨论】:

    标签: nearprotocol


    【解决方案1】:

    NEAR 帐户密钥不适用于此用例。

    一般来说,拥有多个设备的每个参与者都拥有端到端加密消息(在最具体的意义上是端到端加密聊天,但通常是任何交换加密消息的应用程序)并非易事。例如。出于某种原因,在 Telegram 中,私人聊天附加到设备上,而在其他设备上不可用。

    原因是这通常需要在设备之间共享私钥,而安全地做到这一点本身就是一个挑战。

    这是一个关于如何建立端到端加密聊天的逐字建议

    a) 每个参与者都可能从多个设备参与
    b) 消息不仅直接与某人共享,还与参与者的“组”共享。

    设计目标是发送消息应该是恒定的时间(不取决于目标用户使用的设备数量/发送消息的群组中的人数),而某些操作可以是线性的。

    计划将其作为库添加到 NEAR,但尚未开始工作,也未计划开始。

    提案

    问题陈述: 我们希望可以添加新成员和删除旧成员的群聊; 新成员能够在加入之前看到发布的消息是一项愿望清单功能; 老成员离开后应该看不到新消息; 用户应该能够使用多个设备并从所有设备查看所有群聊中的所有消息; 每条消息必须存储一次(不是每个组的参与者一次);

    建议的解决方案:

    1. 系统中有三种密钥对:账户密钥(不要与 NEAR 账户密钥混淆)、设备密钥和消息密钥。

    2. 每个帐户只有一个帐户密钥。它是在帐户首次使用该服务时生成的。

      account_keys:持久映射

    3. 第一次从设备访问聊天时(或每次擦除本地存储时),每个设备都有自己的设备密钥

      类 DeviceKey { 名称:字符串, device_public_key:公钥, encrypted_account_secret_key: EncryptedSecretKey?, }

      device_keys[帐户]:PersistentVector

      持久化向量是每个账户的,每个这样的持久化向量都包含设备公钥(设备私钥只存在于设备上),以及用这样的公钥加密的账户秘钥,如果秘钥没有被加密,则为null用这样的公钥加密过。

      管理设备密钥的方法有以下三种:

        addDeviceKey(device_public_key: PublicKey, name: string): void
    

    添加新密钥,并将 null 关联为对应的加密帐户密钥。

        removeDeviceKey(device_public_key: PublicKey): void
    

    删除设备密钥

    authorizeDeviceKey(device_public_key: PublicKey, encrypted_account_secret_key: EncryptedSecretKey): void
    

    设置设备密钥的加密帐户密钥。

    因此,用户的流程将是:

    a) 从新设备启动聊天,为其命名。
    b) 从其他已经拥有加密帐户密钥的设备打开聊天,进入设备设置并授权新设备。

    1. 所有消息键都存储在一个大的持久向量中:
        all_message_public_keys: PersistentVector<PublicKey>
    

    并且在所有其他地方都使用向量中的 u32 索引进行引用。 每个用户都知道一些消息密钥:

    encrypted_message_secret_keys[account]: PersistentMap<u32, EncryptedSecretKey>
    encrypted_mesasge_secret_keys_indexes[account]: PersistentVector<u32>
    

    地图和矢量是每个帐户的。仅需要该向量,以便当用户更改其帐户密钥时,我们知道我们需要重新加密的所有消息密钥。 密钥使用帐户密钥加密。

    每个通道在每一时刻都有一个与之关联的消息密钥,尽管密钥可能会在通道的整个生命周期内发生变化。

    channel_public_keys: PersistentMap<u32, u32>
    

    其中键是频道 ID,值是消息键 ID。

    1. 每条消息都有一个 u32 字段,指示用于加密它的消息密钥。如果未加密,则值为 u32::max。每当向频道发送消息时,都会使用当前频道消息密钥对其进行加密。

    2. 流程如下:

      当使用初始参与者集创建通道时,通道的创建者创建消息密钥对,使用每个参与者的帐户密钥加密密钥,并调用

        createChannel(channel_name: string,
                      accounts: AccountId[],
                      message_public_key: PublicKey,
                      encrypted_message_secret_keys: EncryptedSecretKey[])
    

    注册消息密钥,将加密的密钥添加到相应的集合中,并创建通道。

    如果需要添加新用户,addUserToChannel(account: AccountId, encrypted_message_secret_key) 会将用户添加到频道用户列表中,并授予他对最新消息访问密钥的访问权限。

    如果需要删除用户,deleteUserFromChallen(account: AccountId) 会删除该用户。在这种情况下,或者如果通道参与者认为他们的消息密钥被泄露,他们会调用

    updateChannelMessageKey(message_public_key: PublicKey, 
                            encrypted_message_secret_keys: EncryptedSecretKey[])
    

    请注意,由于每条消息都有关联的密钥,并且频道参与者没有失去对旧消息密钥的访问权限,因此现有的频道参与者将能够读取所有历史记录,而无需重新加密它.但是,加入频道的新用户只能看到自上次更新密钥以来的消息。

    1. 当用户需要更新帐户密钥时,他们需要:
      a) 使用所有设备密钥对其进行加密;
      b) 用新的帐户密钥加密他们所有的消息密钥;
      c) 将 (a) 和 (b) 提供给将更新相应集合的合约方法。

      完成此过程后,用户将可以使用新帐户密钥访问来自所有设备的所有旧消息。

    【讨论】:

    • 这是一个很好的实现,但我有点指的是 KISS 工作人员版本。就像扫描 QR 码或输入助记符/密钥本身一样,只需访问另一台设备上的加密消息即可。妥协安全是可以的,因为这只是工作人员的版本。没有什么敏感的东西会丢失。当然,如果一个人正在设计一款金融应用程序或处理敏感的政治/法律问题,那么这种密钥管理是必不可少的。
    【解决方案2】:

    是否有可能为此获得一些伪代码?我担心的另一个问题是这些应用程序私钥存储在哪里?通常我习惯于有一个私钥的系统,我会备份它或使用助记符。现在,当我登录到另一台设备时,我会恢复该密钥。

    如何在多个设备上镜像私钥?

    另一方面,查询链以获取用户的应用程序的特定公钥(甚至可能带有标签)是有意义的。

    【讨论】:

      【解决方案3】:

      确实没有默认的方法来做到这一点。 最简单的方法是,如果特定应用程序(例如聊天需要加密消息)是要求用户“使用 NEAR 登录”——这将在应用程序端创建一个新的密钥对,并在用户帐户中为应用程序授权此公钥。

      现在任何其他用户都可以扫描收件人的帐户并找到为此应用授权的密钥并将其用于加密。这与 Telegram 秘密聊天的行为类似,只能在启动聊天的单个设备上解密。

      要使这项工作跨设备(域、应用程序)工作,可以创建一个密钥对,其中公钥是已知的并附加到给定帐户。私钥也存储在链上,但使用来自不同设备的所有访问密钥进行加密。添加新设备/应用时,现有应用需要对此进行授权,这将允许在此会话中解密私钥并使用此会话的访问密钥重新加密。

      【讨论】:

        猜你喜欢
        • 2011-01-22
        • 1970-01-01
        • 2015-12-17
        • 2013-04-19
        • 2022-08-04
        • 2014-11-12
        • 2016-05-07
        • 2013-09-25
        相关资源
        最近更新 更多