依赖
npm install --save base32-decode
npm install --save python-struct
代码
主逻辑
import Authenticator from "./authenticator.js" // 这里确定 Authenticator 类的位置
secretKey = 'secret key' // 这个是 google 验证器的私钥
const a = new Authenticator({secretKey})
console.log(a.calcGoogleCode())
Authenticator 类
const BLOCK = 8 // 常量
class Authenticator {
constructor({
secretKey,
}) {
this.secretKey = secretKey
}
calcGoogleCode () {
const secretKeyLength = this.secretKey.length
const secretKeyPanLength = Math.ceil(secretKeyLength / BLOCK) * 8 - secretKeyLength
const secretKey = this.secretKey + "=".repeat(secretKeyPanLength)
/* hmac code */
const key = base32Decode(secretKey, 'RFC4648')
const duration_input = parseInt((new Date()).getTime() / 30000)
const msg = struct.pack('>Q', duration_input)
const hmac = createHmac('sha1', key)
hmac.update(msg)
const googleCode = hmac.digest()
/* Truncate */
const o = googleCode[19] & 15
let _googleCode = `${(struct.unpack(">I", googleCode.subarray(o, o + 4))[0] & 0x7fffffff) % 1000000}`
if (_googleCode.length === 5) {
_googleCode = '0' + _googleCode
}
return _googleCode
}
}
原理
参数:生成 code 的过程,需要 密钥
和 计时器
的组合来构建,计时器取 30s 的时间间隔
;
生成:密钥和计数器的组合(K,C)
,使用HMAC(Hash-based Message Authentication Code)算法进行一次性加密;
算法:HOTP(K,C) = Truncate(HMAC-SHA-1(H, C)
,因为加密后的字符串会比较长,所以会进行截取部分不变的信息作为 Code;
总结
生成 google 验证器的 code 时,需要的参数不多,就是 密钥和时间戳(可以设置时间间隔的时间戳),然后通过 hmac 进行加密,截取部分内容生成 6 位数的密码。
这里有一个 python 的实现
参考链接
- String.prototype.repeat()
- Node.js Base64 Encoding和Decoding
- npm - base32-decode
- base64 — Base16, Base32, Base64, Base85 Data Encodings
- python-struct
- struct --- 将字节串解读为打包的二进制数据
- Node.js hmac.digest() Method
- 完美解决 node.js 模块化后报错 ReferenceError: require is not defined
- Python-Python3 生成 Google Authenticator 的 6 位验证码
- hmac --- 基于密钥的消息验证
- 解决node环境下SyntaxError: Cannot use import statement outside a module的问题
- Date.prototype.getTime()
- Python - //和/的区别
- 使用google身份验证器实现动态口令验证
- RFC4226
- 谷歌验证 (Google Authenticator) 的实现原理是什么?
网友评论