Skip to content

3.业务消息

oxogenesis edited this page Jul 27, 2019 · 8 revisions

系统描述中介绍了所有消息的基本4字段

  • Action:消息类型
  • Timestamp:消息生成时间
  • PublicKey:消息生成账号的公钥
  • Signature:消息的签名

及定向消息的必备字段

  • To:消息接收账号地址

对一条消息的终极3问:

  • 本条消息是那个账号什么时间生成的?
    生成账号是可被证明的,不可伪造不可抵赖的
    生成时间只供参考,不可被证明
  • 本条消息是要干什么的?
    Action告知系统本条消息的类型
  • 本条消息要发给那个账号?
    To告知系统本条消息应被转发给那个账号,无To字段的为非定向消息

区块链的本质

直接给出我的答案:区块链是一种只增不改不删多副本的逻辑数据库

  • 只增:可以向数据库里写入一条条记录(区块),每个区块都有序号(sequence),每个区块都引用前一区块的散列值(pre_hash)
  • 不改:当第n+1个区块被写入时,前n个区块都不能被修改,如果如果第n个区块被修改,第n+1个区块所引用的第n个区块的散列值就变了,第n+1个区块就失效了
  • 不删:同理,如果第n个区块缺失,则n之后的区块都无法被证明是有效的区块
  • 多副本:区块可以被单独的、分散的存储在不同的设备上
  • 逻辑数据库:依据校验规则,区块在逻辑上是一个新块指向旧块、新块传承旧块的数据链

比特币(BTC)就是利用区块链这种只增不改不删多副本的逻辑数据库的特性,分布式的存储到大量的记账节点中,使得任一节点都无法修改、删除账本中的历史数据,保障了账本不可篡改、不可伪造。

借鉴区块链的思想,来设计公告、聊天两类业务需要的消息、消息需要的字段

公告业务

公告是个体愿意向所有其他个体公开发布的信息。
因此,公告消息本身是不带To字段,应该有内容,吸收区块链属性序号前消息散列值,具体如下:

  • Action:201
  • Sequence:公告序号
  • PreHash:前公告散列值
  • Content:公告内容
  • Timestamp
  • PublicKey
  • Signature

这样单个账号的一系列公告就区块链化了,公告序号从1开始,每次加1,第n+1条公告引用第n条公告的散列值,每条公告都有签发账号的签名。
签名保证公告消息的完整性和与签发账号的关联性。

出于间接传播和交互的考虑,再增加一个字段,用于引用其他公告

  • Quote:是一个0到8个元素的数组

每个元素用于明确一条公告消息,包含3个字段:

  • Address:公告的发布账号
  • Sequence:公告的序号
  • Hash:公告的散列值

现在有了公告消息,再构在两个消息:

公告请求消息

  • Action:202
  • Address:公告的发布账号
  • Sequence:公告序号
  • To:请求接收账号地址
  • Timestamp
  • PublicKey
  • Signature

公告响应消息

  • Action:203
  • Bulletin:公告消息
  • To:响应接收账号地址
  • Timestamp
  • PublicKey
  • Signature

流程

  1. 账号在本地系统生成公告消息(可以引用本地存储的公告消息),等待其他账号来请求公告消息

  2. 账号向其他账号发送公告请求消息,其他账号查询本地系统是否存在Address和Sequence相符的公告,如果有,则返回公告响应消息

    公告请求的两种模式:

    • 对于关注的账号,本地已存储了该账号从1到n的公告,请求序号n之后的公告
    • 对于已获取公告B中引用的公告Q,从B公告签发账号获取被引用公告Q(使用公告Q的账号地址和序号)
  3. 请求账号收到并校验无误后存储到其本地系统

虽然公告消息由其背后的账号签发,公告消息一旦被其他账号获取,即便原签发账号不在线或者被毁灭,其公告消息依然可以通过被引用的方式在网络上继续传播。
原签发账号既无法收回公告消息,也无法否认公告消息是自己签发的,也无法重发一条相同序号的公告,如果网络上出现同一账号签发的同序号不同内容的两条公告,说明该公告消息的签发账号已经不可信了,自己说过的话,自己得认

一条公告是否被传播,完全靠一个个账号背后的个体决定,而非某种权威或特权决定。

加密聊天业务

消息加密

聊天消息也是在账号的本地系统中生成,由远程系统中介转发给对方账号。
远程系统通常是不受控制的,为了防止它作恶,需要对消息内容进行加密。
这里用到了Diffie–Hellman密钥交换算法,原理简单描述如下:

本地系统A生成pkA和skA
本地系统B生成pkB和skB
A和B通过远程系统交换pkA和pkB

本地系统A可以同skA和pkB算出加密密钥x
本地系统B可以同skB和pkA算出加密密钥x
但是远程系统只知道pkA和pkB,算不出加密密钥

AES256对称加密算法本身具有很高的加密强度,但是通常使用对称加密算法,需要定期更换加密密钥,因此两个账号协商加密密钥时也应该考虑时间段的问题。

密钥协商消息具体如下:

  • Action:204
  • Division:一天分成多少个时间块,比如将一天分成3块,则每一块是8小时
  • Sequence:从某一纪元开始,按Division划分,时间块的序号
  • DHPublicKey:本方的pk
  • Pair:对方的pk,如果为空,说明本方无法计算出会话加密密钥,还不能开始聊天,如果不为空,说明本方已经计算出会话加密密钥,本方已就绪,当本方和对方都就绪时才可以开始聊天
  • To:聊天对方的账号地址
  • Timestamp
  • PublicKey
  • Signature

聊天消息

参照公告消息,出于同步和区块链化的考虑,聊天消息也应该包含聊天消息序号前聊天消息散列值
另外,为了通知对方哪些消息已经接收了,增加字段PairHash
具体如下:

  • Action:205
  • Sequence:聊天消息序号
  • PreHash:前聊天消息散列值
  • PairHash:是一个0到8个元素的数组,每个元素为一条未确认接收的对方消息的散列值
  • Content聊天消息内容,为加密后的消息内容
  • To:聊天对方的账号地址
  • Timestamp
  • PublicKey
  • Signature

同步请求

由于消息始终存储在本地系统,无法保证每个账号的本地系统都始终在线,存在发送方本地系统的消息已经到了第n+m条了,但接收方本地系统接收的消息只到第n条,需要聊天同步消息告诉对方已接收到的消息最大序号:

  • Action:206
  • CurrentSequence:已接收消息的最大序号
  • To:聊天对方的账号地址
  • Timestamp
  • PublicKey
  • Signature

流程

检查本方和对方在此刻对于的时间块的会话加密密钥是否就绪,如果未就绪,则开始协商会话加密密钥
如就绪,则可以开始收发加密后的聊天消息。
如收到消息的序号为无效消息(序号或散列值与最近一条消息不对应),则向对方发送同步请求,获取缺失的消息。

没有系统能够监控在物理空间上接触的两个非特定个体之间的信息交互,同理网络空间也应如此。

Clone this wiki locally