• 加密和验证
    • 前言
    • 源码
    • 类图
    • 流程图
    • 概念
      • (1)私钥和公钥
      • (2)加密货币地址
      • (3)加密过程
      • (4)验证过程
  • 实践
  • 总结
  • 参考

    加密和验证

    前言

    加密解密技术在加密货币开发中的作用不言而喻。但技术本身并不是什么新鲜事,重要的是如果没有前面的P2P网络,和后面要介绍的区块链,单独的加解密显然没有那么神奇,加密货币也不会成为无需验证、高度可信的强大网络。

    但是,提到加解密技术,业界的通则是,使用现成的组件,严格按照文档去做,别自作聪明,这也是使用加密解密技术的最安全方式。这篇就来研究亿书是如何使用加解密技术的。

    源码

    Ebookcoin没有提供相关扩展,全部使用Node.js自己的crypto模块进行加密,使用Ed25519组件签名认证。本文涉及到的代码:

    accounts.js: https://github.com/Ebookcoin/ebookcoin/blob/v0.1.3/modules/accounts.js

    account.js: https://github.com/Ebookcoin/ebookcoin/blob/v0.1.3/logic/account.js

    类图

    crypto-class.png

    流程图

    crypto-activity.png

    概念

    仅仅介绍涉及到的最少概念(说实话,多了咱也不会,甚至不敢)。

    (1)私钥和公钥

    加密技术涉及的概念晦涩,讲个小故事,就一下清楚了。大学一哥们追女朋友有贼心没贼胆,一直不敢当面说“I love you”,就想了一招,顺手写下”J mpwf zpv”交给了另一位女生,让她帮忙传信。然后,等女朋友好奇打来电话时,他就告诉她依次向前顺延1个字母,组合起来就是他想说的话。

    暂且不论成功与否,先看概念:这里的“I love you”就是明文,”J mpwf zpv”就是密文,向后顺延1个字母是加密过程,向前是解密过程,而这个规则就是算法。这种简单的加解密过程,就叫“对称加密”。缺点很显然,必须得打电话告诉女朋友怎么解密,岂不知隔墙有耳。

    当然,更安全的方式是不要打电话也能处理。自然就是这里的私钥和公钥,它们都是长长的字符串值,私钥好比银行卡密码,公钥好比银行卡账户,账户谁都可以知道,但只有掌握私钥密码的人才能操作。不过,私钥和公钥更为贴心与先进,用私钥签名的信息,公钥可以认证确认,相反也可以。这就为网络传输和加密提供了便利。这就是“非对称加密”。

    (2)加密货币地址

    拿加密货币的鼻祖,比特币而言,一个比特币地址就是一个公钥,在交易中,比特币地址通常以收款人出现。如果把比特币交易必作一张支票,比特币地址就是收款人,也就是我们要写上收款人一栏的内容。

    而私钥就是一个随机选出的数字而已,在比特币交易中,私钥用于生成支付比特币所必需的签名以证明资金的所有权,即地址中的所有资金的控制取决于相应私钥的所有权和控制权。

    私钥必须始终保持机密,因为一旦被泄露给第三方,相当于该私钥保护之下的比特币也拱手相让了。私钥还必须进行备份,以防意外丢失,因为私钥一旦丢失就难以复原,其所保护的比特币也将永远丢失。

    Ebookcoin也是如此,只不过更加直接的把生成的公钥地址作为用户的ID,用作网络中的身份证明。更加强调用户应该仔细保存最初设定的长长的密码串,代替单纯的私钥保存,更加灵活。

    (3)加密过程

    Node.js的Crypto模块,提供了一种封装安全凭证的方式,用于HTTPS网络或HTTP连接,也对OpenSSL的Hash,HMAC,加密,解密、签名和验证方法进行了封装。

    在币圈里,谈到加密技术时,经常听到Hash算法。很多小盆友时常与数组(array)和散列(hash)等数据格式混淆,以为Hash算法获得的结果都像json格式的键值对似的。

    其实,这是语言上的差异,Hash还有n. 混杂,拼凑; vt. 搞糟,把…弄乱的意思。所以,所谓的hash算法,解释为混杂算法或弄乱算法,更加直观些。

    Ebookcoin使用的是sha256Hash算法(除此之外,还有MD5,sha1,sha512等),这是经过很多人验证的有效安全的算法之一(请看参考)。通过Crypto模块,简单加密生成一个哈希值:

    1. var hash = crypto.createHash('sha256').update(data).digest()

    这个语句拆开来看,就是crypto.createHash('sha256')先用sha256算法创建一个Hash实例;接着使用.update(data)接受明文data数据,最后调用.digest()方法,获得加密字符串,即密文

    然后,使用Ed25519组件,简单直接地生成对应密钥对:

    1. var keypair = ed.MakeKeypair(hash);

    (4)验证过程

    加密技术的作用,重在传输和验证。所以,加密货币并不需要研究如何解密原文。而是,如何安全、快捷的验证。Ebookcoin使用了Ed25519第三方组件。

    该组件是一个数字签名算法。签名过程不依赖随机数生成器,没有时间通道攻击的问题,签名和公钥都很小。签名和验证的性能都极高,一个4核2.4GHz 的 Westmere cpu,每秒可以验证 71000 个签名,安全性极高,等价于RSA约3000bit。一行代码足矣:

    1. var res = ed.Verify(hash, signatureBuffer || ' ', publicKeyBuffer || ' ');

    实践

    Ebookcoin世界里,Ebookcoin把用户设定的密码生成私钥和公钥,再将公钥经过16进制字符串转换产生帐号ID(类似于比特币地址)。付款的时候,只要输入这个帐号ID(或用户别名)就是了。该ID,长度通常是160⽐特(20字节),加上末尾的L后缀,也就是21字节长度。

    因此,在使用的过程中会发现,软件(钱包程序)仅仅要求输入密码(通常很长),而不像传统的网站,还要用户名之类的信息。这通常就是加密货币的好处,即保证了安全,也实现了匿名。

    Ebookcoin要求用户保存好最初设定的长长的明文密码串,它是找回帐号(保存着用户的加密货币财富)的真正钥匙。这比直接保管私钥方便得多,当然,风险也会存在,特别是那些喜欢用短密码的人。为此,Ebookcoin提供了二次签名(类似于支付密码)、多重签名等措施,弥补这些问题。

    这里,仅研究一下用户ID的生成,体验上述过程,请看代码:

    1. // modules/accounts 628行
    2. shared.generatePublickey = function (req, cb) {
    3. var body = req.body;
    4. library.scheme.validate(body, {
    5. ...
    6. required: ["secret"]
    7. }, function (err) {
    8. ...
    9. // 644行
    10. privated.openAccount(body.secret, function (err, account) {
    11. ...
    12. cb(err, {
    13. publicKey: publicKey
    14. });
    15. });
    16. });
    17. };
    18. // 447行
    19. privated.openAccount = function (secret, cb) {
    20. var hash = crypto.createHash('sha256').update(secret, 'utf8').digest();
    21. var keypair = ed.MakeKeypair(hash);
    22. self.setAccountAndGet({publicKey: keypair.publicKey.toString('hex')}, cb);
    23. };
    24. // 482行
    25. Accounts.prototype.setAccountAndGet = function (data, cb) {
    26. var address = data.address || null;
    27. if (address === null) {
    28. if (data.publicKey) {
    29. // 486行
    30. address = self.generateAddressByPublicKey(data.publicKey);
    31. ...
    32. }
    33. }
    34. ...
    35. // 494行
    36. library.logic.account.set(address, data, function (err) {
    37. ...
    38. });
    39. };
    40. // modules/accounts 455行
    41. Accounts.prototype.generateAddressByPublicKey = function (publicKey) {
    42. var publicKeyHash = crypto.createHash('sha256').update(publicKey, 'hex').digest();
    43. var temp = new Buffer(8);
    44. for (var i = 0; i < 8; i++) {
    45. temp[i] = publicKeyHash[7 - i];
    46. }
    47. var address = bignum.fromBuffer(temp).toString() + 'L';
    48. if (!address) {
    49. throw Error("wrong publicKey " + publicKey);
    50. }
    51. return address;
    52. };

    说明:上面628行,是产生公钥的方法,通常需要用户提供一个密码secret。447行,可以看到,将用户密码进行加密处理,然后直接生成了密钥对,接着将公钥继续处理。486行调用了方法generateAddressByPublicKey,455行,该方法对公钥再一次加密,然后做16进制处理,得到所要地址。

    过程中,对于私钥没有任何处理,直接无视了。这是因为,这里的使用方法ed25519,基于某个明文密码的处理结果不是随机的,用户只要保护好自己的明文密码字符串,就可以再次生成对应私钥和公钥。

    总结

    加解密技术专业性很强,需要花费时间深入研究。我在前人研究成果的基础上进行了汇总和再加工,绘制了三张脑图,建议阅读,详情见第四部分《三张图让你全面掌握加密解密技术》一章。本篇权当入门,并没有对交易、区块链和委托人等的加密验证处理过程进行分析,加密解密过程都比较类似,后续阅读时会进一步说明。

    其实,加密和验证的过程贯穿于亿书的全过程,接下来我们逐一揭开他们神秘的面纱。请看下一篇:地址

    参考

    Ed25519官方网站