研究 | 全面對比Schnorr簽名方案和BLS簽名方案

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

​前言

Schnorr 簽名算法最初是由德國密碼學家 Claus Schnorr 於 2008 年提出的,而來自區塊鏈協議公司 Blockstream 的密碼學家 Gregory Maxwell、Pieter Wuille 等人,則在 2018 年提出了一種名為 MuSig 的 Schnorr 簽名方案,這也是我們即將探索的簽名方案。

而 BLS 簽名方案,最初是由斯坦福大學教授 Dan Boneh 等人於2001年便提出的一種方案,目前則在 Boneh 教授等人的完善下,變得更適用於區塊鏈。

總的來說,兩大簽名方案各有千秋,它們在不同的場景下都有各自的優勢。

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

原文 | Stepan

目錄

1、橢圓曲線數字簽名算法(ECDSA)

2、什麼是 Schnorr 簽名?

3、Schnorr 簽名的批量驗證

4、Schnorr 簽名的密鑰聚合

5、MuSig:由 Blockstream 提出的 Schnorr 簽名方案

6、默克爾多重簽名(Merkle Multisig)

7、什麼是 BLS 簽名方案?

8、BLS 簽名的魔法

9、BLS 簽名方案的具體原理

10、BLS 簽名的簽名聚合

11、BLS 簽名的密鑰聚合和 n-of-n 多重簽名

12、子群多重簽名方案(m-of-n multisig)

13、BLS 簽名可能的應用場景

14、BLS 簽名的弊端:配對效率低下

15、結論

Blockstream 曾在 2018 年初的時候發布了一份關於 MuSig 的論文,這是一種 Schnorr 簽名方案,總的來說,這種簽名方案的一些特徵是非常好的,但其也存在着一些讓人討厭的其他特徵。

1 橢圓曲線數字簽名算法(ECDSA)

首先,我們需要明白,比特幣目前使用的是 ECDSA 橢圓曲線數字簽名算法,要對消息 m 進行簽名,我們需對其進行哈希操作,並將此哈希視為一個數字:z = hash(m)。我們還需要一個隨機或隨機查找的數字 k。我們不喜歡信任隨機數生成器(存在太多的故障,很多漏洞與糟糕的 RGN 有關),因此,我們通常會使用 RFC6979,並根據我們的秘密和我們要簽名的消息,計算確定性 K 值。使用私鑰 pk,我們可以為包含兩個數字的消息m生成簽名:r(隨機點R的x坐標 = k×G) 和 s = (z+r⋅pk)/k。然後,使用我們的公鑰 P = pk×G,任何人都可通過檢查點 (z/s)×G+(r/s)×P的 x 坐標等於 r,來驗證我們的簽名。

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

▲ ECDSA算法的可視圖

這個算法很常見,也很棒,但它也是可改進的。首先,簽名驗證包括反轉(1/s)和兩點乘法,這些操作的計算量非常大。在比特幣中,每個節點都必須驗證所有交易。這意味着當你廣播一筆交易時,數千台計算機將不得不驗證你的簽名。而簡化驗證過程將是非常有益的,即使簽名過程會更加困難。第二,每個節點必須分別驗證每個簽名。如果是 m-of-n 多重簽名交易節點,則可能需多次驗證相同的簽名。例如,具有 7-of-11 多重簽名輸入的交易將包含 7 個簽名,並且需要對網絡中的每個節點進行 7-11 次的簽名驗證。同樣,這樣的交易會佔用大量的空間,你必須為此支付大量的費用。

2 什麼是Schnorr簽名

Schnorr 簽名的生成則略有不同,我們使用了一個點 R 和一個標量s來代替兩個標量(r,s)。與 ECDSA 相似的是,R 是橢圓曲線(R=K×G)上的一個隨機點。簽名的第二部分計算略有不同: s = k + hash(P,R,m) ⋅ pk。這裡的 pk 是你的私鑰,而P = pk×G 則是你的公鑰,m 是消息。然後可通過檢查 s×G = R + hash(P,R,m)×P 來驗證這個簽名。

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

▲Schnorr簽名算法的可視圖

這個方程是線性的,所以方程可互相加減,並且仍然有效,這就給我們帶來了幾大關於 Schnorr 簽名的好處。

3 Schnorr簽名的批量驗證

要驗證比特幣區塊鏈中的區塊,我們需確保區塊中的所有簽名都有效。如果其中一個是無效的,我們不會在乎是哪個無效的,我們只會拒絕掉整個區塊。

對於 ECDSA 簽名算法,每個簽名都必須單獨驗證。也就是說,如果區塊中有 1000 個簽名,我們就需要計算 1000 次倒置和 2000 次點乘運算,總共約 3000 次繁重的計算任務。

而通過使用 Schnorr 簽名,我們可以將所有簽名驗證方程相加,從而節省一些計算能力。對於有 1000 個簽名的區塊而言,我們需驗證:

(s1+s2+…+s1000)×G=(R1+…+R1000)+(hash(P1,R1,m1)×P1+ hash(P2,R2,m2)×P2+…+hash(P1000,R1000,m1000)×P1000)

這裡我們有一堆加法(在計算能力上幾乎是免費的)以及 1001 次點乘法。我們需要為每個簽名計算大約一次繁重的計算。

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

▲兩個簽名的批驗證圖,由於驗證方程是線性的,只要所有簽名都有效,幾個方程的和就有效。我們節省了一些計算能力,因為標量和點加法比點乘法容易得多

4 Schnorr簽名的密鑰聚合

我們希望讓自己的比特幣保持安全,所以我們可能希望使用至少 2 個不同的私鑰來控制我們的比特幣。比如說一個放在筆記本電腦或手機,另一個則放在硬件錢包/冷錢包。因此,當其中一個受到威脅時,我們仍然可以控制我們的比特幣。

目前,它是通過 2-of-2 多重簽名腳本來實現的,這需要在交易中包含兩個單獨的簽名。

而使用 Schnorr 簽名,我們可以使用一對私鑰 (pk1,pk2),並生成一個與共享公鑰 P=P1+P2=pk1×G+pk2×G 對應的共享簽名。要生成這個簽名,我們需要在每個設備上選擇一個隨機數(k1,k2),生成一個隨機點 Ri=ki×G,將它們相加以計算一個公共哈希 (P,R1+R2,m),然後從每個設備 (si = ki + hash(P,R,m) ⋅ pki) 中獲取 s1 和 s2。然後我們可以將這些簽名相加,並使用一對 (R, s) = (R1+R2, s1+s2) 作為我們對共享公鑰 p 的簽名。

其他所有人都無法說出它是否是聚合簽名,它看起來與普通 schnorr 簽名完全相同。

這種構造有 3 個問題,

第一,從用戶界面的角度來看,要進行交易,我們需要進行幾輪通信,計算公共 R,然後-簽名。有了兩個私鑰,只需一次訪問冷錢包就可以完成:我們在在線錢包上準備一個未簽名的交易,選擇 k1,將 R1=K1×G 與未簽名的交易一起記下。然後我們將這些數據傳送到冷錢包並簽名。因為我們已經有了 R1,所以我們可以一次性在冷錢包上籤署交易。從冷錢包中,我們得到了 R2 和 s2,並將其傳輸回在線錢包。在線錢包使用之前選擇的 (k1, R1) 簽署交易,結合簽名並廣播簽名交易。這與我們現在的情況非常相似,但一旦添加第三個私鑰,一切就會變得更加複雜。比方說,你有一筆財富,它是由 10 個私鑰控制的,它們存儲在世界各地不同的安全位置,然後,你需要進行一筆交易。目前,你只需要瀏覽所有這些位置一次,但如果你使用的是密鑰聚合,則需要執行兩次,以組裝所有 R1,然後簽名。在這種情況下,最好在不進行聚合的情況下保留單獨的簽名,然後我們就需要 3 輪通信:

1. 選擇一個隨機數 ki 和相應的 Ri=ki×G,然後只告訴每個人其哈希 ti=hash(Ri),這樣每個人都可以確定在學習了其他隨機數之後你不會改變主意;

2. 把所有的數字彙總起來,計算出共同的 R;

3.簽名;

第二個問題是已知的惡意密鑰攻擊。無論是在論文還是這篇文章中,都有很好的描述,所以我不想詳細討論。其想法是,如果你的某個設備被黑客攻擊(比如說,你的在線錢包),並假裝其公鑰是 (p1-p2),那麼它可以用它的私鑰 pk1 控制共享資金。一個簡單的解決方案是,在設置設備時,需要使用相應的私鑰對公鑰進行簽名。

還有第三個重要問題。不能使用確定性 k 進行簽名。有一種簡單的攻擊方式,如果你使用確定性 K,它允許黑客獲得我們的私鑰。攻擊看起來會是這樣的:有人入侵了我們的筆記本電腦,並完全控制了兩個私鑰中的一個(例如 pk1)。我們可能覺得是安全的,因為我們的比特幣需要來自 pk1 和 pk2 的聚合簽名。因此,我們嘗試像往常一樣進行交易,準備一個未簽名的交易和 R1 值,將它們轉移到我們的硬件錢包並在那裡簽名。然後返回( r2,s2) 和我們的在線錢包發生了一些事情,它無法簽名和廣播。我們再次嘗試,但我們被黑的電腦這次使用了另一個隨機值 R1'。我們再次與我們的硬件錢包簽署相同的交易,並將值 (r2,s2) 帶回我們被黑的電腦。然後,糟糕的事就發生了,我們的比特幣就丟失了。在這個攻擊中,黑客為同一筆交易獲得一對有效的簽名:  

(R1, s1, R2, s2)  和 (R1', s1', R2, s2'),

這裡 R2 是相同的,但 R = R1+R2 和 R'=R1'+R2 是不同的,這意味着黑客可以計算我們的第二個私鑰:

s2-s2'=(hash(P,R1+R2,m)-hash(P,R1'+R2,m))⋅pk2 and pk2=(s2-s2')/(hash(P,R1+R2,m)-hash(P,R1'+R2,m))。

我發現這是密鑰聚合最不方便的特性:我們需要在任何地方使用好的隨機數生成器來使用密鑰聚合。

5 MuSig:由Blockstream提出的Schnorr簽名方案

MuSig 方案解決了其中一個問題,它使得密鑰盜竊攻擊成為了不可能。目標是將多個參與方/設備的簽名和公鑰聚合到一個參與方/設備,但不能證明你擁有與公鑰對應的私鑰。

聚合簽名對應於聚合公鑰。但是,我們不只是將所有聯合簽名者的公鑰相加,而是將它們乘以某個因子。聚合的公鑰將是 

P=hash(L,P1)×P1+…+hash(L,Pn)×Pn。

這裡 L=hash(P1,…,Pn) 是一個取決於所有公鑰的公用數字。這種非線性特性可以防止攻擊者構造一個不好的公鑰,例如在惡意密鑰攻擊當中。儘管攻擊者知道自己的哈希 (L,Patk)×Patk 應是什麼,但他不能從中派生 Patk,這和從公鑰派生私鑰是相同的問題。剩餘部分和前面的情況非常相似,為了生成簽名,每個聯合簽名者選擇一個隨機數 ki,並與其他人共享 Ri=ki×G。然後將所有這些隨機點相加到一個 R=R1+…+Rn,生成簽名 si = ki + hash(P,R,m) ⋅ hash(L,Pi) ⋅ pki。這個聚合簽名是  (R, s)=(R1+…+Rn, s1+…+sn) ,驗證方程與之前相同:

s×G = R + hash(P,R,m)×P。

6 默克爾多重簽名(Merkle Multisig)

你可能會注意到,MuSig 和密鑰聚合都需要所有簽名者簽署一筆交易。但是,如果你要的是一個 2-of-3 的多重簽名呢?在這種情況下,是否可以使用簽名聚合,或者我們必須使用我們通常使用的 OP_CHECKMULTISIG 和單獨的簽名?

嗯,這是可能的,但是協議有一個小的改變。我們可以開發一個類似 OP_CHECKMULTISIG 的新 op 碼,它檢查聚合簽名是否與公鑰的默克爾樹中的特定項對應。

例如,如果我們使用帶有公鑰 p1、p2和 p3 的 2-of-3 多重簽名,那麼我們需要為所有可使用的組合構造一個聚合公鑰的默克爾樹:(P1, P2), (P2, P3), (P1, P3) ,並將根放到鎖定腳本中。為了使用比特幣,我們提供了一個簽名以及一個證明我們的公鑰在默克爾樹上的證據。對於 2-of-3 多重簽名,默克爾樹中只有三個元素,證明將由兩個哈希組成,其中一個是我們想要使用的哈希,另一個則是其鄰哈希。而對於 7-of-11 的多重簽名,已經有 11!/7!/4!=330 種可能的密鑰組合,而證明需要 8 個元素。一般來說,證明中的元素數量幾乎與多重簽名種的密鑰數成線性關係 ( log2(n!/m!/(n-m)!)。

但是,有了公共密鑰的默克爾樹,我們不局限於 m-of-n 的多重簽名。我們可以用任何我們想要的公共密鑰製作一棵默克爾樹。例如,如果我們有一台筆記本電腦、一部電話、一個硬件錢包和一個恢複種子,我們可以構建一個結構,允許我們將比特幣與一台筆記本電腦、一個硬件錢包、一部電話和一個硬件錢包或僅與一個恢複種子一起使用。只有當你用分支和其他東西構造更複雜的腳本時,僅使用 OP_CHECKMULTISIG 會是不可能的。

7 什麼是BLS簽名方案

BLS 簽名方案最初是由斯坦福大學教授 Dan Boneh 等人於2001年就提出的一種簽名方案,而在 2018 年,Boneh 教授還與 IBM 研究機構的 Manu Drijvers 等人更新了這種簽名方案。

Schnorr 簽名方案是非常了不起的,如果我們做得對,我們可以將交易中的所有簽名和公鑰組合為一個密鑰和一個簽名,沒有人會發現它們對應於多個密鑰。區塊驗證也可以變得更快,因為我們可一次性驗證所有簽名。但它也存在着一些問題:

1. 多重簽名方案需要多輪通信,這會使冷存儲變得非常煩人;2. 對於簽名聚合,我們必須依賴隨機數生成器,我們不能像在 ECDSA 中那樣確定地選擇隨機點 R;

3. m-of-n 多重簽名方案是棘手的,我們需要製作一個公共密鑰的默克爾樹(merkle tree),對於大數的 m 和 n 來說,這顆默克爾樹可以變得相當大;

4. 我們不能將區塊中的所有簽名組合為單個簽名;

BLS 簽名可修復上述所有問題,我們不需要隨機數,區塊中的所有簽名都可以組合成單個簽名,m-of-n 類型的多重簽名非常簡單,我們不需要簽名者之間進行多輪通信。此外,BLS 簽名相比 Schnorr 簽名或 ECDSA 簽名要小 2 倍,其簽名不是一對,而是一個單曲線點。聽起來似乎很棒,對吧,讓我們看看它是如何工作的。

8 BLS簽名的魔法

在開始之前,我們需要兩個新的結構:哈希到曲線(hashing to the curve)以及曲線配對(curves pairing)。

哈希到曲線(hashing to the curve)

通常對於 ECDSA 簽名以及 Schnorr 簽名,我們會哈希一則消息,並在簽名算法中使用此哈希作為一個數字。而對於 BLS 簽名,我們需要一個稍修改過的哈希算法,它直接哈希到橢圓曲線。最簡單的方法是像往常一樣哈希一則消息,並將結果視為點的 x 坐標。橢圓曲線(就像我們在比特幣中使用的曲線)通常有 2²⁵⁶ 個點,而 SHA-256 哈希算法也給出了一個 256 位的結果。但是對於每個有效的 x 坐標,有兩個點具有正和負的 y 坐標(因為如果(x,y)在曲線 y²=x³+ax+b 上,則 (x,-y)也在曲線上)。這意味着我們的哈希有大約 50% 的概率為一些x找到兩個點,另有50%的概率無法找到。

要為任何消息找到一個點,我們可嘗試哈希幾次,方法是在消息中追加一個數字,並在失敗時遞增。如果 hash(m||0)  找不到點,我們嘗試 hash(m||1)、hash(m||2) 等等,直到最後得到一個匹配的點。然後我們選擇兩個對應點中的一個,比如y較小的那個,然後我們就完成了。

曲線配對(curves pairing)

我們需要的另一件事是一個非常特殊的函數,它在一條曲線(或兩條不同的曲線)上取兩點 P 和 Q,並將它們映射至一個數字:

e(P, Q) → n。

我們還需要這個函數的一個重要屬性。如果我們有一些秘密數字 x 和兩點 P 和 Q,不管我們用哪個點乘以這個數字,我們都應得到相同的結果:即:

e(x×P, Q) = e(P, x×Q)。

基本上,我們需要能夠在不改變結果的情況下交換兩個參數之間的點乘數。更普遍地說,所有這些互換都應產生相同的結果:

e(a×P, b×Q) = e(P, ab×Q) = e(ab×P, Q) = e(P, Q)^(ab)

我不想描述這個函數是如何精確工作的。基礎數學相當複雜,如果你想知道所有令人討厭的細節,我建議你閱讀這篇文章和其中的參考資料。如果你想更深入一些,那這篇論文會比較適合你。目前,我們只需要接受這種函數的存在,它們不會泄露關於我們的秘密數字 X 的任何信息。一個重要的注意項是,我們不能在這裡使用任何橢圓曲線(特別是標準比特幣曲線 secp256k1 不起作用)。為了使這個函數高效和安全,我們必須使用來自“友好配對”家族非常特殊的曲線。

9 BLS簽名方案的具體原理

現在我們有了構建 BLS 簽名所需的一切。和往常一樣,我們的私鑰是一些秘密數字 pk,我們的公鑰是 P = pk×G,我們要簽名的消息則是 m。為了計算簽名,我們將消息哈希到曲線H(m) ,並將結果點乘以私鑰:  S = pk×H(m)。就是這樣了!沒有別的東西,沒有隨機數,沒有額外的操作,只有哈希乘以私鑰!我們的簽名只是曲線上的一個單點,在壓縮序列化格式中只需要 33 個字節!

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

▲BLS簽名生成,為了獲得簽名,我們將消息的哈希值乘以私鑰

要驗證此簽名,可以使用我們的公鑰 P 並檢查:e(P, H(m)) = e(G, S) 這為真,因為上面描述的配對函數的優良特性:e(P, H(m)) = e(pk×G, H(m)) = e(G, pk×H(m)) = e(G, S)

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

▲ BLS簽名驗證,我們只需要檢查公鑰和消息哈希是否映射到與曲線生成器點和簽名相同的數字

這個簽名方案既美觀又簡單,此外也有幾個非常好的功能,特別是對比特幣而言。

10 BLS簽名的簽名聚合

現在,讓我們組合區塊中的所有簽名!假設我們有一個包含 1000 筆交易的區塊,每筆交易都包含一個簽名 Si、一個公鑰 Pi 以及一個簽名為 mi 的消息。如果我們可以合併所有簽名,為什麼要存儲所有的簽名?畢竟,我們只關心區塊中的所有簽名是否有效。聚合簽名將只是區塊中所有簽名的總和: S = S1+S2+…+S1000 要驗證區塊,我們需要檢查以下等式是否成立:

e(G, S) = e(P1, H(m1))⋅e(P2, H(m2))⋅…⋅e(P1000, H(m1000))

如果你仔細看,你會發現這是真的:

e(G, S) = e(G, S1+S2+…+S1000) = e(G, S1)⋅e(G, S2)⋅…⋅e(G, S1000) = e(G, pk1×H(m1))⋅…⋅e(G, pk1000×H(m1000)) = e(pk1×G, H(m1))⋅…⋅e(pk1000×G, H(m1000)) = e(P1, H(m1))⋅e(P2, H(m2))⋅…⋅e(P1000, H(m1000))

我們仍然需要知道所有的公鑰並計算 1001 個配對函數,但是至少區塊中的所有簽名只佔用 33 個字節。簽名聚合可以由礦工完成,並節省區塊大量的空間。

11 BLS簽名的密鑰聚合和n-of-n多重簽名

如果我們使用多重簽名地址,我們將使用不同的密鑰簽署相同的交易。在這種情況下,我們可以像在 Schnorr 簽名方案中那樣進行密鑰聚合,在 Schnorr 中,我們將所有簽名和所有密鑰組合到一對密鑰和一個簽名上。以常見的 3-of-3 多重簽名方案為例(對於任何數量的簽名者都可以這樣做)。

組合它們的一個簡單方法,是將所有簽名和所有密鑰添加到一起。結果將是簽名 S=S1+S2+S3 和密鑰 P=P1+P2+P3。很容易看出,同樣的驗證方程仍然有效:

e(G, S) = e(P, H(m))e(G, S) = e(G, S1+S2+S3) = e(G, (pk1+pk2+pk3)×H(m)) = e((pk1+pk2+pk3)×G, H(m)) = e(P1+P2+P3, H(m)) = e(P, H(m)) 

和 Schnorr 簽名方案一樣,運用 BLS 簽名需要保護自己免受流氓密鑰攻擊。我們可通過要求每個聯合簽名者證明他們具有的公鑰的私鑰(通過簽名他們的公鑰),或者我們可以在方案中添加一些非線性元素,使惡意密鑰攻擊成為不可能。我們不是簡單地將所有的密鑰和簽名相加,而是將它們乘以一個特定的數字,然後再相加:

S = a1×S1+a2×S2+a3×S3

P = a1×P1+a2×P2+a3×P3

在這裡,簽名和密鑰的係數是根據簽名者的公鑰和所有其他公鑰來確定計算的: 

ai = hash(Pi, {P1,P2,P3}) 

例如,它可以只是簽名者公鑰和用於簽名的整個公鑰集的級聯:ai = hash(Pi||P1||P2||P3)。

同樣的驗證方程仍然有效。在證明中會有額外的係數 ai,但邏輯仍然存在。這個方案的好處在於,你不需要在設備之間進行多輪通信。你只需要知道誰是其他簽名者。這比 Schnorr 簽名的3輪多重簽名方案要簡單得多。它也不依賴任何隨機性,它是一種完全確定的簽名算法。

12 子群多重簽名方案(m-of-n multisig)

通常,我們不會想用 n-of-n 的多重簽名方案,我們更喜歡使用 m-of-n(比如說2-of-3) 的多重簽名方案。我們不想因為丟了一把私鑰就把錢給弄丟。在這種情況下,最好使用密鑰聚合。有了 Schnorr 簽名方案,我們就可以通過使用公共密鑰的默克爾樹來做到這一點,它不是最有效的辦法,但很管用,壞處在於一旦 m 和 n 值很大,默克爾樹(merkle tree)的大小就會成倍放大。

而對於 BLS 簽名方案,還有另一種方法。不過也沒那麼簡單,我們需要一個普通的哈希函數,它輸出一個數字 hash(x),以及一個到曲線的哈希  H(x)。當我們決定使用多重簽名時,我們還需要一個“設置”階段,但在此之後,我們不再需要通信,我們只需要簽名來簽署任何數量的交易。

再次,我將使用一個簡單的例子,我們希望構建三個不同設備上存儲密鑰的 2-of-3 多重簽名方案,但它可以擴展到任何值的 m 和 n。

設置階段

我們的每個設備都有一個簽名者編號 i=1,2,3,代表其在集合中的位置,一個私鑰 pki 以及一個對應的公鑰 Pi = pki×G。這裡計算聚合公鑰的方式與之前完全相同:

P = a1×P1+a2×P2+a3×P3, 

ai = hash(Pi, {P1,P2,P3})

現在,每個設備都需要簽名,而編號i是我們的聚合公鑰的成員(對於每個 i),聚合這些簽名並將結果保存到相應的設備上:

MKi = (a1⋅pk1)×H(P, i)+(a2⋅pk2)×H(P, i)+(a3⋅pk3)×H(P, i)

這個簽名我們稱為“成員密鑰”,稍後我們將使用它進行簽名。每個成員密鑰都是消息 H(P,i) 的有效 n-of-n 簽名,這意味着:

e(G, MKi)=e(P, H(P,i))

記住這個方程,我們以後會用到的。它將用來證明我們是多重簽名方案的有效參與者。

簽名

現在假設我們只想用密鑰 pk1 和 pk3 簽署一筆交易。我們生成兩個簽名 S1 和 S3:S1 = pk1×H(P, m)+MK1, S3=pk3×H(P, m)+MK3 並將它們相加以獲得單個簽名和密鑰:

(S’, P’) = (S1+S3, P1+P3)

我在這裡寫為 P’和 S’,來強調這個密鑰和簽名只由簽名者的一個子集簽名,它與 P 不同,P 是所有簽名者的聚合密鑰。要驗證這 3 個簽名中的 2 個,我們需要檢查:

e(G, S’) = e(P’, H(P, m))⋅e(P, H(P, 1)+H(P, 3))

我們記得成員密鑰 MK1 和 MK3 是由聚合密鑰 P 簽名的消息 H(P, 1) 及 H(P, 3) 的有效簽名,因此:

e(G, S’) = e(G, S1+S3)=e(G, pk1×H(P, m)+pk3×H(P, m)+MK1+MK3) =e(G, pk1×H(P, m)+pk3×H(P, m))⋅e(G, MK1+MK3)=e(pk1×G+pk3×G, H(P, m))⋅e(P, H(P, 1)+H(P, 3))=e(P’, H(P, m))⋅e(P, H(P, 1)+H(P, 3))

就是這樣,要比 n-of-n 複雜一點,但仍然是可被理解的。

13 BLS簽名可能的應用場景

要實現這個多重簽名方案,我們需要將資金髮送到與聚合公鑰 P 對應的地址,並表示我們至少需兩個簽名。在比特幣腳本語言中,鎖定腳本可能如下所示:

OP_2OP_CHECK_BLS_MULTISIG

這裡,OP_2 告訴我們需要兩個密鑰來簽署消息。我們不會說任何地方總共就只有 3 個簽名者,所以不能說它是 2-of-3 還是 2-of-100 多重簽名地址。為了使用這個輸出,我們需要在我們的案例 1 和 3 中提供參與簽名者的密鑰 P’、簽名 S’以及索引。

解鎖腳本可能如下所示:

OP_1 OP_3

結合這些腳本,可以給我們提供所有必要的信息。從 OP_1 和 OP_3,我們知道我們需要計算哈希 H(P, 1) 和 H(P, 3),然後我們就擁有了驗證交易所需的一切。這意味着對於任何 m 和 n,我們只需要:

1. 鎖定腳本中的一個聚合公鑰 P;

2. 參與簽名者的一個聚合公鑰 P’

3. 一個聚合簽名;

4. 帶有簽名者索引的 m 數字;

但它也並非完美… 通常我們只使用一次地址(我們使用像 bip32 這樣的密鑰派生來生成新的私鑰和地址),但是對於每一組新的私鑰,我們也需要一組新的成員密鑰。一種不用每次都運行設置階段的方法是生成一組密鑰,比如 1000 個密鑰,並獲得相應的成員密鑰。畢竟,它們只有 32 字節大小,然後,只有在使用了所有 1000 個地址時,我們才需要再次運行設置階段。

14 BLS簽名的弊端:配對效率低下

正如本文以及很多技術大佬在 Twitter上 所指出的,上面的討論沒有談到一個重要的部分,而它可能是 BLS 簽名方案最大的缺陷。

BLS 簽名的配對是很難的,我們認為神奇的函數  e(P, Q) 是有效和安全的,但事實並非如此。BLS 簽名驗證要比 ECDSA 簽名驗證的難度大上幾個數量級。對於具有 1000 筆交易的整個區塊的簽名聚合,仍然需要計算 1000 次配對,因此驗證一個區塊中的一個小簽名,可能比驗證 1000 個單獨的 ECDSA 簽名需要更長的時間。

這裡 BLS 簽名能夠實現的唯一好處,在於我們可以在區塊中容納更多的交易,因為聚合簽名只需要大約 32 個字節。與 BLS 簽名不同,Schnorr 簽名是非常有效的,它們可以一起驗證,而且這個過程比 ECDSA 效率高 3 倍。另外,配對函數是複雜的,如果我們不夠小心,它會成為我們的敵人。一方面,我們希望配對能夠有效地、更快地驗證簽名,另一方面,我們不希望透露任何關於我們密鑰的信息。這兩大需求相互競爭,我們需要非常小心地選擇對配對友好的曲線。

實際上有一種針對橢圓曲線加密系統的攻擊方法稱為 MOV 攻擊(以Menezes, Okamoto和Vanstone命名),它允許使用我們的魔法配對函數來降低系統的安全性。所以我們真的需要小心。然後問題就出現了:什麼對我們而言會更重要?

15 結論

Schnorr 簽名和 BLS 簽名方案都有自己的獨特之處,前者的主要缺點在於需要額外的通信回合,以及不適合較大值 m 和 n 的多重簽名方案,後者的驗證時間則是最大的弊端,兩者共同存在的好處都是可聚合簽名,節省區塊空間。

研究 | 全面對比Schnorr簽名方案和BLS簽名方案

本文鏈接:https://www.8btc.com/article/6684336

轉載請註明文章出處

(0)
上一篇 2021-09-10 17:41
下一篇 2021-09-10 18:08

相关推荐