一图了解Google工具栈

Google 一名前员工在 GitHub (1) 上分享了他在 Google 工作时日常使用的工具列表,并详细列出了这些工具列表的外界对应的替代方案。

网友廖君结合现有的资料将学习笔记整理成脑图,并在原文基础上进行了一定的补充和翻译(xmind 源文件下载见链接2)。

(点击图片可以全屏缩放)

相关链接:

  1. github:https://github.com/jhuangtw-dev/xg2xg

  2. xmind 文件链接: https://pan.baidu.com/s/1iAEPf6OfC2YkG-k7TSyq8g 提取码: 6n9m

几种常见的软件授权模式

开源运动同样有自己的游戏规则和道德准则。

不遵行这些规则不但损害开源运动的健康发展,也会对违规者造成名誉和市场上的损失,更可能陷入法律纠纷和赔偿。

现今存在的开源协议很多,而经过Open Source Initiative组织通过批准的开源协议目前有58种。

我们在常见的开源协议如BSD、GPL、LGPL、MIT等都是OSI批准的协议。

  • 什么是许可协议?

    什么是许可,当你为你的产品签发许可,你是在出让自己的权利,不过,你仍然拥有版权和专利(如果申请了的话),许可的目的是,向使用你产品的人提供一定的
    权限。

    不管产品是免费向公众分发,还是出售,制定一份许可协议非常有用,否则,对于前者,你相当于放弃了自己所有的权利,任何人都没有义务表明你的原始作者身
    份,对于后者,你将不得不花费比开发更多的精力用来逐个处理用户的授权问题。

而开源许可协议使这些事情变得简单,开发者很容易向一个项目贡献自己的代码,它还可以保护你原始作者的身份,使你至少获得认可,开源许可协议还可以阻止其它人将某个产品据为
己有。以下是开源界的 5 大许可协议。

以下是一些开源的软件许可协议。

强开源约束授权

  • GNU GPL

    GNU General Public Licence (GPL) 有可能是开源界最常用的许可模式。GPL
    保证了所有开发者的权利,同时为使用者提供了足够的复制,分发,修改的权利:

  • 可自由复制

    你可以将软件复制到你的电脑,你客户的电脑,或者任何地方。复制份数没有任何限制。

  • 可自由分发

    在你的网站提供下载,拷贝到U盘送人,或者将源代码打印出来从窗户扔出去(环保起见,请别这样做)。

  • 可以用来盈利

    你可以在分发软件的时候收费,但你必须在收费前向你的客户提供该软件的 GNU GPL
    许可协议,以便让他们知道,他们可以从别的渠道免费得到这份软件,以及你收费的理由。

  • 可自由修改

    如果你想添加或删除某个功能,没问题,如果你想在别的项目中使用部分代码,也没问题,唯一的要求是,使用了这段代码的项目也必须使用 GPL 协议。

需要注意的是,分发的时候,需要明确提供源代码和二进制文件,另外,用于某些程序的某些协议有一些问题和限制,你可以看一下 @PierreJoye 写的

Practical Guide to GPL Compliance 一文。使用 GPL 协议,你必须在源代码代码中包含相应信息,以及协议本身。

我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。

GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代码做为闭源的商业软件发布和销售。

这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商业软件公司开发的免费软件了。

GPL协议的主要内容是只要在一个软件中使用(“使用”指类库引用,修改后的代码或者衍生代码)GPL
协议的产品,则该软件产品必须也采用GPL协议,既必须也是开源和免费。

这就是所谓的”传染性”。

GPL协议的产品作为一个单独的产品使用没有任何问题,还可以享受免费的优势。

由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。

其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。


弱开源约束授权

MPL License(Mozilla Public License)

允许免费重发布、免费修改,但要求修改后的代码版权归软件的发起者。

这种授权维护了商业软件的利益,,它要求基于这种软件的修改无偿贡献版权给该软件。

这样,围绕该软件的所有代码得版权都集中在发起开发人得手中。

但MPL是允许修改,无偿使用的。

MPL软件对链接没有要求。(要求假如你修改了一个基于MPL协议的源代码,则必须列入或公开你所做的修改,假如其他源代码不是基于MPL则不需要公开其源代码)

  • *GNU LGPL *

    GNU 还有另外一种协议,叫做 LGPL (Lesser General Public Licence),它对产品所保留的权利比 GPL
    少,总的来说,LGPL 适合那些用于非 GPL 或非开源产品的开源类库或框架。因为 GPL 要求,使用了 GPL 代码的产品必须也使用 GPL
    协议,开发者不允许将 GPL 代码用于商业产品。LGPL 绕过了这一限制。

LGPL是GPL的一个为主要为类库使用设计的开源协议。

和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。

LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。

这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。

但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。

因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。

GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品。

  • MIT

    MIT 协议可 能是几大开源协议中最宽松的一个,核心条款是:

    该软件及其相关文档对所有人免费,可以任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版权和许
    可提示。

    这意味着:
    你可以自由使用,复制,修改,可以用于自己的项目。
    可以免费分发或用来盈利。
    唯一的限制是必须包含许可声明。
    MIT 协议是所有开源许可中最宽松的一个,除了必须包含许可声明外,再无任何限制。

MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制。

也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的。


无开源约束授权

  • *BSD *

    BSD 在软件分发方面的限制比别的开源协议(如 GNU GPL)要少。该协议有多种版本,最主要的版本有两个,新 BSD 协议与简单 BSD
    协议,这两种协议经过修正,都和 GPL 兼容,并为开源组织所认可。

    新 BSD
    协议(3条款协议)在软件分发方面,除需要包含一份版权提示和免责声明之外,没有任何限制。另外,该协议还禁止拿开发者的名义为衍生产品背书,但简单 BSD
    协议删除了这一条款。

BSD开源协议是一个给于使用者很大自由的协议。

基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。

但”为所欲为”的前提当你发布使用了BSD协议的代码,或者以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

  • 1、如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。
  • 2、如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
  • 3、不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。

BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。

而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

  • Apache

    Apache 协议 2.0
    和别的开源协议相比,除了为用户提供版权许可之外,还有专利许可,对于那些涉及专利内容的开发者而言,该协议最适合(这里有一篇文章阐述这个问题)。

    Apache 协议还有以下需要说明的地方:

  • 永久权利

    一旦被授权,永久拥有。

  • 全球范围的权利

    在一个国家获得授权,适用于所有国家。假如你在美国,许可是从印度授权的,也没有问题。

  • 授权免费,且无版税

    前期,后期均无任何费用。

  • 授权无排他性

    任何人都可以获得授权

  • 授权不可撤消

    一旦获得授权,没有任何人可以取消。比如,你基于该产品代码开发了衍生产品,你不用担心会在某一天被禁止使用该代码。
    分发代码方面包含一些要求,主要是,要在声明中对参与开发的人给予认可并包含一份许可协议原文。

Apache Licence是著名的非盈利开源组织Apache采用的协议。

该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。

需要满足的条件也和BSD类似:

  • 1、需要给代码的用户一份Apache Licence
  • 2、如果你修改了代码,需要再被修改的文件中说明。
  • 3、在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
  • 4、如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。

你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。

Apache Licence也是对商业应用友好的许可。

使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

  • Creative Commons

    Creative Commons (CC) 并非严格意义上的开源许可,它主要用于设计。Creative Commons
    有多种协议,每种都提供了相应授权模式,CC 协议主要包含 4 种基本形式:

  • 署名权

    必须为原始作者署名,然后才可以修改,分发,复制。

  • 保持一致

    作品同样可以在 CC 协议基础上修改,分发,复制。

  • 非商业

    作品可以被修改,分发,复制,但不能用于商业用途。但商业的定义有些模糊,比如,有的人认为非商业用途指的是不能销售,有的认为是甚至不能放在有广告的网
    站,也有人认为非商业的意思是非盈利。

  • 不能衍生新作品

    你可以复制,分发,但不能修改,也不能以此为基础创作自己的作品。
    这些许可形式可以结合起来用,其中最严厉的组合是“署名,非商用,不能衍生新作品”,意味着,你可以分享作品,但不能改动或以此盈利,而且必须为原作者署名。在这种许可模式下,原始作者对作品还拥有完全的控制权,而最宽松的组合是“署名”,意味着,只要为原始作者署名了,就可以自由处置。

另外
  • Freeware

    不同于Free Software,Freeware
    为【免费软件】而非【自由软件】,虽然它是免费的软件,但是不见得必须要公布其源码,但看释出者的意见!这个东西与Open Source
    毕竟是不太相同的!此外,目前很多标榜免费软件的程序很多都有小问题! 例如假借免费软件的名义,实施窃取使用者数据的目的,所以“来历不明的软件,切勿安装”。

  • *Shareware *

【共享软件】,与【自由软件】有点类似的事,Shareware在使用初期,它也是免费的,但是到了所谓的“试用期限”之后,您就必须选择“付费后继续使用”或者“删除”了,通常这些【共享软件】都会自行撰写是小程序,让你在试用期使用之后就无法使用该软件了。

  • Close Source

程序的核心是封闭的,优点是有专人维护,您不需要去更动他;缺点则是灵活度大打折扣,使用者无法变更该程序成为自己想要的样式,此外,若有木马程序或者安全漏洞,将会花上相当长的一段时间来除虫。

两步认证技术

什么是两步认证

在介绍两步认证之前,首先来看下目前主流的几种认证方式。

[
](https://dn-coding-net-production-pp.codehub.cn/ebc07cdb-948e-434f-ae4f-
d14a81c7893d.png)

上图中的认证方式大体上可以分为三大类

1.You know : 比如密码,这种只有我们知道的

2.You are : 比如指纹,这种只有我们拥有的

3.You have : 比如信用卡,这种只属于你的

了解上面所说的三大类之后,我们就很容易的理解下面几点。

什么是两步认证?

两步验证,对应的英文是 Two-factor Authentication(2FA),从名字可以看出,「两步」是 2FA 的重点,而两步就是我们上面所提到的
You know + You Have ,也就是 密码 + 一次性密码(One Time Password,OTP)

为什么我们需要两步验证?

传统的密码认证方式,如果在用户名密码在其他网站上泄露,任何用户都可以使用你的账号密码进行登陆做任何操作。但有了两步认证就能在一定程度上有效的避免这种情况的发生。因为在每次登录时,不仅需要输入您的帐户密码,还需输入移动设备为您生成的一次性动态验证码

OTP

前面说过,2FA 中使用的是一次性密码(One Time Password,OTP),也被称作动态密码。一般 OTP 有两种策略:HOTP ( HMAC-
based One Time Password) 和TOTP ( Time-based One-time Password)
。目前被广泛使用的正是后者这种基于时间的动态密码生成策略。

算法大体是这样:

  1. 客户端和服务器事先协商好一个SECRET,用于一次性密码的生成过程,此密钥不被任何第三方所知道。此外,客户端和服务器都采用时间做计数器。

  2. 客户端对密钥和计数器的组合(SECRET,time/30)使用HMAC(Hash-based Message Authentication Code)算法计算一次性密码,公式如下:HMAC-SHA-1(SECRET, time/30)

  3. 各种算法加特效后成6位数字

在这里就只简要介绍该算法,如想深入了解

==> https://tools.ietf.org/html/rfc6238

基于TOTP的密码有如下特点

  1. 无需记忆,不会产生password这样的泄漏问题

  2. 动态生成,每30s生成一个,安全性大大提高

  3. 对网络无要求,离线下仍可正常使用

  4. 成本低,无需购买硬件和软件

两步认证流程

  1. 服务器随机生成一个类似于『DPI45HKISEXU6HG7』的密钥,并且把这个密钥保存在数据库中。

  2. 在页面上显示一个二维码,内容是一个URI地址(otpauth://totp/账号?secret=密钥?issuer=厂商)

  3. 客户端扫描二维码,把密钥『DPI45HKISEXU6HG7』保存在客户端。

  4. 客户端每30秒使用密钥『DPI45HKISEXU6HG7』和时间戳通过TOTP『算法』生成一个6位数字的一次性密码

两步认证的其他情况

然后仅仅只是做好上面这种正常的验证流程是不够的,Coding 的两步认证在一些异常情况下做了很多处理。

  1. 生成的 OPT 应该是不能复用的,也就是用户在登陆或者危险操作时输入完一次 OPT 后,手机端 OPT 仍然未刷新时,在进行登陆或者危险操作时输入刚才的OPT是无效的,必须等待手机上OPT的刷新。

  2. 既然可以离线使用,那么怎么保证时间的差异性,我们服务端会兼容服务器时间的前后30s。从而有效的避免细微时间上差异而导致的验证失败,同时也避免了用户刚输入完 OPT 后还未做提交操作时 OPT 刷新而引起验证失败。

  3. 在遇到使用遍历所有6位数数字进行暴力破解 OPT 时,我们会对错误次数进行限制,90s 限制其错误次数能有效避免暴力破解的出现。

  4. 在开启两部认证后,其他所有登陆的客户端都会因为开启两部认证而过期,必须重新登陆。

两部认证的实现

目前 Coding 采用的 https://github.com/wstrange/GoogleAuth 实现的TOTP 算法,在提供 TOTP
算法之外,该库提供了可以存储用户 secret 的接口,采用的 ServiceLoader 方式,ServiceLoader
方式可以通过链接了解更多==>http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html


在对外网开放的后台管理系统中,使用静态口令进行身份验证可能会存在如下问题:

    (1) 为了便于记忆,用户多选择有特征作为密码,所有静态口令相比动态口令而言,容易被猜测和破解;

    (2) 黑客可以从网上或电话线上截获静态密码,如果是非加密方式传输,用户认证信息可被轻易获取;

    (3) 内部工作人员可通过合法授权取得用户密码而非法使用;

静态口令根本上不能确定用户的身份,其结果是,个人可以轻松地伪造一个假身份或者盗用一个已有使用者的身份,给企业造成巨大的经济和声誉损失。本文主要介绍并实现了一种动态口令(OTP)的实现方式。

  动态口令(OTP,One-Time
Password)又称一次性密码,是使用密码技术实现的在客户端和服务器之间通过共享秘密的一种认证技术,是一种强认证技术,是增强目前静态口令认证的一种非常方便技术手段,是一种重要的双因素认证技术,动态口令认证技术包括客户端用于生成口令产生器的,动态令牌,是一个硬件设备,和用于管理令牌及口令认证的后台动态口令认证系统组成。

otp从技术来分有三种形式, 时间同步、事件同步、挑战/应答。

(1) 时间同步

原理是基于 动态令牌动态口令验证服务器的时间比对,基于
时间同步令牌,一般每60秒产生一个新口令,要求服务器能够十分精确的保持正确的时钟,同时对其令牌的晶振频率有严格的要求,这种技术对应的终端是硬件令牌。

(2)事件同步

基于事件同步的令牌,其原理是通过某一特定的事件次序及相同的种子值作为输入,通过HASH算法中运算出一致的密码。

(3)挑战/应答

常用于的网上业务,在网站/应答上输入 服务端下发的
挑战码动态令牌输入该挑战码,通过内置的算法上生成一个6/8位的随机数字,口令一次有效,这种技术目前应用最为普遍,包括刮刮卡、短信密码、动态令牌也有挑战/应答形式。

使用阿里云身份宝(或者Google Authenticator)时间同步实现OTP动态口令

如上图,是一种基于时间同步的OTP计算方式,是通过客户端和服务器持有相同的密钥并基于时间基数,服务端和客户端采用相同的Hash算法,计算出长度为六位的校验码。当客户端和服务端计算出的校验码相同是,那么验证通过。

  由于客户端需要存储密钥和计算校验码的载体,阿里云的身份宝(或者Google
的Authenticator)提供了手机端的APP进行密钥存储和校验码计算。下面我们以这两款客户端为例,实现在应用采用OTP进行权限验证,主要流程如下图:

流程关键代码如下,(更详细代码,请Git下载:https://github.com/suyin58/otp-demo

1 用户注册:

1.1 生成OTP密钥:

1
2
3
String secretBase32 = TotpUtil.getRandomSecretBase32(64);

oper.setOtpSk(secretBase32);

1.2 生成OTP扫描用字符串:

约定字符串格式如下:

1
2
String totpProtocalString = TotpUtil.generateTotpString(operCode, host,
secretBase32);

1.3 将1.2中生成的字符串生成二维码,通过邮件发送给用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
String host = "otptest@wjs.com"; // 自定义

            String totpProtocalString = TotpUtil.generateTotpString(operCode,
host, secretBase32);

            String filePath = f_temp;

            String fileName = Long.toString(System.currentTimeMillis()) +
".png";



            try{

                QRUtil.generateMatrixPic(totpProtocalString, 150, 150,
filePath, fileName);

            }catch (Exception e){

                throw new RuntimeException("生成二维码图片失败:" + e.getMessage());

            }


            String content = "用户名:"+operCode+"</br>"


                    +"系统使用密码 +
动态口令双因素认证的方式登录。</br>请按以下方式激活手机动态口令:</br>安卓用户请点击<a
href='http://otp.aliyun.com/updates/shenfenbao.apk'>下载</a>,"

+"</br>苹果手机在AppStore中搜索【身份宝】(Alibaba)。下载安装后,通过扫描以下二维码激活动态口令。</br>"

                    +"<img src=\"cid:image\">";

            EmailBaseLogic emailBaseLogic = new EmailBaseLogic();

//            String to, String title, String content, String imagePath

            emailBaseLogic.sendWithPic(email,"账户开立通知", content, filePath + "/"
+ fileName);

1.4 将用户注册信息与1.1的OTP密钥存储到数据库中

数据存储代码(略)

2 客户端工具使用

2.1 下载APP

安卓用户下载地址:http://otp.aliyun.com/updates/shenfenbao.apk

苹果手机在AppStore中搜索【身份宝】(Alibaba),或者Google Authenticator

2.2 扫描二维码

使用下载的APP,扫描1.3邮件中的二维码,客户端获取密钥。APP使用密钥基于时间算出6位校验码(每分钟变化)。

1 用户登录

客户端输入登录用户名、用户密码,以及2.2客户端工具中的6位校验码。

1.1 服务端根据用户名和用户密码获取用户信息和密钥

代码参考略

1.2 服务端使用密钥基于时间算出6位校验码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
String secretHex = "";

        try {

            secretHex = HexEncoding.encode(Base32String.decode(secretBase32));

        } catch (Base32String.DecodingException e) {

            LOGGER.error("解码" + secretBase32 + "出错,", e);

            throw new RuntimeException("解码Base32出错");

        }

        long X = 30;

        String steps = "0";

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        df.setTimeZone(TimeZone.getTimeZone("UTC"));

        long currentTime = System.currentTimeMillis() / 1000L;

        try {

            long t = currentTime / X;

            steps = Long.toHexString(t).toUpperCase();

            while (steps.length() < 16) steps = "0" + steps;

            return generateTOTP(secretHex, steps, "6",

                    "HmacSHA1");

        } catch (final Exception e) {

            LOGGER.error("生成动态口令出错:" + secretBase32, e);

            throw new RuntimeException("生成动态口令出错");

        }

1.3 比较客户端和客户端校验码是否一致

代码参考略

其他,Demo中的例子可以使用身份 + 密码,先进行密码验证,在通过动态口令进行二次验证,使系统登录更加安全可靠。


Google
Authenticator是谷歌推出的一款动态口令工具,旨在解决大家Google账户遭到恶意攻击的问题,在手机端生成动态口令后,在Google相关的服务登陆中除了用正常用户名和密码外,需要输入一次动态口令才能验证成功,此举是为了保护用户的信息安全。那么,Authenticator采用了哪些算法?又是如何实现的?且看本文技术解读。

很多手机用户会使用 [Google Authenticator](https://code.google.com/p/google-
authenticator/)(谷歌身份认证)来生成认证令牌,与传统单因子密码不同,其采用的是更安全的双因子(2FA two-factor
authentication
)认证。FA是指结合密码以及实物(信用卡、SMS手机、令牌或指纹等生物标志)两种条件对用户进行认证的方法。只需要在手机上安装如此高大上的密码生成应用程序,就可以生成一个随着时间变化的一次性密码,用于帐户验证,而且这个应用程序不需要连接网络即可工作。

实际上Google Authenticator采用的算法是TOTP(Time-Based One-Time
Password基于时间的一次性密码),其核心内容包括以下三点:

一个共享密钥(一个比特序列);

当前时间输入;

一个签署函数。

共享密钥

共享密码用于在手机端上建立账户。密码内容可以是通过手机拍照二维码或者手工输入,并会被进行base32加密。

手工密码的输入格式如下:

xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

包含该令牌的二维码的内容是一个URL:

otpauth://totp/Google%3Ayourname@gmail.com?secret=xxxx&issuer=Google

时间输入(当前时间)

输入的时间值来自于手机本身,一旦我们获得密钥后,就无需与服务器再进行通信了。但是最重要一点是务必确保手机上的时间是正确的,因为往后的步骤服务器会多次重复使用之前得到的时间值,服务器只会认准这个值。进一步说,服务器会比对所有提交的令牌以确认哪一个是你输入并提交的。

签署

签署所使用的方法是HMAC-SHA1。HMAC的全称是Hash-based message authentication
code(哈希运算消息认证码),以一个密钥和一个消息为输入,生成一个消息摘要作为输出,这里以SHA1作为消息输入。使用HMAC的原因是:只有用户本身知道正确的输入密钥,因此会得到唯一的输出。其算法可以简单表示为:

hmac = SHA1(secret + SHA1(secret + input))

事实上,TOTP是HMAC-OTP(基于HMAC的一次密码生成)的超集,区别是TOTP以当前时间作为输入,而HMAC-
OTP以自增计算器作为输入,该计数器使用时需要进行同步。

算法

首先,要进行密钥的base32加密。虽然谷歌上的密钥格式是带空格的,不过base32拒绝空格输入,并只允许大写。所以要作如下处理:

1
2
3
original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))

第二步要获取当前时间值,这里使用的是UNIX
time
函数,或者可以用纪元秒。

1
input = CURRENT_UNIX_TIME()

在Google Authenticator中,input值拥有一个有效期。因为如果直接根据时间进行计算,结果将时刻发生改变,那么将很难进行复用。Google
Authenticator默认使用30秒作为有效期(时间片),最后input的取值为从Unix epoch(1970年1月1日
00:00:00)来经历的30秒的个数。

1
input = CURRENT_UNIX_TIME() / 30

最后一步是进行HMAC-SHA1运算

1
2
3
4
5
6
7
original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))

input = CURRENT_UNIX_TIME() / 30

hmac = SHA1(secret + SHA1(secret + input))

至此,2FA所需的两个因子都已准备就绪了。但是HMAC运算后的结果会是20字节即40位16进制数,应该没有人会愿意每次都输入这么长的密码。我们需要的是常规6位数字密码!

要实现这个愿望,首先要对20字节的SHA1进行瘦身。我们把SHA1的最后4个比特数(每个数的取值是0~15)用来做索引号,然后用另外的4个字节进行索引。因此,索引号的操作范围是15+4=19,加上是以零开始,所以能完整表示20字节的信息。4字节的获取方法是:

1
four_bytes = hmac[LAST_BYTE(hmac):LAST_BYTE(hmac) + 4]

然后将它转化为标准的32bit无符号整数(4 bytes = 32 bit):

1
large_integer = INT(four_bytes)

最后再进行7位数(1百万)取整,就可得到6位数字了:

1
2
3
large_integer = INT(four_bytes)

small_integer = large_integer % 1,000,000

这也是我们最后要的目标结果,整个过程总结如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))

input = CURRENT_UNIX_TIME() / 30

hmac = SHA1(secret + SHA1(secret + input))

four_bytes = hmac[LAST_BYTE(hmac):LAST_BYTE(hmac) + 4]

large_integer = INT(four_bytes)

small_integer = large_integer % 1,000,000

我在这里准备了一个完整可执行的GO语言程序,感兴趣的朋友请点击点击 [这里](https://github.com/robbiev/two-factor-
auth)进行查看。

英文出自: [Garbagecollected](http://garbagecollected.org/2014/09/14/how-google-
authenticator-works/)


当你使用网银时,网站要求提供六位数动态口令。那么网站是如何验证这六位数是不是正确的呢?验证原理是什么?

令牌实际相当于一个密码本,输进去AAA得到BBB,BBB是正确答案,验证通过。实际用的时候还会令牌会有一个时间有效性的问题,在不同的时间里输入AAA得到的答案是不同的,服务器端认为的正确答案是在随时间变动的,前一分钟有可能是DDD,后一分钟可能是MMM,一般在一个有效时间段(一般为一分钟)才会得到的答案BBB,

每个令牌都有不同ID,帐号先与令牌ID绑定,令牌会根据自身的特定ID与当前时间来计算出6位的随机码。服务器端程序因为
有了令牌ID,所以也可以根据这个令牌的特征和当前时间来生成同样的随机码,然后你提交令牌生成的验证码,服务器会验证与它自己生成的是否一致,一致就通过,不一致就提示错误……

动态口令牌使用唯一的128位种子将其初始化;其内部芯片每分钟都会使用一种算法,组合该种子与当前时间,生成一个随机的数字。而在认证服务器则采取和这个动态密码器同一种算法产生该随机数字,保证动态密码器和我行网银服务器的单一认证,就像每个客户都有了世界上独一无二的身份认证,保证客户使用网银的安全性。

服务器端和每个对应的“动态口令牌”都使用同样的一套算法,可以自定义计算数组的时间间隔。每批次“动态口令牌”都拥有唯一的序列号,然后服务器端和“动态口令牌”执行相同的计算程序,在设定好的相同的更新时间计算出新的数组.

其实上网输入密码服务器验证时跟这个动态口令牌没有有直接物理联系,唯一有联系就是二者根据唯一的序列号,利用公式,你算你的,我算我的。但同一时间算出的数字都是一样的,要不就会验证不能通过,这个6位阿拉伯数字的计算过程中时间是一个很重要的参数,使用时间参数时2者的时间必须要保持一致,要不就会时间不同步导致动态口令牌失效!

对于失去时间同步的令牌,目前可以通过增大偏移量的技术(前后10分钟)来进行远程同步,确保其能够继续使用,降低对应用的影响,但对于超出默认(共20分钟)的时间同步令牌,将无法继续使用或进行远程同步,必须返厂或送回服务器端另行处理。

原理

动态密码的密码其实不是随机的,而是由规律的。当下动态密码分为两类,时间性和事件性。何为时间性动态密码?该类令牌产出动态密码是以时间为参数的,而事件性一般以使用次数为参数的。我们以时间性动态为主要说明对象。整个验证的过程如下:

1.动态密码令牌产生动态密码 以时间和种子为参数,进行迭代,得出动态密码,这里的时间一般是秒数。每个时间性动态密码令牌中会内置一个时钟芯片。

2.服务器校验动态密码。 服务器读取系统时间加上种子,以相同的迭代方法得出动态密码,然后双方进行比对。

讲到这边,可能有所怀疑难道令牌的时间和服务器的时间一定会一致吗?我的答案肯定是不一致的。那怎么能检验的过去呢?原来很简单,服务器校验是是在一个时间区间里校验的,比如现在是12:00,服务器会生成11:55-12:05中所有的动态密码,然后和令牌产生的动态密码比对,这样不就解决了时间不一致的问题了。另外服务器会把令牌和服务器相差的时间记录下来,下次检验的会先把这个偏移值记录下来,以减少动态密码迭代次数,这样就完成了另外一个比较重要的功能,偏移值自动调整。

动态口令,又叫动态令牌、动态密码。它的主要原理是:
用户登录前,依据用户私人身份信息,并引入随机数产生随机变化的口令,使每次登录过程中传送的口令信息都不同,以提高登录过程中用户身份认证的安全性。

  银行通常提供给用户两种动态口令:
一种是固定数量的动态口令,最常见的就是刮刮卡。用户每次根据银行提示,刮开卡上相应区域的涂层,即可获得一个口令。刮刮卡成本低廉,使用方法简单,因此很多银行采用这种方法,如工商银行;
另一种是硬件形式的动态口令,即电子令牌,它采用专用硬件,每次可以用自带的密码生成芯片得到一个当前可用的一次性动态密码,交通银行等就采用这种方式。一般来讲,每个客户端的电子令牌都有一个唯一的密钥,该密钥同时存放在服务器端,每次认证时令牌与服务器分别根据同样的密钥,同样的随机数和同样的算法计算出认证时的动态口令,从而确保口令的一致性和认证的成功。因每次认证时,随机数的参数不同,所以每次产生的动态口令也不同。每次计算时参数的随机性保证了每次口令不可预测,以保证系统安全。

OTP与常用认证技术比较

目前在信息系统中使用的增强型认证技术包括:

1 USBKey: 申请PKI证书。

2 动态口令卡:打印好的密码刮刮卡。

3 动态短信:使用电信通道下发口令。

4 IC卡/SIM卡:内置与用户身份相关的信息。

5 生物特征:采用独一无二的生物特征来验证身份,如指纹。

6 动态令牌:动态口令生成器和认证系统。



动态口令认证技术不足

动态口令认证技术没有第3方权威机构认证,如果业务应用系统安全策略不完善的情况下,可能会受到中间人攻击。如某某银行使用时间型动态令牌受到网络钓鱼攻击。建议在应用中完善安全使用策略,划清口令使用权限,加强交易系统流程控制,用以提高系统安全性。

otpauth://totp/oa?secret=63985989418859891633&period=60&digits=8

secret:密钥,也就是上面生成的seed

period:每60秒生成一次

digits:生成的随机码长度


Golang的实现

https://www.jianshu.com/p/e4b574be0ba6

Java服务端的实现:

https://github.com/wstrange/GoogleAuth

https://github.com/suyin58/otp-demo

Python的实现:

https://github.com/sahands/python-totp

Flutter、Dart的实现:

https://github.com/vubon/dart-totp

算法原理:

https://blog.csdn.net/qq_29951983/article/details/80814272

Measure

Measure

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×