更多互联网新鲜资讯、工作奇淫技巧关注原创【飞鱼在浪屿】(日更新)
基于时间的一次性密码(TOTP)算法基本流程
在最高级别上,您在这些应用上看到的密码是使用TOTP(Time-based One-Time Passwords,基于时间的一次性密码)算法创建的。密码是通过结合身份验证所用服务的密钥和当前时间生成的。这就是为什么代码总是在几秒钟后过期的原因。
如果用过这些应用程序(Twilio Authy,Google Authenticator,Microsoft Authenticator,这些app都可以在苹果商店/安卓市场下载到),则可能会记得必须在整个过程中的某个地方需要扫描二维码。扫描二维码就是读取二维码的密钥,存到设备存储中。该算法与SIM卡,蜂窝网络提供商或电话的品牌/型号无关,因此比向用户发送验证码应用性更强。该算法的相关因素是当前时间和共享密钥。
每当在支持TOTP的服务上创建新帐户时,都会为你的用户帐户生成唯一的密码。然后,下次您登录时,该网站将运行客户端运行的相同算法来生成密码。如果来自客户端的密码与服务器生成的密码相匹配,则对用户进行身份验证,并且完成了双重身份验证过程。
算法如何工作
让我们看看从头开始实现TOTP服务需要做些什么。
TOTP是基于HMAC的一次性密码算法(HOTP)构建的,先了解下HMAC。
HMAC(基于哈希的消息身份验证代码)使用了以下东西:
- 加密哈希函数(通常为SHA1)
- 秘密密钥
- 计数器(客户端和服务器TOTP进程通过计数器保持同步)
生成唯一的基于时间的身份验证代码。
TOTP和HOTP / HMAC之间的主要区别在于计数器属性。
HOTP的计数器通常是事件驱动的,例如,按下按钮会更改计数器的值。
而在TOTP中,计数器值是基于当前时间戳设置的。
让我们看一下端到端的流程。
首先,我们将从时间戳创建一个计数器。为了避免引入额外的复杂性,将使用从纪元开始的时间戳,该时间戳与时区无关。
使用从纪元开始到现在时间经过了多少个Tx间隔来作为HOTP算法的输入。简而言之,此计算是为了找出用户有多少Tx间隔。
实践
以下是Swift代码的实现:
let secretKey = "digitalbunker" let counter = "53283545" let hmacResult: String = secretKey.hmac(algorithm: .SHA1, counter: counter)
有了共享密钥secretKey和计数器counter,经过hmac不可逆运算,得到一个哈希值hmacResult(1OyZRjbfhe+8womld8xldXo5V9M=)。
接下来,将此哈希值转换为十六进制字符串hexString:
let data = Data(hmacResult.utf8)let hexString = data.map{String(format:"%02x ", $0)}
hexString现在等于31 4f 79 5a 52 6a 62 66 68 65 2b 38 77 6f 6d 6c 64 38 78 6c 64 58 6f 35 56 39 4d 3d。
这并不像是用户每次进行身份验证时键入的内容。让可以找到一种更简单的表示方式,6位代码将是一种很好的用户友好选择。
我们将通过称为动态截断的过程将此哈希值转换为较短的代码。
动态截断包括获取十六进制字符串最后一个字节的低4位,并将其用作字符串的偏移量,以帮助创建6位代码,同时仍然保持安全。
最后一个字节是3d指最后4位是十六进制d(十进制13)。
从偏移量13开始,截取接下来的4个字节:
31 4f 79 5a 52 6a 62 66 68 65 2b 38 77 6f 6d 6c 64 38 78 6c 64 58 6f 35 56 39 4d 3d
现在,我们将转换0x6f6d6c64为十进制1869442148。由于只需要一个6位数字的代码,因此我们可以取最后6位数字442148并将其返回给用户。
现在,服务器将执行3个完全相同的步骤序列。也就是说它将检查当前的30秒间隔,上一个间隔和下一个间隔,以解决时钟不一致问题。如果服务器的代码与用户输入的代码匹配,则对用户进行身份验证通过。
总结
攻击者可以像其他密码一样篡改TOTP值,但是攻击者必须几乎客户端和服务端实时地窃取凭据。这加大了被攻击的难度,提升了安全等级。
如果时间容忍性太大,安全等级会降低。可以缩短代码的TTL。TOTP代码的标准TTL范围从10到30秒不等,以解决时间延迟(客户端和服务器端),不同步的时钟以及用户的易用性。随时调整TTL以满足你的安全需求。但是,如果攻击者能够找到共享密钥,则可以随意创建有效的TOTP代码,也就被攻击到,所以保护好密钥是最重要的事情。