區塊鏈上的隨機性

復聯4:Daniel vs 滅霸


本文主要內容包括隨機性的基本概念,以及你們比較關心的一些區塊鏈項目中的當紅炸子雞是如何獲取隨機性的,以及隨機性和區塊鏈之間的關係,主要是這三個方面。不會涉及到傳統的僞隨機發生器。(這裏說明一下,做者把 Nervos 的幾個 CXO Daniel 、Jan、Terry 都調侃了一遍...算法

隨機性的定義

話說滅霸得到無限手套,集齊6顆無限原石。只要滅霸發動「比心」攻擊,宇宙一半的生命就會消失,這時候復聯派出了終極武器—Daniel!
「Daniel,就決定是你了!」安全


這時,電視裏又開始在放《武林外傳》,Daniel看到呂秀才。dom


因而,Daniel 靈機一動,跑去找滅霸。
Daniel:尊敬的滅霸先生,據說你要消滅宇宙一半的生命?
滅霸:請求是沒有用的,全部生命都是隨機選擇的,絕對公平!這是爲了宇宙的平衡,宇宙的將來。
因而,Daniel 深吸了一口氣,提出了一連串的問題。
Daniel:那什麼是隨機?隨機的源頭在哪裏?你瞭解無限手套隨機選擇的原理嗎?如何驗證你的選擇是隨機的呢?你怎麼知道本身的選擇是不受干涉而徹底公平的呢?選擇出來的人被選擇以後仍是隨機的嗎?@&*(@^$^&@*!(&#*!……」分佈式



Daniel:好吧,咱們從最簡單的開始,什麼是隨機性?
滅霸:那太簡單了,就是均勻分佈。
Daniel:01230123 是隨機序列嗎?
滅霸:還要與出現的位置無關。
Daniel:xxxxx 是隨機序列嗎?
滅霸:我知道了,再加個相互獨立。
Daniel:xxxxx 是隨機序列嗎?這個是天然數 e,是 2.871828828函數


從以上的對話中能夠看出,光從均勻性出發定義隨機性是不夠的,由於每個數字出現的機率是同樣的,並不能保證他們就是獨立的。那麼加上相互獨立的話,這個序列是隨機的嗎?咱們能夠認爲它是隨機序列,可是是有限定條件的,這類隨機序列只能用在仿真當中。好比咱們想要模擬人流的泊松到達,用這樣的隨機序列是能夠的,可是在密碼學中這樣的隨機序列是不夠的,咱們還須要不可預測性。好比咱們用天然對數的底e的數碼做爲隨機序列。e確實能夠被認爲在統計上是均勻分佈和獨立的(儘管沒有徹底證實),用來作仿真是足夠的,可是不能用做密碼學中的隨機種子。由於對手有可能經過必定長度的已知序列猜想到是在使用e。密碼學的隨機種子要求任意片斷序列不能預測該序列餘下的部分,這是密碼學中獨有的特性,目前接下來的內容都是能夠適用於密碼學中的隨機序列。區塊鏈

隨機性的分類

隨機性和隨機性之間是有差異的,咱們來簡單說明下隨機性的分類。從真假來分類,能夠分爲真隨機數發生器和僞隨機數發生器。還有一種與之正交的分類,是硬件隨機數發生器和軟件隨機數發生器。測試


真隨機數發生器一般是經過物理手段,包括量子過程。軟件真隨機數發生器是存在的:Linux下有個/dev/urandom,是一個軟件真隨機數發生器,採集機器運行過程當中的噪音數據來獲取足夠的熵源。網站


僞隨機數發生器一般經過單向函數來構造,僞隨機數發生器一般能夠將熵源,也就是隨機種子進行擴充,好比真隨機數發生器產生了 1bit 的隨機數,那麼僞隨機數發生器就能夠將這 1 比特擴充到 10bit 或 100bit,可是它的熵仍是 1bit。加密


爲何把量子過程單獨領出來說呢?由於在量子力學沒有被推翻以前,它是目前理論上可以證實的真隨機。從物理學原理上它是自然蘊含在理論裏的隨機性像。其餘獲取隨機數的手段,像大氣噪聲,咱們還不能徹底從理論上證實它是隨機的,也許將來某一天有人能找出它的規律呢?spa

  • 那麼僞隨機數發生器存在嗎?在密碼學安全嗎?
  • 很遺憾,不存在.
  • 這個問題等價於P是否等於NP;然而尚未被證實出來。
  • 那爲何還要去用呢?
  • 咱們如今統計學上的一些檢測手段能夠檢測出你這個發生器產生的隨機序列是否知足密碼學的計算安全性的要求。
  • 如何判斷一個序列的隨機數程度?
  • 用統計學統計學測試。
  • 可以徹底證實嗎?
  • 不能。
  • 有理論證實隨機數發生器嗎?
  • 有,量子隨機數發生器。
  • 僞隨機數和不可預測性的關係?
  • 僞隨機性等於多項式時間不可預測性。

全部的真正的僞隨機數發生器生成的隨機數序列必定是不能被在多項式時間內預測的,也就是給定一個僞隨機數發生器,已知它產生的隨機序列的任意片斷,是沒法在多項式時間內以高於一半的機率預測出下面的1bit。

如何從區塊鏈上取得隨機數

僞隨機數發生器不能直接用在區塊鏈上。爲何?
僞隨機數發生器生成的隨機序列難道不是不可預測的嗎?


不可預測性的前提是說僞隨機數發生器做爲一個黑盒,除了它的輸出,外界沒法得知其餘一切信息。可是區塊鏈上的一切都是公開透明的,包括使用的僞隨機數發生器也是透明的,種子也是同樣的,你怎麼選取種子呢?一旦你知道了種子,知道了隨機數的算法,那麼後面的不可預測性沒必要再考慮了,徹底可以預測到後面的序列了。


真隨機數發生器呢?


能夠,可是很難作到去中心化。例如以太坊如今經常使用的隨機數發生器就是經過 Oraclize,引入random.org(random.org 是一個網站,它聲稱提供真隨機數。)你們經過 oraclize 把真隨機數入到智能合約中,這是一個比較廣泛的用法。好比 Fomo3D,他們以前用了一個並不安全的,在區塊鏈上取隨機數的方法。
那麼歸根結底,在區塊鏈這樣的一個系統當中隨機性能夠來自哪裏呢?這個隨機性來自「人類的行爲」。咱們如今從最簡單的狀況開始去逐步構造一個區塊鏈上可使用的公平的隨機數發生器。下文所涉及到的在分佈式的環境下的協議均可以轉換爲區塊鏈的環境,所以不對「分佈式」和「區塊鏈」作區分。

v1.0 斯里蘭卡炒餅

例如,如今有 Jan 和 Daniel 兩我的,在他們面前有一盤炒餅,他們都想吃,可是這個炒餅只夠一我的吃。所以,他們如今須要一個分佈式的隨機數發生器來決定由誰來吃這個炒餅。假設最後輸出的結果是 0,那就給 Jan;是 1 的話就給Daniel。


爲了構造這樣的一個公平的協議——歷史上叫作 coin-flipping 或者 coin-tossing 協議,咱們要求二人分別對協議進行輸入。這樣的協議須要知足全部的輸入與輸出都是獨立的。Jan 和 Daniel 他們之間確定是不可能共謀的,這樣他們倆的輸入就相互獨立了。如今只須要知足輸出和兩個輸入也分別是相互獨立的;第二個性質就是隻要有一個輸入是均勻選擇的,那麼結果就是均勻分佈的。也就是說,即便 Daniel 一直選 1,只要Jan的選擇是均勻的,那麼到最後輸出的結果就是均勻的。現實中知足這些條件的構造方式有不少,其中一種是異或操做:在給定 Daniel 選 1 的狀況下(Jan 不知道),Jan 無論選 0 仍是 1,輸出結果都是是 0/1 各一半的可能性;給定 Daniel 選 0 的狀況同理。另外一種方法是利用 mod 運算。

 

v2.0 槐花餅

可是這裏就有一個問題。Daniel 比較聰明,他等 Jan 選好了輸入進去以後,再進行選擇,因爲協議的交互對於兩人來說是公開的,他能看到 Jan 的選擇。若是看到 Jan 選 0,那他就選 0;若是看到 Jan 選 1,那他就選 1。異或起來永遠是 1,這樣不管 Jan 怎麼選擇都是 Daniel佔 據優點。


爲了防止這種做弊行爲,這時候咱們引入新的機制:承諾。也就是說,要讓 Daniel 即便知道 Jan 選擇了什麼,也不能根據 Jan 的選擇去更改本身的選擇。怎麼作呢?在第一個承諾階段,咱們先讓他們把隨機數簽名,簽名結果輸入進協議。在這樣的狀況下,經過第二個揭示階段,把簽過名的隨機數輸入進去,與第一個階段的承諾進行比對成功以後,再異或出結果,得到咱們想要的隨機數。簽名而不採用哈希函數的目的,是爲了保證輸入的隨機數是由本人輸入,而不是別人僞造輸入的,然而在區塊鏈的設定下,咱們能夠直接使用哈希函數,由於一般區塊鏈的交易都是帶有簽名的。

v3.0a 一個比特幣一碗的蛋炒飯

可是這樣還不夠,還有問題。假設此時 Terry 來了,此次他們一共三我的要決定一份蛋炒飯的全部權。多了一我的以後,Daniel 發現事情有起色,他又想到了個主意:若是最後結果看起來不太妙,不是我吃的話,我就不進行揭示階段直接僞裝暈倒。剛纔的協議之下,咱們實際上規定了只有全部人都輸入的狀況下,參與者纔有輸出結果。假如參與者承諾,但卻沒有揭示,那怎麼辦?是從新再來一遍,仍是就取剩下兩我的的輸入呢?這兩種方法是都有問題的:若是要從新來一遍,那麼攻擊者就能夠經過這種方法在每次本身不利的狀況下強行使得協議從新運行;若是隻取剩下兩我的的輸入,攻擊者一樣能夠選擇是否放棄輸入來趨利避害。所以,咱們須要有懲罰機制來保證參與者不得隨意放棄。當參與者在承諾的時候,必需要向協議上交一個比特幣——若是是帶有智能合約的區塊鏈的環境,這樣的操做十分容易。若是Daniel 不按時揭示,那就沒收 Daniel 的比特幣分給 Jan 和 Terry。因爲蛋炒飯的價值一般並不會超過一個比特幣,Daniel 不會選擇這樣的方式進行做弊。這樣的一個懲罰機制,就是爲了防止拒絕服務攻擊。

 

v3.0b 集齊七顆龍珠才能召喚的蛋炒飯

除了懲罰以外,還有另一種方式,咱們稱之爲集齊七顆龍珠才能召喚的蛋炒飯。簡單來說,就是以前的 coin-tossing 的協議,再追加一個門限機制。咱們能夠理解爲對於拒絕服務這種攻擊,咱們加強了系統的健壯性,使得它可以容忍必定程度的拒絕服務。這樣的門限機制總的說來有三種。


第一種門限機制是簡單地取前 t 個輸入。可是這種方式不抗女巫攻擊,假設 Daniel 是黑客帝國的複製人,他複製了一萬個本身,這樣,Daniel 有很大的可能佔有前 t 個輸入,等同於控制了整個隨機數。所以,這種門限的方法是不抗女巫攻擊的,只能用在 permissioned 環境下,在知道總人數的狀況下,只取前 t 個。


第二種方法有三種形式:一種是無分發者的祕密分享;另外一種是無分發者的可驗證祕密分享;最後一種是無分發者的公開可驗證祕密分享。這些都納入到使用無分發者的祕密分享這一類,祕密分享能夠將一個祕密分紅多個碎片,只有集齊必定數量才能將祕密恢復出來。固然,這三種方式是有區別的。第一種沒法驗證,祕密碎片能夠被僞造。第二種是祕密碎片可被驗證,可是驗證不是每一個人均可以作的,每一個人只能驗證本身的份額。最後一種是可被公開驗證的,每一個人均可以驗證全部的祕密碎片。這種方式須要每產生一個隨機數都進行一次祕密分享來保證門限機制。好比說有 N 我的,假設只須要有 t 我的提交了就能輸出咱們想要的隨機數,咱們須要 r 個這樣的隨機數。所以咱們須要這 N 我的相互交互至少r輪。另外一個侷限是,方案須要在許可環境下實施,協議必須知道總人數 N,才能知道門限 t。


無分發者的祕密分享首先要分發,好比說 Jan,把他的隨機數分紅三份,發給 Terry 和 Daniel 每人各一份。每一個人都像 Jan 這樣作以後,每一個人手上都有 3 份來自不一樣的人,包括本身,的份額。此時,再把這些份額拼成份額向量廣播給全部人,這樣每一個人只要手裏有兩份(包括本身的)這樣的向量就能恢復出 Jan、Daniel 和 Terry 三人的隨機數,而後就能夠算出最終的隨機數。而無分發者的公開可驗證祕密分享,在分發的時候多了一些數據。這些數據就是proof。全部人經過收到的 proof 驗證收到的份額。驗證經過就能夠說明這個份額確實和其餘發出去的份額是一致的。


無分發者的祕密分享


無分發者的公開可驗證祕密分享


第三種方法是分佈式密鑰生成+門限簽名。門限簽名能夠理解爲祕密分享應用到了簽名方案中,可是它又不是單純將二者相疊加。一般的簽名是,一我的用本身的私鑰加密了消息以後,你們能夠用公鑰進行驗證。而該方案使用的門限簽名則是,一樣有一對公私鑰,可是每一個人分別只有私鑰的其中一個碎片;每一個人能夠利用本身碎片進行簽名,這些簽名能夠被公鑰的相應碎片驗證;而且,這些碎片中的任意 t 個合起來能夠計算出來一個能夠被完整的公鑰驗證的簽名。所以,這樣的簽名過程並不須要全部人蔘與,只須要 n 我的中的 t 我的的有效簽名就能夠了。並且不管是哪 t 我的,最後生成的簽名是同樣的。而且簽名過程當中涉及到的私鑰不會被泄露,這使得多輪無交互簽名成爲可能。固然,這個總的公私鑰對不是憑空出來的,它的生成須要全部人在一開始運行分佈式密鑰分發協議才能生成有這樣的密碼學特性的公私鑰對。同時,這個方案仍是存在必需要知道總人數的問題。

v4.0 桂花糕

在這裏介紹下這四個項目:Algorand、Cardano,Dfinity 和 Randao 分別是如何利用上述三種基本的方案構建隨機數生成協議的。


Algorand 的共識過程利用了隨機抽籤,它的隨機抽籤所依賴的種子本質是經過取前t個輸入來生成的。Algorand 的共識過程要求節點先在本地抽籤,經過一個 Verifabale Random Function 算出來一個可驗證的肯定的隨機數,這樣的隨機數是根據上一輪的公共信息加上每一個節點本身的私鑰計算出來的,是惟一肯定的,而且可被其餘人驗證。隨機數被用於每一個節點的本地抽籤。本地抽籤後,每一個人知道本身是否被選中。以後,被選中的人廣播抽籤結果、證實和候選區塊到全網節點,根據區塊的 quality 大小,選出來候選區塊。而肯定哪一個區塊的 quality 更大是須要作 BA 共識的,這個時候,就須要再進行一輪本地抽籤,全部的節點會本身知道是否被選中去作 BA*(一個拜占庭類型的共識),去投票選本身認爲的 quality 最高的候選區塊,投票會進行不少輪,每一輪都要從新進行一次本地抽籤。能夠看出,Algorand共識的本質就是咱們每一個人都生成一個隨機數。可是咱們最終只想要一個隨機數,這樣咱們才能根據最後肯定的隨機數去決定哪一個塊會被全網接受。這個時候的方案就是根據某種肯定的規則從衆多備選結果中取一個,方法是經過拜占庭共識達成一致,這就是 Algorand 的核心思想。

Dfinity。它的機制和 algorand 很像,也須要一個委員會,委員會會運行一個分佈式的生成隨機種子的協議。同樣,咱們先假設已經有了這樣的隨機數種子了,這樣,隨機數種子能夠被利用算出每個節點的排名。同時節點能夠註冊進入不一樣的組,不一樣的組中能夠有相同的節點。委員會就是在這些組中隨機挑選的一個,隨機種子是剛剛提到的那個種子。此時,你們均可以提交候選區塊,廣播給全部的節點,可是在全部人作區塊認證的時候,誠實節點老是會選擇排名最高的塊簽名,簽好後,廣播給全部的節點,直到節點收到或擁有某個得到一半以上簽名的區塊。一輪的公共種子其實是根據上一輪的種子以及開始設置的密鑰對惟一輩子成的。其實就是無分發者的祕密分享加上門限簽名的方案。首先,在最開始,會有一次分佈式密鑰生成來進行初始化配置。此時,組內的 n 我的必需要所有參與到這個協議中。經過這樣一種方式,每一個人得到一把私鑰的一個碎片,以及用來驗證這些碎片正確性的證實,這個碎片是用來作門限簽名的。私鑰的碎片,用來對上一輪生成的隨機數和輪數拼在一塊兒的字符串進行簽名,而後廣播之。這樣的 n 個簽名中只須要任意t個就能夠拼出完整的可被公鑰驗證的簽名,這個簽名就是當前輪的隨機數。整個過程,算法是肯定的,對於一個節點來說,惟一不肯定的是其餘人的簽名結果。值得注意的地方就是 Dfinity 此處採用基於 BLS 的門限簽名方案,這個方案的第一個好處就是僅須要進行一次全局設置。以前提到的祕密分享,每次都須要分享一次給每個人。可是使用門限簽名,除了密鑰分發的階段,以後的階段只須要 n 我的中 t 我的提交有效的簽名便可得出結果。第二個好處就是惟一性,不管哪 t 我的提交,最後對一樣消息生成的簽名都是相同的,這保證了最後生成的隨機數是沒法被偏移的。




隨機數與共識

隨機數生成與共識協議有着千絲萬縷的關係,主要體現爲如下兩點。

防止女巫攻擊的方法之一是不可預測的隨機抽籤。不管是 PoW,仍是 PoS,咱們均可以理解爲一種隨機抽籤的方法。無論公有鏈上的共識協議再怎麼設計,包括比特幣在內,都是在經過某種方式產生必定的隨機性。礦工經過 PoW 競爭出塊,使得出塊的人變得不肯定,從而防止了經過假裝大量節點獲利的女巫攻擊。

區塊鏈上的隨機數安全依賴於共識協議。以 Randao 爲例,針對 Fomo3D 的攻擊一樣對 Randao 有效。因爲以太坊的激勵機制和共識協議的特色,礦工會優先打包手續費高的交易,因此攻擊者能夠經過 Censorship Attack,人爲調整打包區塊時包含的交易,或者製造高手續費的垃圾交易,迅速的把區塊的 Gas Limit 耗光,阻止其餘人的特定交易上鍊。當 Randao 即將計算出的結果不理想時,能夠經過這種方式強行將協議終止,令無辜的節點蒙受損失,本身從中獲利。儘管這樣的手段有時成本較高,但這樣的攻擊仍然有沒法忽略的可能性發生,而這樣的攻擊之因此成立的緣由,實際上根植於共識協議的設計。再例如 Grinding Attack。

Fomo3D 採用了取上一個塊的哈希值做爲種子的方法生成隨機數。這種狀況下,礦工能夠把全部的區塊組織的可能性都試驗出來,而後選擇一種對本身最有利的方式打包交易。這種攻擊手段就是 Grinding Attack。儘管這樣的攻擊手段有必定的成本,可是若是隨機數所牽涉的利益足夠,例如用在某些賭博遊戲裏,礦工想要從中獲利很是容易。

所以,區塊鏈上隨機數的生成是須要上下文環境的,必需要給定情景。拿 Randao 來說,若是它的某一個隨機數的生成,只和 0.01 個 eth 相關,那麼攻擊者將沒有足夠的理由去破壞它的公平性。若是押金不夠多,那麼 Randao 就有多是不安全的。

 

 

做者簡介:

邱飛暘,清華大學本科畢業生,黑客馬拉松愛好者,Blockchain Dev Meetup 講師之一。主要研究方向有:分佈式共識、密碼學。Blockchain Dev Meetup 是由「Nervos」基金會和「祕猿科技」 贊助的技術分享活動,咱們是崇尚開源、務實篤行的極客團隊。

相關文章
相關標籤/搜索