相同密钥下Time based OTP在Badger 2040上结果不一致原因
Badger 2040运行MicroPython生成TOTP结果不一致的核心原因
TOTP算法生成结果完全由三个核心条件决定:准确的UTC Unix时间戳、正确解码的原始密钥字节、符合标准的HMAC-SHA1计算与截断逻辑,跨平台结果不一致基本逃不开以下几类问题:
- 设备时间源错误
Badger 2040本身不带掉电保持的硬件RTC,没有配纽扣电池供电,只要一断电,系统时间就会重置为固件内置的初始时间(大多是2021年1月1日)。如果上电后没有主动通过NTP或者手动校准到标准UTC时间,utime.time()返回的秒数和真实时间能差几个月甚至几年,算出来的时间步长T = 当前Unix时间戳 // 30完全不对,生成的OTP自然和其他平台对不上。
另外两个容易踩的时间坑:一是部分旧版本Badger 2040固件的utime.time()返回的是设备从上电开始算的运行秒数,根本不是从1970-01-01 00:00:00 UTC起算的标准Unix时间戳;二是校时的时候误用了本地时间而不是UTC时间,比如东八区直接把北京时间当UTC输入,会差8小时,步长直接偏960个周期,结果完全错。 - Base32密钥解码逻辑不兼容
你使用的TOTP实现如果是自写的简易Base32解码,在MicroPython下很容易出兼容问题:比如没自动把小写的密钥转成大写、没正确处理Base32末尾的=填充符、位运算拼字节的时候移位错了,都会导致解码出来的原始密钥字节和标准结果不一致,后面HMAC算出来的结果必然不对。 - 算法实现的MicroPython适配问题
不少自写的HMAC-SHA1、动态截断逻辑在PC上跑着正常,到MicroPython上就出问题:比如算时间步长的时候误用浮点数除法/而不是整数除法//,MicroPython的单精度浮点数精度不够,大数值下算出来的步长直接错;转4字节大端整数的时候字节序搞反;动态截断取偏移量的时候索引越界,都会导致最终OTP结果错。
快速排查方法
- 第一步先在设备上跑
print(utime.time()),把输出值和当前标准UTC Unix时间戳对比,确认误差不超过30秒,而且计数基准是UTC的Unix纪元,不是上电时间、不是本地时间。 - 用固定标准测试用例排除算法逻辑问题:用RFC6238的标准测试参数,Base32密钥填
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ(对应原始密钥是12345678901234567890),固定传入Unix时间戳59,正确生成的6位TOTP应该是94287082。如果这个固定值都算不对,逐环节查Base32解码、HMAC-SHA1计算、截断逻辑就能定位问题,不用折腾动态时间的问题。 - 检查代码里所有涉及时间步长计算的除法,全部换成整数除法
//,避免浮点数精度丢失。
内容的提问来源于stack exchange,提问作者Neha
相关产品推荐
相关产品推荐

