当前仓库属于暂停状态,部分功能使用受限,详情请查阅 仓库状态说明
1 Star 0 Fork 14

kingkong/otp
暂停

forked from superzlc/otp
暂停
 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
otp.py 2.93 KB
一键复制 编辑 原始数据 按行查看 历史
superzlc 提交于 2021-02-26 22:39 . save
# -*- coding: utf-8 -*-
import hashlib,hmac
import struct
import time
import base64
class HOTP:
def __init__(self, secret = None, counter = 0):
self.secret = secret.encode() if secret != None else None
self.counter = counter
def setSecret(self, secret, format = None):
self.secret = self._convertSecret(secret, format)
def gen(self, counter = None):
if counter == None:
if self.counter == None:
self.counter = 0
counter = self.counter
return self._gen(self.secret, counter)
def verify(self, token, counter = None):
if counter == None:
if self.counter == None:
self.counter = 0
counter = self.counter
if (token == self.gen(counter)):
self.counter += 1
return true
return false
return token == self.gen(counter)
@staticmethod
def _gen(secret, counter):
data = counter.to_bytes(8, byteorder='big', signed=False)
hash = hmac.new(secret, data, hashlib.sha1).digest()
offset = hash[19] & 0xf
num = (hash[offset] & 0x7F) << 24 | \
(hash[offset + 1] & 0xFF) << 16 | \
(hash[offset + 2] & 0xFF) << 8 | \
(hash[offset + 3] & 0xFF)
num = num % 1000000
return "%06d"%(num)
@staticmethod
def _convertSecret(secret, format):
if type(secret) == bytes:
return secret
if type(secret) == str:
if 'hex' == format:
return bytes.fromhex(secret)
elif 'base64' == format:
return base64.b64decode(secret.encode())
elif 'string' == format:
return secret.encode()
else:
raise Exception('参数错误')
elif type(secret) == bytes:
return secret
else:
raise Exception('参数错误')
class TOTP:
def __init__(self, secret = None, window = 3, interval = 30):
self.hotp = HOTP(secret, 0)
self.window = window
self.interval = interval
def setSecret(self, secret, format = None):
self.hotp.setSecret(secret, format)
def gen(self, timestamp = None):
if timestamp == None:
timestamp = round(time.time() * 1000)
counter = int(timestamp / 1000 / self.interval)
return self.hotp.gen(counter)
def verify(self, token, timestamp = None):
if timestamp == None:
timestamp = round(time.time() * 1000)
counter = int(timestamp / 1000 / self.interval)
i = 0
w = 0
while(True):
if token == self.hotp.gen(counter - i):
return True
w += 1
if w >= self.window:
break
if i > 0:
if token == self.hotp.gen(counter + i):
return True
w += 1
if w >= self.window:
break
i += 1
return False
# -------------------------------
"""
if __name__ == "__main__":
p1 = HOTP("123456", 0)
print(p1.gen()) # 186818
print(p1.gen(1234)) # 263197
print(p1.verify('263197', 1234))
p2 = TOTP("123456", 3, 30)
print(p2.gen(1614054214456)) # 330925
print(p2.verify('330925', 1614054214456))
p3 = TOTP('helloworld', 3, 30)
p3.setSecret("helloworld", "string")
p3.setSecret("68656c6c6f776f726c64", "hex")
p3.setSecret("aGVsbG93b3JsZA==", "base64")
print(p3.gen(1614054214456)) # 759440
print(p3.verify('759440', 1614054214456))
"""
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/kingkong/otp.git
git@gitee.com:kingkong/otp.git
kingkong
otp
otp
master

搜索帮助