# IOTA: MAM Eloquently Explained (中譯) 原文:[IOTA: MAM Eloquently Explained](https://medium.com/@abmushi/iota-mam-eloquently-explained-d7505863b413) MAM,Masked Authenticated Message,是IOTA最出色的特性之一。 讓我們來推測這個充滿了小型物聯網設備的世界,他們的小型工作,微觀數據流和奈米支付在全球各地流傳。 IOTA 的目標是成為這樣一個社會的基礎層,它是當前最具挑戰性的項目,它挑戰了即將發生的轉變範例。 而 MAM 是其核心推動力,它通過使數據流和交易更便宜,更安全和無處不在,將IOTA 與其他分佈式賬本區分開來。 然而,儘管 MAM 在IOTA及其未來發展中具有極其重要的意義,但由於它仍處於發展階段,所以在技術實施方面只能獲得有限的信息。 這篇文章盡可能以可理解的方式展示它,讓更多的人能夠圍繞這種跨世代的技術。 MAM Channel ------ 就像 Youtube 和其他媒體一樣,MAM 也有 Channel,所有者就像發布者一樣,而觀看者就如同訂閱者。 觀看者訂閱頻道以獲取可用的數據。頻道所有者在自己的頻道上發布新數據。所有權透過 IOTA Seed 來實現和保護。 如果你告訴別人你的種子,他們可以在你的頻道上發布他們的任何消息。重複,Seed 將所有的隱私和財產存於 81 trytes 內。切勿將其暴露並妥善保管。 Channel Mode ------ 在頻道上發布新訊息時,發布者有三種選項。 **Public:** 每個人都可以查看,**Private:** 只有你(即 Seed 所有者)可以查看,而 **Restricted:** 你可以通過告訴他們一個密鑰來指定你的查看者。 該密鑰在程式碼中被命名為**sideKey**。 所以,在這篇文章中,我也會稱這個關鍵的密鑰為 **sideKey**。 而且,對於任何模式,作為訊息識別碼的 **root** 被提供給觀看者以便從 Tangle 中找到消息。 >Public: Masked-message 使用 root 解密 Private: address=hash(root). 被屏蔽的消息使用root 進行解密。 Restricted: address=hash(root). 被屏蔽的消息使用 sideKey 進行解密。 Message Chain ------ 在 IOTA 協定中,像許多其他密碼一樣,人們可以將任意消息附加到交易 (transaction) 中。 但是,IOTA 完全不用費用!然而,它的限制是,發送者一次只附加一條消息,並且不能發布具有任意上下文的連續相關消息。 例如,如果您想每 15 分鐘發布一次當前溫度數據,而不使用 MAM,那就必須將每條消息發佈到相同的地址 (address)。 因為任何分散式分類帳包括 Tangle 都可以公開存取,所以對於攻擊者來說很容易識別每 15 分鐘更新一次的地址,並以垃圾交易 (spam transactions) 干擾。 即使您每次發布新數據都決定更改地址,但您必須跟踪所有地址。 就線上存儲信息而言,監視它們相對昂貴。 然而,MAM 由於其訊息鏈 (Message Chain) 的設計,我們可以保護我們的頻道 (channel) 避免受任何令人不安的垃圾郵件干擾,並讓我們免於管理累積地址。 MAM 將每條訊息發佈到不同的地址,但使用連接它們的詳細信息。 在這條訊息鏈上,一代到下一代,舊訊息總是會導引至新訊息。流程是單向的。 Basic Structure of MAM Bundle ------ MAM 捆綁 (MAM bundle) 大致有兩個部分,簽名部份 (**Signature section**) 和 MAM 部分 (**MAM Section**),每個細節將在本文稍後介紹。 他們的資料儲存在 transaction bundle 的 **signatureFragment** 中。 簽名用於宣示 MAM 的所有權和其有效性檢查 (validity checking)。 MAM 部分 (MAM section) 則用來存儲實際的屏蔽訊息。 ![](https://i.imgur.com/7AzVsEo.png) Address: Where MAM is being stored ------ Address, 屏蔽訊息的儲存處,這是由 hash(root) 產生的。 Hashing 是一個複雜的計算,人們無法透過輸出,來猜測輸入是什麼。 ``` if (channel.mode !== 'public') { // private, restricted mode address = Crypto.converter.trytes(Encryption.hash(81, Crypto.converter.trits(mam.root.slice()))); } else { address = mam.root; } ``` **Notice:** > Paul Handy 的[文章](https://blog.iota.org/introducing-masked-authenticated-messaging-e55c1822d50e)顯示了 restricted address = hash (root + sideKey) 。 但是,如上面的程式碼所示,address = hash (root)。 因此,在本文中,我將解釋為 address = hash (root) 作為 restricted mode。 這可能與事實有所不同,所以如果有人對此有詳細的了解。 請評論或與我聯繫。 我很感激。 Public Mode ------ > root 是 address。root 是加密和解密的鑰匙。 ![](https://i.imgur.com/lT3UwBk.png) nextRoot 是連接下一條訊息的指標。 當一代的屏蔽訊息被解密時,未屏蔽的訊息包含用於訂閱者尋找位於頻道內下一代的訊息的 nextRoot。簡而言之,就像你在第一個寶箱中找到打開第二個寶箱的鑰匙。 反复地,人們可以追踪直到創世頻道上的所有信息。 如果你被賦予中間世代,你可以從這一點開始閱讀連鎖。 你不能追溯查看過去的消息。 Restricted Mode ------ > hash(root) 是 address. sideKey 是加密和解密的鑰匙。 ![](https://i.imgur.com/Etknfh3.png) 主要意思與 Public mode 一樣。 sideKey 僅用於解密被屏蔽的訊息。 沒有 sideKey 的人可以用 root 找到訊息的位置,但無法理解那裡加載了什麼。 Ownership of Channel ------ 考慮以下情況: Alice 剛剛在她的頻道上發布了她的第一條訊息,並希望 Bob 閱讀她的訊息。 所以,Alice 給了 Bob 自己的 root 和 sideKey。 Bob 通過生成 Address (= hash(root)) 來查看她的訊息,並使用 sideKey 對其進行解密。Bob 喜歡 Alice 的訊息,並「很想讀下一則!」。 並且他在解密的當前訊息中具有 next root,並且可以生成下一個 Address。 但是,他意識到 Alice 尚未在下一個 Address 發布下一條訊息。 Bob 突然變得邪惡。 他有 next root 和 sideKey。 他可以將使用 sideKey 加密的消息發佈到地址 hash(nextRoot)。 他可以劫持 Alice 的頻道。 你認為它會起作用嗎?從目前解釋的信息來看,沒有矛盾。 ... 但是,這是 MAM 的失敗。 別擔心,MAM 的設計使得像 Bob 這樣的人不會混淆頻道。 下一個要討論的話題是 Alice 如何保護她的訊息鏈不被其他人編輯。 這裡我們需要在 MAM 中簽名。 Merkle tree based signature scheme ------ [基於 Merkle tree 的簽名 schema](https://www.imperialviolet.org/2013/07/18/hashsig.html) 是 MAM 中使用的技術。 如果趕興趣的話請點開連結獲取更多資訊。 MAM Publish 101: root ------ root 是 Merkle tree 的根。 要獲得 root,首先必須創建 Merkle tree。 而 Seed 則是被用來創建 Merkle tree。 Merkle tree 具有整數參數代表起點 (start) 和大小 (size)。這些表示從 Seed 生成的地址索引。回想一下,當生成地址時,我們將索引作為參數之一(種子,索引,安全性)。 最近期的解釋在[這裡](https://medium.com/@abmushi/iota-signature-and-validation-b95b3f9ec534)。 跟著 A,B,C,D之後是分別由索引= 0,1,2,3 生成的私鑰。 而 A',B',C',D' 是相應的地址。 ![](https://i.imgur.com/ExykAVZ.png) 然後A“,B”,C“,D” 是 hash(address)。 最多可以根據每個對的 hash 組合將它們縮小。 請注意,您無法從 root 獲取前一個。 現在,我們得到了 root。 在 Public mode 下,此 root 直接作為 MAM addrss ,在其他模式下,address= hash(root)。 MAM Publish 102: MAM Section ------ MAM section 包含發布者將要發布的掩碼訊息,他/她的原始訊息,任意長度的 ascii code 字串。 但是,在連接之前,它應該轉換為 tryte(使用函式庫 `toTrytes(ascii); //從asciiToTrytes.js`),並存儲為訊息 (`message`)。 MAM Publish 102: MAM Section — nextRoot ------ 要發布一代的屏蔽訊息,必須生成兩個 merkle tree。 第一棵 tree 用於當代,另一棵用於下一代。 對於 Genesis 世代(即第 0 代),merkle tree 的tree0 具有參數 start0 和 count(=樹葉數)。 對於下一代(即第 1 代),merkle tree 的 tree1 是用 start1 = start0 + count 和 count 生成的。 ![](https://i.imgur.com/1eMexvh.png) 順帶一題,每個 merkle tree 可以有不同的大小。 MAM Publish 102: MAM Section — Branch Index ------  Branch Index,`branch_index` 是從當前世代的樹的 index 中選擇的。 在下面的例子中,merkle tree 已經用start = 0 和 count = 4 創建,所以 branch_index 應該是 0,1,2 和 3 中的一個。 ![](https://i.imgur.com/aE1zO0L.png) MAM Publish 102: MAM Section — Siblings ------ 比方說,給定葉 A',為了獲得 root,你需要所有其他葉子B'C'D'。 但是,如果你不能訪問這些,你怎麼得到根? 兄弟姐妹是一組互補的 hash,通過與給定的葉片相結合,可以產生根。 看下面的圖。 ![](https://i.imgur.com/zO8tutR.png) 這個圖例舉了 branch_index = 0 的情況,其中只給出了A'。 在這種情況下,B“和 hash(C”D“)都是獲取 root 的必要條件,您不必擁有其他葉子。 在這個例子中,B“ 和 Hash(C”D“)被稱為 A' 的兄弟節點,在 MAM 中,它被稱為 branch_index = 0 的兄弟節點,不同的 branch_index 具有不同的兄弟節點集合。 MAM Publish 102: MAM Section — completed ------ 在 MAM section 中,message 的合成:nextRoot,branch_index 和 Siblings,稱為 messageTrytes,用root(Public mode)或 sideKey(restricted mode)加密。 下圖是 MAM section 的 restricted mode 加密的示例。 ![](https://i.imgur.com/P3qOhI5.png) MAM Publish 103: Signature Section ------ 正如我所提到的,對於 MAM section 的有效性檢查,發布者在 Bundle 中添加 Signature。 簽名存儲在交易的簽名片段 (`signatureFragment`) 中,這些交易稱為 MAM Bundle 中的簽名部分 (Signature section)。 MAM Publish 103: Signature Section — signing ------ 掩碼消息的簽名由 Private Key = key(seed,branch_index,security)創建。 簽名的數據是 MAM section 的 messageTrytes。 這裡有 Signing 的方案[解釋](https://medium.com/@abmushi/iota-signature-and-validation-b95b3f9ec534)。 ![](https://i.imgur.com/CEpb5Ff.png) MAM Fetch ------ 為了獲取被屏蔽的消息,在 Restricted mode 下需要 root 和 sideKey。 首先,從 givenroot 計算地址。 並蒐索地址的 Bundle。 然後解密找到 Bundle 的 MAM section 的messageTryte。 解密密鑰是 Public mode 的 root,Restricted mode 的 sideKey。 現在,從解密的數據,我們有訊息,nextRoot,branch_index,兄弟姐妹。 下一步是檢查未屏蔽消息的有效性。 現在,查看簽名部分。 簽名部分的簽名用於驗證 Bundle 的 MAM seciotn 的 messageTryte 作為簽名數據。 驗證過程在這裡[解釋](https://medium.com/@abmushi/iota-signature-and-validation-b95b3f9ec534)。 在驗證過程之後,您得到的是 address,它被用作 merkle tree 的 index = branch_index 的葉子地址,並與兄弟姐妹結合以計算樹的 root,名為 temp_root。 如果 temp_root 等於給定的 root,那麼這個未被屏蔽的消息是該通道的有效消息。 如果不是,則不由頻道所有者(=種子所有者)發布。 Chainfork ------ MAM 的訊息鏈可以分叉。 而且很容易分叉。 對於您選擇分叉的一代,您只需發布具有不同 branch_index 的消息。 但是,在這一代中可以分叉的分枝的極限是一代 merkle tree 的大小。 如果分叉更多,新的分支索引會溢出到下一代的branch_index 中。 您可以在子鏈之間設置不同的 sideKey 和頻道模式。 ![](https://i.imgur.com/fb1WvXU.png) Snapshot ------ 被掩碼的消息存儲在交易的 `signatureFragment` 中。 因此,在快照之後,刪除所有 transaction 和零餘額地址之後,快照之前的所有 MAM 都將被刪除。 為了防止這種情況發生,MAM 存儲在 Permanode 中,它不會執行快照。 儘管 permanode 需要大量存儲,頻寬和高速,但目前它運行時沒有經濟誘因。 我們的社群必須討論 IOTA 的基礎設施應該如何維持並得到獎勵以維持穩定。 References ------ > MAM JS Library: https://github.com/iotaledger/mam.client.js IOTA github: https://github.com/iotaledger/iota.lib.js Introducing MAM: https://blog.iota.org/introducing-masked-authenticated-messaging-e55c1822d50e About Author ------ @abmushi on [twitter](https://twitter.com/abmushi), Discord 本文的日文翻譯在[這裡](https://qiita.com/ABmushi/items/f49a431c5c4a94abf33c) Donation is always welcome and appreciated! BTC: 1ACGpgpAMgaAKbGpPq2sDa467MnRNdW4wX IOTA:KWIEEQHAJBJTDPE9WEDILKMVQCJPZSF9CXALYQTULCGNPLIIKJLFYHCWSJNXDALKHAOOTELQUIXWIOFVDPQNXMLBZB 原始文章刊登於 [https://gist.github.com](https://gist.github.com/abmushi/61d65059689f10d4ac4e5571b4573cda)