程序员人生 网站导航

《Nodejs开发加密货币》之十九:签名和多重签名

栏目:php教程时间:2016-09-03 15:31:49

前言

加密货币是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个消息签名的功能,可以用来对其他用户通过比特币网络以外的信息进行签名和验证。我个人使用的是 比特币官方网站 提供的比太钱包,如图:

bither-wallet-sign.png

这个功能干甚么用的呢?有好多小火伴不清楚,这里举个简单的例子解释1下,具体使用的时候绝不限于这些利用。

Alice开了1个网店,但没有直接接入比特币网络,不能自动确认和验证支付者。客户Imfly购买了她的产品,并用比特币支付了全部货款。由于比特币地址和交易都是公然匿名的,为了避免冒充冒领实,Alice需要确认Imfly提供的那个付款地址确切是imfly本人的,否则不能发货。这时候候,就需要Imfly先把支付货款的比特币地址和相干交易签名信息(如图),然后通过QQ或邮件传给Alice,Alice使用客户端验证信息签名,才能确认交易确切是Imfly的。

想象1下,如果没有签名功能会怎样样呢?由于比特币仅是1个匿名、安全的支付手段,但却没法确认支付方或收款方是谁,信息的不肯定性,将使得比特币网络以外的交易没法达成。在中心化的世界里,这个问题是通过运营平台这个第3方达成的,比如支付宝等,双方的全部信息,平台都掌握,任何1方出现讹诈,都需要通过向平台投诉来解决。用户需要对第3方平台绝对信任,并通过牺牲个人信息安全取得交易的基本保障。

(3)电子签名

通过上述分析,可以理解的是,签名的作用是肯定资产所属,其特点是简单、安全、可验证。把这个概念抽象出来,利用到计算机系统里,为了肯定数字资产所属,也需要进行签名,这就是大家常常看到的“电子签名”的概念。在网络世界里,签名可以对任何需要确认的数字资产进行处理,比如比特币地址、电子书版权等,并以此来宣布重要资产的所属,这让无需监管的去中心化交易成为可能。

具体开发设计中,就是加密技术代替人的字迹,不然任何签名方法都会被模仿,而且模仿的本钱极低,相反,验证的本钱却很高。具体的加密或验证技术,请参考前面的章节,这里我们介绍亿书是如何使用签名技术的。

亿书也具有签名能力,只不过,目前没有单独提供签名信息的操作供用户使用,而是通过签名,添加了支付密码功能,对用户帐号资产追加了1层保护。

(4)亿书的支付密码

签名方法在modules/signatures.js文件里,类图以下:

signatures-class.png

我们还是从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单项支付的能力更具吸引力,让加密货币技术利用到各行各业成为可能。这里简单的罗列几个利用场景,供探索和思考:

  • 电子商务。比较常见的是2/3的模式。上面电子商务网站的例子,就是最典型的场景之1,目前已有成功的案例了。延伸1下,这类利用本质就是中介,所以还可用在各类中介机构性质的服务上。
  • 财产分割。比如夫妻双方共有财产,可使用1/2的模式,1个账户谁都可使用,跟各自具有帐号1样,好处是系统忠实记录了每一个人的花消,闹掰的时候很容易清算。扩大到公司合伙经营,可使用1/n模式,n个人合伙人,都可以直接安排共有资金,具体清算时,1目了然。
  • 资金监管。其实,这是多重签名的最直接作用,1笔钱需要多个人签名才能使用,任何1个人都没法直接动用资金,这在生活中太常见了,只要灵活设置多重签名的比重模式,就可以解决生活中很多问题。比如,接着上面夫妻的例子,夫妻要储备1笔资金,供孩子上大学使用,在这之前谁都不能动,那末把模式改成2/2,不但限制了夫妻双方,也给黑客攻击增加了难度。

多重签名的设计,让各种业务去中心化充满无穷可能。

(4)亿书的多重签名

多重签名方法在modules/multisignatures.js文件里,类图以下:

multisignatures-class.png

实现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方法,对应的自然是更新操作,不查看代码也能够料想到,该功能应当是在已有帐号基础上的操作,从客户端钱包设置菜单里,可以看到如图操作:

addMultisignature.png

看看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) { ... // 767try { 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) { ... // 632function 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

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐