加密貨幣是1種數字資產,隨著區塊鏈等相干技術的創新和突破,很多有形或無形資產實現了去中心化。比如我們這里分享的 億書 就是要把數字出版物版權進行保護,實現去中心化,解決業界多年來版權保護不力的困難。
不管數字資產,還是數字出版版權,都是有明確所有權的,當前實現數字資產所屬的技術手段就是本篇要介紹的簽名
。而多重簽名
是對簽名
的擴大使用,給數字資產轉移提供了安全保障和技術手段。本篇,從基本概念入手,詳細了解簽名
和多重簽名
的作用和代碼實現。
主要源碼地址:
signatures.js https://github.com/Ebookcoin/ebookcoin/blob/v0.1.3/modules/signatures.js
multisignatures.js https://github.com/Ebookcoin/ebookcoin/blob/v0.1.3/modules/multisignatures.js
(1)簽名的作用和特點
名字的解釋。簽名
是甚么?有人第1反應是平常生活中的用筆簽名
,那末我會說,你的直覺是對的。不過,當很多小火伴看到網上的很多解釋,卻又迷惑了,事實上不同概念在不同領域的表述是有差別的,但本質相同。我深信生活是1切創作的源泉,任何1個概念都能從生活中找到原型,這里的“簽名”也是如此。
簽名的作用。平常生活中,凡是需要確認歸屬的(是簽名人的,不是其他的),都需要所有者進行簽名。比如,我簽名了1份文件,出了問題,責任我負,我簽名了1個支票,就代表將由我支付。我們普通老百姓最多見的場景,就是去銀行辦業務,銀行職員會讓你反復簽1大堆的單據,想必每一個人都會有深入的印象。
簽名的特點。人的字跡是很個性化的,越熟練的字體,個性特點越固定,因此1個人的名字,不同的人寫出完全相同字跡的幾率非常小,即使是專業模仿也能夠通過技術鑒別出來,這樣1來,人的簽名
就具有唯1性、可驗證的特點,并被法律認可。
簽名的驗證如果,你拿著1張支票去銀行兌換,銀行職員會對支票上的簽名和印章仔細比對,確保印章大小、樣式,和付款人簽名等,與銀行保存的信息1致,才會給你兌付,這就是簽名
驗證。
(2)比特幣客戶端簽名功能
數字資產需要簽名。類比人類簽名,比特幣也有簽名功能。如果了解比特幣錢包(客戶端軟件),就會發現它提供了1個消息簽名的功能,可以用來對其他用戶通過比特幣網絡以外的信息進行簽名和驗證。我個人使用的是 比特幣官方網站 提供的比太錢包,如圖:
這個功能干甚么用的呢?有好多小火伴不清楚,這里舉個簡單的例子解釋1下,具體使用的時候絕不限于這些利用。
Alice開了1個網店,但沒有直接接入比特幣網絡,不能自動確認和驗證支付者。客戶Imfly購買了她的產品,并用比特幣支付了全部貨款。由于比特幣地址和交易都是公然匿名的,為了避免冒充冒領實,Alice需要確認Imfly提供的那個付款地址確切是imfly本人的,否則不能發貨。這時候候,就需要Imfly先把支付貨款的比特幣地址和相干交易簽名信息
(如圖),然后通過QQ或郵件傳給Alice,Alice使用客戶端驗證信息簽名
,才能確認交易確切是Imfly的。
想象1下,如果沒有簽名
功能會怎樣樣呢?由于比特幣僅是1個匿名、安全的支付手段,但卻沒法確認支付方或收款方是誰,信息的不肯定性,將使得比特幣網絡以外的交易沒法達成。在中心化的世界里,這個問題是通過運營平臺這個第3方達成的,比如支付寶等,雙方的全部信息,平臺都掌握,任何1方出現訛詐,都需要通過向平臺投訴來解決。用戶需要對第3方平臺絕對信任,并通過犧牲個人信息安全取得交易的基本保障。
(3)電子簽名
通過上述分析,可以理解的是,簽名
的作用是肯定資產所屬,其特點是簡單、安全、可驗證。把這個概念抽象出來,利用到計算機系統里,為了肯定數字資產所屬,也需要進行簽名
,這就是大家常常看到的“電子簽名”的概念。在網絡世界里,簽名
可以對任何需要確認的數字資產進行處理,比如比特幣地址、電子書版權等,并以此來宣布重要資產的所屬,這讓無需監管的去中心化交易成為可能。
具體開發設計中,就是加密技術代替人的字跡,不然任何簽名方法都會被模仿,而且模仿的本錢極低,相反,驗證的本錢卻很高。具體的加密或驗證技術,請參考前面的章節,這里我們介紹億書是如何使用簽名技術的。
億書也具有簽名能力,只不過,目前沒有單獨提供簽名信息
的操作供用戶使用,而是通過簽名,添加了支付密碼
功能,對用戶帳號資產追加了1層保護。
(4)億書的支付密碼
簽名
方法在modules/signatures.js
文件里,類圖以下:
我們還是從Api開始,代碼以下:
// modules/signatures.js文件
// 179行
router.map(shared, {
"get /fee": "getFee",
"put /": "addSignature"
});
// 188行
library.network.app.use('/api/signatures', router);
通過上面的代碼,可以了解簽名
提供了兩個簡單的公共接口:
get /api/signatures/fee -> shared.getFee
put /api/signatures/ -> shared.addSignature //簽名操作
明顯,最核心的方法也就是shared.addSignature
,代碼:
// 215行
shared.addSignature = function (req, cb) {
...
library.scheme.validate(body, {
properties: {
...
},
required: ["secret", "secondSecret"]
}, function (err) {
...
library.balancesSequence.add(function (cb) {
if (body.multisigAccountPublicKey && body.multisigAccountPublicKey != keypair.publicKey.toString('hex')) {
modules.accounts.getAccount({publicKey: body.multisigAccountPublicKey}, function (err, account) {
...
try {
var transaction = library.logic.transaction.create({
type: TransactionTypes.SIGNATURE, // 297行
sender: account,
keypair: keypair,
requester: keypair,
secondKeypair: secondKeypair,
});
} catch (e) {
return cb(e.toString());
}
...
}
毫無疑問,支付密碼
也是1個簡單的交易(交易類型TransactionTypes.SIGNATURE
,見297行)。基于此,我們不難想象,添加類似比特幣的簽名
功能也是件非常簡單的事情,我們會在億書下1個版本里添加這項功能,具體請關注 億書幣版本庫 最新進展。
上面我們提到,比特幣的匿名性,使交易處于不可信當中,終究致使用戶不敢交易。有了簽名功能,就有了確認雙方信息的有效手段,問題總算有了解決方案。聰明的小火伴會發現,簽名和驗證進程除繁瑣,并沒有讓我們覺得比使用第3方平臺更有效、更安全。有無更好的解決方案呢?回答是:有,那就是多重簽名。
(1)基本概念
多重簽名,可以簡單的理解為1個數字資產的多個簽名。簽名標定的是數字資產所屬和權限,多重簽名預示著數字資產可由多人安排和管理。在加密貨幣領域,如果要動用1個加密貨幣地址的資金,通常需要該地址的所有人使用他的私鑰(由用戶專屬保護)進行簽名。那末,多重簽名,就是動用這筆資金需要多個私鑰簽名,通常這筆資金或數字資產會保存在1個多重簽名的地址或帳號里。這就好比,我們工作中有1份文件,需要多個部門簽署才能生效1樣。
在實際的操作進程中,1個多重簽名地址可以關聯n個私鑰,在需要轉賬等操作時,只要其中的m個私鑰簽名就能夠把資金轉移了,其中m要小于等于n,也就是說m/n小于1,可以是2/3, 3/5等等,是要在建立這個多重簽名地址的時候肯定好的。
(2)工作原理
數字資產在某種情況下,需要多人安排。換句話說,在某些特定條件下,數字資產如果沒法確認歸屬某個特定的人,那末最好讓相干人共同簽署它的所有權。
依然舉上面的例子,在Alice發貨以后,Imfly收到貨之前,這筆錢應當由第3方信譽比較高的中介暫時保存,這個階段,這筆錢要末是Alice的,要末是Imfly的,終究的歸屬要看Imfly是不是收到貨。所以,這個第3方,不管如何都是應當有的,不然Imfly就要承當大部份風險(由于比特幣的單向不可逆,Imfly發送以后就沒有辦法收回了)
這樣1來,這筆錢的所屬關系,在交易進程中觸及到Alice、Imfly和平臺第3方(雖然不屬于它,但它有權裁定資金去向),那末就應當由他們3方簽名,因此網上購物就是典型的多重簽名的例子。其多重簽名模型就是2/3,也就是說只要他們中的兩個簽名,資金就能夠被轉移。
具體到這個例子,Imfly把錢打給1個關聯3方私鑰的多重簽名地址,如果全部交易進程順利,只要Alice和Imfly兩個簽名,這筆錢就會順利到達Alice手里。如果不順利,他們任何1人提出仲裁,平臺第3方調查以后,通過簽名就可以把這筆錢轉給Alice或退回Imfly。這非常類似淘寶和京東的模式,但是比他們更加便捷和安全,最少不用擔心第3方倒閉、挪用資金或攜款跑路。
(3)利用場景
很明顯,多重簽名給了加密貨幣騰飛的翅膀,讓它單1單項支付的能力更具吸引力,讓加密貨幣技術利用到各行各業成為可能。這里簡單的羅列幾個利用場景,供探索和思考:
多重簽名的設計,讓各種業務去中心化充滿無窮可能。
(4)億書的多重簽名
多重簽名
方法在modules/multisignatures.js
文件里,類圖以下:
實現Api的代碼以下:
// 318行
router.map(shared, {
"get /pending": "pending", // Get pending transactions
"post /sign": "sign", // Sign transaction
"put /": "addMultisignature", // Add multisignature
"get /accounts": "getAccounts"
});
// 329行
library.network.app.use('/api/multisignatures', router);
解析1下,最后產生的Api以下:
get /api/multisignatures/pending -> shared.pending // 查詢等待中的交易
post /api/multisignatures/sign -> shared.sign // 簽名交易
put /api/multisignatures/ -> shared.addMultisignature // 創建多重簽名帳號
get /api/multisignatures/accounts -> shared.getAccounts // 取得關聯的帳號(對應者用戶私鑰)
提供的功能很明顯,包括:待交易查詢、關聯帳號列表查詢,用戶簽名交易,創建多重簽名帳號等4個核心功能。我們先從創建多重簽名帳號開始,這個Api使用的是http的put
方法,對應的自然是更新
操作,不查看代碼也能夠料想到,該功能應當是在已有帳號基礎上的操作,從客戶端錢包設置
菜單里,可以看到如圖操作:
看看shared.addMultisignature
的源代碼以下:
// modules/multisignatures.js文件
shared.addMultisignature = function (req, cb) {
var body = req.body;
library.scheme.validate(body, {
...
// 732行
required: ['min', 'lifetime', 'keysgroup', 'secret']
}, function (err) {
...
library.balancesSequence.add(function (cb) {
modules.accounts.getAccount({publicKey: keypair.publicKey.toString('hex')}, function (err, account) {
...
// 767行
try {
var transaction = library.logic.transaction.create({
type: TransactionTypes.MULTI, // 769行
sender: account,
keypair: keypair,
secondKeypair: secondKeypair,
min: body.min,
keysgroup: body.keysgroup,
lifetime: body.lifetime
});
} catch (e) {
return cb(e.toString());
}
...
};
從732行可知,創建1個多重簽名,必須’min’, ‘lifetime’, ‘keysgroup’, ‘secret’這4參數(其實,1個默許參數就是當前帳號),min代表上面講到的m
值,即需要確認的人數;lifetime代表生命周期;keysgroup包括多重簽名關聯的全部帳號,它是數組類型,包括的元素個數就是n
;secret是用戶密碼,與用戶私鑰對應。
經過1系列的驗證以后,作為1個交易(交易類型TransactionTypes.MULTI,769行)保存到數據庫(區款鏈)里。創建成功的帳號,可以顯示多重帳號菜單,對交易進行操作。接下來,自然應當能夠查看全部關聯的帳號(請看shared.getAccounts方法),查看待確認的交易
(請看shared.pending方法),這兩個方法僅僅是簡單的查詢,沒甚么難度,這里不再浪費篇幅。
如果用戶同意交易,就能夠對待確認的交易
進行簽名(shared.sign方法),這個方法的源碼以下:
// 586行
shared.sign = function (req, cb) {
var body = req.body;
library.scheme.validate(body, {
...
required: ['transactionId', 'secret']
}, function (err) {
...
// 632行
function done(cb) {
library.balancesSequence.add(function (cb) {
// 634行
var transaction = modules.transactions.getUnconfirmedTransaction(body.transactionId);
if (!transaction) {
return cb("Transaction not found");
}
// 640行
transaction.signatures = transaction.signatures || [];
transaction.signatures.push(sign);
library.bus.message('signature', {
signature: sign,
transaction: transaction.id
}, true);
cb();
}, function (err) {
if (err) {
return cb(err.toString());
}
cb(null, {transactionId: transaction.id});
});
}
...
};
這個方法,相比單獨的簽名方法,不同的是單獨的簽名方法相當于1個新建交易,而這里的多重簽名的用戶簽名,明顯僅僅是對未確認交易(634行)進行簽名確認(640行保護了1個簽名數組,641行的push方法把用戶簽名寫入數組)。而且,相比獨立簽名,驗證也更復雜,我們將在下1篇《交易》1文中集中討論驗證問題。您也能夠結合下1篇的內容,瀏覽和理解這里的簽名方法。
在加密貨幣里,每個交易都觸及到使用私鑰簽名,用于確認每筆資金所有人。肯定了所有人,自然就肯定了資金轉移的條件、目標和方向,就為我們下1步進行資金轉移操作奠定了基礎。很自然的,該研究1下億書的交易了,請看下1篇:《交易》。
本系列文章即時更新,若要掌握最新內容,請關注下面的鏈接
根源文地址: https://github.com/imfly/bitcoin-on-nodejs
首發區塊鏈俱樂部: http://chainclub.org
億書官方網站: http://ebookchain.org
億書開發QQ群: 185046161 (億書為開源項目,歡迎各界小火伴參與)
億書白皮書 http://ebookchain.org/ebookchain.pdf