以太坊和Metamask开发web应用不需要再使用密码

我在ConsenSys为各种客户构建了大量的概念证明,通常他们想要利用以太坊区块链来解决某些业务用例。奇怪的是,这些系统通常设计有标准的网络登录(即用户名和密码)。我总是问自己为什么我还在这样做设计,毕竟,这是今天以太网目前可以解决每个烦人的Web应用程序的一个方面。所以我决定停下脚步,设计一下这个解决方案。

JSON Web token

登录标准Web系统(和/或使用其API)的一种非常流行的方法是将密码(经过哈希的客户端)提交给认证端点并接收token作为回报。这通常称为JSON Web Token,通常在一段有限的时间内(几分钟到几天)有效。这是一个关于标准实现的很好的教程。

JSON Web Token很好,我开始认为在区块链上验证自己很容易。事实上,当你使用以太坊时,你需要不断地去改进。

如果你将以太网地址(这只是公钥的sha3哈希)视为网站上的帐户,则可以通过使用私钥对一段数据进行签名来证明你拥有该帐户,这非常容易。此数据是任意的,可以是网站API提供的任意随机字符串。因此,我们可以使用地址作为用户名并绕过密码的需要。事实上,我们甚至不需要使用区块链来做到这一点。

这是使用Express的样子:

首先,我们需要使用私钥进行椭圆曲线签名:

    var ethUtil = require(‘ethereumjs-util’);  // >=5.1.1
    var data = ‘i am a string’;
    // Elliptic curve signature must be done on the Keccak256 Sha3 hash of a piece of data.
    var message = ethUtil.toBuffer(data);    
    var msgHash = ethUtil.hashPersonalMessage(message);    
    var sig = ethUtil.ecsign(msgHash, privateKey);    
    var serialized = ethUtil.bufferToHex(this.concatSig(sig.v, sig.r, sig.s))    
    return serialized

不要过分担心这些参数是什么。这里有一些密码学,我鼓励你阅读椭圆曲线签名。比特币维基是一个不错的起点。

无论如何,一旦我们有了签名组件,我们就可以将它们与用户的地址一起打包并将其全部发送到认证端点。

POST/Authenticate

    var jwt = require(‘jsonwebtoken’);
    var ethUtil = require('ethereumjs-util');
    function checkSig(req, res) {
      var sig = req.sig;
      var owner = req.owner;
      // Same data as before
      var data = ‘i am a string’;
      var message = ethUtil.toBuffer(data)
      var msgHash = ethUtil.hashPersonalMessage(message)
      // Get the address of whoever signed this message  
      var signature = ethUtil.toBuffer(sig)
      var sigParams = ethUtil.fromRpcSig(signature)
      var publicKey = ethUtil.ecrecover(msgHash, sigParams.v, sigParams.r, sigParams.s)
      var sender = ethUtil.publicToAddress(publicKey)
      var addr = ethUtil.bufferToHex(sender)

      // Determine if it is the same address as 'owner' 
      var match = false;
      if (addr == owner) { match = true; }
      if (match) {
        // If the signature matches the owner supplied, create a
        // JSON web token for the owner that expires in 24 hours.
        var token = jwt.sign({user: req.body.addr}, ‘i am another string’,  { expiresIn: “1d” });
        res.send(200, { success: 1, token: token })
      } else {
        // If the signature doesn’t match, error out
        res.send(500, { err: ‘Signature did not match.’});
      }
    }

所以基本上,给定一些数据,一个地址和一个EC签名的组件,我们可以安全的证明该地址属于签署数据的人。很酷,对吧?

一旦我们对签名和地址匹配感到满意,我们就可以为该地址服务器端签署一个JSON Web token。 在这种情况下,token有效期为1天。

现在我们只需要放入一些中间件来保护任何服务或修改受保护信息的路由。

middleware/auth.js

    function auth(req, res, next) {
      jwt.verify(req.body.token, ‘i am another string’, function(err, decoded) {
        if (err) { res.send(500, { error: ‘Failed to authenticate token.’}); }
        else {
          req.user = decoded.user;
          next();
        };
      });
    }

app.js

    // Routes
    app.post(‘/UpdateData’, auth, Routes.UpdateData);
    …

如果提供的Token对应于发送请求的用户,我们将继续请求路由。请注意,中间件会修改请求。我们需要引用这个新的user参数,因为我们知道它已经在我们的中间件中设置了。

POST/UpdateData

    function UpdateData(req, res) {
      // Only use the user that was set in req by auth middleware!
      var user = req.user;
      updateYourData(user, req.body.data);
      ...
    }

我们终于搞定它了! 你的用户已经完全登录,但不需要密码。

UI方面

用户如何在浏览器中实际签署此数据?Metamask会提供帮助!Metamask是一个整洁的chrome扩展,它将web3注入你的浏览器窗口。

mycomponent.jsx

    makeSig(dispatch) {

     function toHex(s) {
       var hex = ‘’;
       for(var i=0;i<s.length;i++) { hex += ‘’+s.charCodeAt(i).toString(16); }
       return `0x${hex}`;
     }

     var data = toHex(‘i am a string’);
     web3.currentProvider.sendAsync({ id: 1, method: 'personal_sign', params: [web3.eth.accounts[0], data] },
       function(err, result) {
         let sig = result.result;
         dispatch(exchange.authenticate(sig, user))
        })
      }
    }
    render(){
      let { dispatch, _main: { sig } } = this.props;
      if (Object.keys(sig).length == 0) { this.makeSig(dispatch); }
      return (
       <p>I am a webpage</p>
      );
    }

这将触发Metamask弹出一个窗口,要求用户对消息进行签名:

一旦调用了回调,它将调用以下操作:

    authenticate(sig, user) {
      return (dispatch) => {
        fetch(`${this.api}/Authenticate`, {
          method: 'POST',
          body: JSON.stringify({ owner: user, sig: sig}),
          headers: { "Content-Type": "application/json" }
        })
        .then((res) => { return res.text(); })
        .then((body) => {
          var token = JSON.parse(body).token;
          dispatch({ type: 'SET_AUTH_TOKEN', result: token})
        })
      }
    }

一旦你在reducer中保存了auth token,你就可以调用经过身份验证的端点。我们终于得到它了!

请注意,必须从签名中恢复vrs值。Metamask有一个签名util模块,用于显示签名的构造方式。它可以像这样解构:

    var solidity_sha3 = require('solidity-sha3').default;
    let hash = solidity_sha3(data);
    let sig = result.result.substr(2, result.result.length);
    let r = sig.substr(0, 64);
    let s = sig.substr(64, 64);
    let v = parseInt(sig.substr(128, 2));

其中r将被解析为0或1.另请注意,这使用solidity-sha3模块来确保此哈希算法与用作solidity本机hash方法的哈希算法相同(我们正在hash之前签名的十六进制字符串))。

生产准备

我无法强调使用JSON Web token的每个Web应用程序今天都可以轻松利用这一点。具有Metamask扩展的任何用户都可以简单地绕过登录屏幕,其安全性可能比目前用于管理登录的任何内容都要好。这意味着更少的忘记密码,更少的浪费时间和更快乐的用户群。

而且,你知道,如果你希望你的用户在没有中间人的情况下向对方(或你或使用此用户的任何其他系统上的用户)付款,或者如果你想要利用以太坊的其他百万其他功能,那么你需要也这样做。

今天开始,加入我们以太坊,去征服世界。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP专享栏

PHP汉字转拼音

基于 CC-CEDICT 词典的中文转拼音工具,更准确的支持多音字的汉字转拼音解决方案。

28520
来自专栏LINUX阅码场

没有Bug的OS内核? 鸿蒙黑科技之操作系统形式验证与安全认证

IoT operating systems – formal verification and safety/security certification

35230
来自专栏用户5855053的专栏

DigiMarket:货币贬值?现金债券不再安全?数字货币可成替代资产?

据巴克莱和德意志银行的数据,价值超过15万亿美元的全球债券现在正处于负收益状态。自2018年10月以来,这一统计数据几乎增至三倍。对于一种按照正常经济理论毫无意...

10120
来自专栏源中瑞开发技术

虚拟币交易平台app开发技术安全解决方案

应用级别通过交易所管理系统、钱包管理系统两大系统协同保障币安全管理,两大系统独立管理,协同运营账户体系同时分别拥有独立账号体系,审核独立,从分工上保障安全。 ...

14040
来自专栏大数据手稿笔记

Kafka 的事务到底长啥样?

这篇文章主要讲述 Kafka 事务性相关原理,从 Kafka EOS 语义、幂等性、事务性等几个方面阐述。

30110
来自专栏区块链大本营

只需要支付0.5元就可以撤回交易?这下可坑苦DApp了……

骗子们牢牢抓住受害者的心理活动,假冒公检法的身份来突破受害者的心理防线,再罗织一些罪名就能让受害者乖乖交出自己的钱财,等受害者反应过来,骗子们早已逃之夭夭。

8930
来自专栏用户5745643的专栏

区块链技术应用于版权保护与其优势所在

  Nowadays,区块链的应用于各个场景的捷迅可谓是炙手可热。在这个时间节点中,还有诸如墨者链之类的平台将区块链应用于版权保护,并且各个平台已经在实践中实现...

13830
来自专栏AI科技时讯

使用递归神经网络-长短期记忆(RNN-LSTM)预测比特币和以太币价格

2017年对人工智能和加密货币来说是重要的一年, 我们见证了许多新的研究进展和突破。毋庸置疑,人工智能是当今甚至今后很长一段时间内最令人瞩目的技术之一。 而加...

12020
来自专栏区块链大本营

屌!小哥用 12 个月的时间开发了12款比特币Dapp, 0.00000001 BTC就能玩区块链版"蚂蚁庄园"

曾几何时,每个人的朋友圈里都充斥着各种各样的打卡。打开朋友圈你会发现,这个好友在学英语,那个好友在背古诗词,还有一些好友今天又跑步了几公里,好不热闹。

12130
来自专栏nim

只用65行Nim代码写一个自己的区块链

这篇文章的原文为英文,出自 Coral Health公司: Code your own blockchain in less than 200 lines of...

6700

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励