掩码认证消息(Masked Authenticated Message),简称MAM,是IOTA最显著的特点之一。让我们来设想一下在这个布满小型物联网设备的世界上,它们的微工作、微观数据流和纳米支付遍布全球的情景。
IOTA的目标是成为未来社会最基本的层面,是当前最有远见的项目,它挑战了即将到来的范式转变。 MAM则是其核心驱动力,它通过使数据流和交易更便宜,更安全和无处不在,而将IOTA与其他分布式账本区分开来。
然而,尽管MAM在IOTA及其未来发展中具有极其重要的意义,但由于它仍处于发展阶段,所以在技术实施方面我们只能获得有限的信息。
这篇文章以一种易于理解的方式来讲解MAM,这样更多的人就可以更轻松的围绕这种下一代技术进行深入研究。
MAM频道(MAM Channel)
像Youtube和其他媒体一样,MAM也有频道。频道所有者可以发布新数据,观看者可订阅频道来获取可用的数据。这种所有权由IOTA通过Seed来实施和保护的。如果你把你的Seed告诉了别人,别人就有了在你的频道上发布任何消息的权限。再次说明,Seed在其81个trytes中保存所有的隐私和产权,切勿将其暴露并妥善保管。
频道模式(Channel Mode)
当在频道上发布新消息时,发布者可以有三种选项。Public(公共模式):每个人都可以查看。Private(私有模式):只有你(即种子所有者)可以查看。Restricted(受限模式):你可以将一个密钥告诉某个人,授权他成为查看者。这个密钥在源代码中被命名为sideKey。所以在这篇文章中,我也会沿用sideKey的称呼。而且,在任何模式下,root可以作为消息标识符被赋予给观看者以便从缠结中找到消息。
- Public:掩码消息使用 root 来解密 。
- Private:address=hash(root) 。掩码消息使用 root 来解密 。
- Restricted:address=hash(root) 。掩码消息使用 sideKey 来解密 。
消息链(Message Chain)
在IOTA协议中,像许多其他的加密技术一样,人们可以在交易上附加任意消息,而且它是免费的。但是,它限制发送者一次只能附加一个消息,并且不能在一个消息流上发布连续的相关消息。
例如,如果您想在不使用MAM的情况下,每15分钟发布一次当前的温度数据,就必须将每个消息发布到同一个地址。因为任何分布式帐本(包括Tangle)都是可以公开访问的,所以对于攻击者来说很容易识别每15分钟更新一次的地址,并用spam交易干扰它。即使你决定每次发布新数据时都要更改地址,你也需要跟踪所有的地址,就在线存储信息而言,监控它们的成本相对较高。
然而,由于MAM的消息链设计,用户可以保护他们的频道免受任何spam的干扰,并让他们免于管理累积地址。
MAM将每条消息发送到不同的地址,但有详细的有用信息来连接它们。在这条消息链上,一代传到下一代,旧消息总是引导新的,它的流动是单向的。
MAM Bundle的基本结构
MAM Bundle大致有两个部分,Signature Section和MAM Section ,详细细节将在文章后面解释。他们的数据是作为Bundle中交易的signatureFragment来被存储。 Signature用于MAM的所有权,并因此用于其有效性检查。MAM Section存储实际的掩码消息。
Address: MAM的存储位置
Address, 即存储掩码消息的地方,是从root散列得到的。 散列是一种复杂的计算方法,在这种计算中,人们无法通过研究output来猜测input了什么。
if (channel.mode !== ‘public’) {
// private, restricted mode
address = Crypto.converter.trytes(Encryption.hash(81, Crypto.converter.trits(mam.root.slice())));
} else {
address = mam.root;
}
注意: Paul Handy的文章显示受限模式地址(restricted mode address)= hash(root+sideKey) 。但是,如上面的源代码所示,address = hash(root) 。因此,在本文中,我将解释为受限模式下的address = hash(root) 。这可能与事实有出入,所以如果有人对此有详细的了解,请评论或与我联系。在此表示感谢。
公共模式(Public Mode)
root 是 address。root 是加密和解密的密钥。
nextRoot是连接下一条消息的指针。当一代掩码消息被解密时,明码消息(unmasked message)则包含用于查看者寻找下一代频道消息的nextRoot。举个形象的例子,就像您在第一个宝箱中找到打开第二个宝箱的钥匙。如此反复,我们可以从第一代开始跟踪链上的所有消息。如果你被授权访问中间代,你就可以从中间代开始继续向下一代推进,但你不能向后追溯查看过去的消息。
受限模式(Restricted Mode)
hash(root) 是address。sideKey是加密和解密的密钥。
主要思想与公共模式一样。sideKey仅用于解密掩码消息。没有sideKey的人可以通过root找到消息的位置,但是无法理解那里加载了什么。
频道的所有权
思考一下下面的例子:
韩梅梅刚刚在她的频道上发布了她的第一条消息,并希望李雷能够阅读她的帖子。所以,韩梅梅把她的root和sideKey给了李雷。李雷通过生成address(= hash(root) )来访问韩梅梅的消息,并使用sideKey对其进行解密。李雷喜欢韩梅梅的帖子,并表示“我还想读下一个!”。并且在他解密的当前消息中有nextRoot,并且可以从它生成下一个address。但是,他意识到韩梅梅尚未在下一个address发布下一条消息。李雷瞬间产生了一个邪恶的想法。他手上有nextRoot和sideKey。他可以把经过sideKey加密的消息发布到address hash(nextRoot),这样就可以劫持韩梅梅的频道。
你认为李雷上述的行为会成功吗? 从目前了解到的信息来看,完全没问题啊……这是否意味着MAM失败了?别担心,MAM的设计使得像李雷这样的人不能把频道搞乱。下一个要讨论的话题就是韩梅梅如何使她的消息链不被其他人编辑。
这里我们需要在MAM中签名。
基于Merkle tree的签名方案
基于Merkle tree的签名方案是MAM中使用的技术。感兴趣的人可以点击链接详细了解。
MAM Publish 101: root
root是Merkle tree的根。要得到root,首先必须创建Merkle tree,而Merkle tree是用Seed种出来的(创建的)。
Merkle tree具有整数参数start和size。它们表示从Seed生成的address的index。回想一下,在生成address时,我们将index作为参数之一(seed,index,security)。最近在这里解释过。
A、B、C、D是由index = 0,1,2,3生成的私钥。A’ B’ C’ D’是对应的address。
然后,A”,B”,C”,D”分别=hash(address)。到root之前,可以通过将A”,B”,C”,D”分队组合然后再次散列来将它们缩小。请注意,您无法从root获取前边的内容。
现在,我们得到了root。在公共模式下,此root直接用作MAM address,在其他模式下,address =hash(root)。
MAM Publish 102: MAM Section
MAM Section包含发布者想要发布的掩码消息,即他/她的原始消息,任意长度的ascii代码字符串。 但是,在被附加之前,应该将其转换为tryte(使用库函数toTrytes(ascii); // from asciiToTrytes.js ),并存储为message。
MAM Publish 102: MAM Section — nextRoot
要发布一代的掩码消息,必须生成两棵merkle tree。 第一棵树用于当前代,另一棵用于下一代。
对于创世代(即第0代),merkle tree,tree0具有参数start0和count(= 叶片数) 。 对于下一代(即第1代),merkletree,tree1 是由start1 = start0+count和count生成。
顺便说下,每个Merkle tree可以有不同的大小。
MAM Publish 102: MAM Section — Branch Index
Branch Index,branch_index,选自当前一代merkle tree的任意叶子的index。在下面的示例中,merkle tree已被创建为start=0和count=4,所以branch_index应该是0、1、2和3中的一个。
MAM Publish 102: MAM Section — Siblings
比方说,叶子A’是给定的,为了获得root,你需要有其他所有的叶子B’C’D’,但是,如果你不能访问它们,你怎么得到root?Siblings是一组互补的散列,通过与给定的叶子结合,可以产生root。请看下图。
这个图举例说明了branch_index=0的情况,其中只给出了A’。在这种情况下,B”和Hash(C”D”)都是获得root的必要条件。你不需要有其他的叶子。
在本例中,B”和Hash(C”D”)被称为A’的Siblings。在MAM中,它被称为branch_index=0的Siblings。不同的branch_index有不同的Siblings集合。
MAM Publish 102: MAM Section — completed
在MAM节中, message, nextRoot , branch_index和Siblings的混合 ,称为messageTrytes ,用root(Public mode)或sideKey(Restricted mode)加密。下图是MAM Section的限制模式加密的示例。
MAM Publish 103: Signature Section
正如我所提到的,对于MAM Section的有效性检查,发布者在Bundle中添加Signature 。Signature存储在交易的signatureFragment中,这些交易称为MAM Bundle中的Signature Section 。
MAM Publish 103: Signature Section — signing
掩码消息的签名由Private Key =key(seed, branch_index ,security) 。签名的数据是MAM Section的messageTrytes 。这里解释签名方案。
MAM Fetch
要获取掩码消息,在限制模式下需要的是root和sideKey 。
首先,从给定的root计算address。并搜索address的bundle,然后解密找到的bundle的MAM Section的messageTryte。解密密钥是公共模式的root,限制模式的sideKey。现在,我们有了message,nextRoot,branch_index,Siblings。
下一步是检查明码消息的有效性。现在,查看Signature section 。Signature section的签名用于验证Bunle的MAM section的messageTryte作为签名数据。验证过程在这里解释。
在验证过程之后,您得到的是address,它被用作merkle tree的index = branch_index的叶子地址,并与Siblings结合以计算树的root,名为temp_root 。
如果temp_root等于给定的root,那么这个明码消息是该频道的有效消息,如果不是,那么消息就不是由频道所有者(种子所有者)发布的。
Chainfork
MAM的消息链可以fork,而且很容易fork。对于您选择fork的一代,您只需使用不同的branch_index来发布消息。但是,在这一代中可以fork的分枝的上限是这一代merkle tree的大小。如果fork太多,新的分支index会溢出到下一代的branch_index。您可以在子链之间设置不同的sideKey和频道模式。
Snapshot
掩码消息存储在交易的signatureFragment中。因为在Snapshot之后会删除所有交易和零余额的地址,所以Snapshot之前的所有MAM都会被删除。
为了防止这种情况的发生,MAM存储在了Permanode中,它不会执行Snapshot。Permanode需要大容量的存储、带宽和高速访问性能,但目前缺少对permanode运营者的经济激励机制。我们的社区需要讨论应该如何维持并奖励IOTA的基础设施运营者以维持稳定。
MAM浏览器
首个基于Web的IOTA MAM浏览器发布了,地址:iota-mam-explorer.now.sh,你可以凭KEY来获取公共MAM流数据。测试KEY:O9OTU9GN9KHBWEBMPOOCSMDYAKIZTKONZUVUKVQUUZXG9UYCWONKNLKRO99KVFYYZEGLMOUYZMRRSCZYL。
以上翻译内容基于个人理解,如果您发现有误请在下方评论处留言或者联系微信Foxybloody告之我,非常感谢。
参考资料
MAM JS库 : https://github.com/iotaledger/mam.client.js
IOTA github : https://github.com/iotaledger/iota.lib.js
介绍MAM : https://blog.iota.org/introducing-masked-authenticated-messaging-e55c1822d50e
本文来自网络,本文观点并不一定代表我爱IOTA立场,转载请联系原作者。