自定义UI的一次性密码(OTP)生成器

在当今的网络安全环境中,两步验证已成为提高账户安全性的重要手段。一次性密码(OTP)是两步验证中常用的一种方式,它通过动态生成的密码来增强安全性。本文将介绍如何在移动设备上实现一个具有自定义用户界面的OTP生成器。

OTP生成器通常是一个运行在移动设备上的应用程序,无论是基于iOS还是Android系统,它们都对HTML5有很好的支持。这使得能够以纯HTML/JavaScript的形式实现OTP生成器,作为一个单页应用程序。

挑战

要实现一个自定义UI的OTP生成器,需要解决以下几个挑战:

  • JavaScript中实现OTP令牌生成。
  • 实现用户界面和逻辑,以每30秒更改一次代码。
  • 确保实现的解决方案能够在离线状态下工作。

逐步实现

根据之前的文章,需要以下组件来实现算法:

  • base32转换库。
  • SHA1加密算法实现。
  • 如果存在,HMAC和OTP算法实现。

倾向于选择MIT或LGPL许可证的库,以便能够将解决方案作为商业用途免费许可。对于base32实现,强烈推荐Nibbler库:

http://www.tumuski.com/2010/04/nibbler/

对于SHA1算法和其他JavaScript中的加密算法,推荐使用Google的CryptoJS库:

http://code.google.com/p/crypto-js/

CryptoJS是一个不断增长的标准和安全的加密算法集合,使用最佳实践和模式在JavaScript中实现。它们快速,并且具有一致且简单的接口。库目前仍在支持和开发中。可以在那里找到sha1和hmac的实现。

对于OTP算法,可以使用NodeJS模块作为基础:

https://github.com/guyht/notp/

问题是该模块专为NodeJS环境设计,因此需要消除所有不必要的依赖,以允许该模块在浏览器环境中工作。MIT许可证允许进行这样的修改。

在这种情况下,不得不进行Buffer对象的端口,使用Nibbler实现base32,并模拟NodeJS crypto模块:

var cryptoFAKE = { createHmac: function(algorithm, key) { var _key = key.value(); return new HMacBasicImpl(_key); } };

结果采用了NOTP类,它提供了计算一次性密码的方式:

Notp.getTOTP(args, err, cb)

参数:包含所需字段K(私钥字符串)的对象。

对于UI,需要回答以下问题:

  • 将在哪里存储密钥(在本节中称为CLUE)。
  • 将如何编程UI。

幸运的是,HTML5允许网页在客户端设备上持久化数据 - DOM存储:

var CLUE = localStorage.getItem('CLUE'); if (typeof(CLUE) === "undefined") { CLUE = null; }

对于单页应用程序,最喜欢的库是KnockoutJS。它允许专注于开发逻辑,并将绑定到Knockout标记的HTML元素外包。

模型:

var Model = { existsclue: ko.observable(CLUE !== null), clue: ko.observable(CLUE), token: ko.observable('XXXXXXX'), notp: new Notp(), UpdateTokenCallback: function(code) { this.token(code); }, UpdateToken: function() { var args = { K: CLUE }; this.notp.getTOTP(args, function(err) { alert(err); }, Model.UpdateTokenCallback.bind(Model)); } };

视图:

<header aria="company logo"> <div class="center"> <img src="im/logo.gif"/> </div> </header> <div id="main" role="main" class="center"> <p data-bind="text:token" id="code">LOADING...</p> <p data-bind="text:clue" id="clue">CLUE</p>( <span data-bind="text:existsclue"></span>) <p data-bind="visible:(!existsclue())" id="syncro"> <a href="setup.php">Please navigate to this link to setup your device!</a> </p> <p> <a href="#" onclick="window.applicationCache.update()">Debug: cache.swapCache()</a> </p> </div>

检测本地存储中是否存在CLUE,如果不存在,则建议客户进行设置(“请导航到此链接以设置设备”)。在真实场景中,可能希望用户使用某种安全方法登录,但为了演示目的,使用简单的方法:将CLUE放入会话并显示QR码,客户设备只需扫描QR码即可配置OTP应用程序。

离线模式

客户在每次需要OTP值时不需要互联网访问。这是利用另一种HTML5技术:离线缓存的地方:

<html class="no-js" lang="en" manifest="appcache.php">

在真实场景中,可能希望清单文件是紧凑的,但再次为了演示目的,让将所有项目脚本包含在离线模式中。

代码运行

将通过一系列屏幕截图来演示代码。

  • 尚未定义CLUE。
  • CLUE设置过程。
  • CLUE已存储,OTP生成。
  • 可以添加到移动设备的主屏幕。
  • 并在离线模式下使用。

重要说明

请确保缓存清单以正确的MIME类型提供:

AddType text/cache-manifest appcache AddType text/cache-manifest .appcache

如果克隆了仓库 - 则调整appcache.php代码,或删除.git文件夹和子文件夹。

https://github.com/Voronenko/JSOTP
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485