某软件OTP算法分析

某软件OTP算法分析

OTP,即one time password,也就是我们常说的动态口令,目前在很多app都有应用。最近有人找我分析一款app的动态口令生成算法,记录一下。

入手点

打开app,可以看到6位的动态口令,每隔30秒自动刷新一次,每次间隔20秒才可以手动刷新。通过DDMS工具查看具体生成的时候用到了哪些函数。
某软件OTP算法分析
这样做有一个问题就是,我们不清楚哪些函数是关键点。大概的猜想com.b之类的包是关键点,没有详细的入手点。通过看日志,我们发现有趣的地方。
某软件OTP算法分析
打开JEB,直接在字符串部分搜索otpNumStr8,定位在了关键的地方:
某软件OTP算法分析
之后便是无聊的来回定位时间,纯属体力活。
但是这儿需要值得注意的地方是,该app用了几个加密以及编码算法,在源码中由于混淆的原因,可能直接辨认出来,这就需要长时间的实践有一个条件反射,知道哪些方法或者变量是哪个算法的特征。比如此处看到:
某软件OTP算法分析
需要能够反应过来这是SHA中的常量,再根据后面的方法确定是SHA-512。此外,该app还实现了AES,BASE64,URLEncode等的算法,都要对算法本身很了解才行。
说一下目标app生成OTP的思路,采用伪代码进行描述:
1.生成当前GMT时间GMTTime,格式为yyyyMMddkkmm
2.生成设备哈希值
deviceSHA-1 = sha-1(‘Mobilians MOTP HWINFO Create’ + IMEI)
deviceSHA-1 = deviceSHA-1.sub(1, 11) + deviceSHA-1.sub(13, 18)
3.生成AES的**
OTPID-SHA-1 = get_sha-1_key(BASE64Encode(URLEncode(OTPID)) + “&” + BASE64Encode(URLEncode(‘option1’)) + “&” + BASE64Encode(URLEncode(‘option2’)) + “&” + BASE64Encode(URLEncode(‘option3’)))
其中,get_sha-1_key算法思想如下:
首先ret = sha-1(param),对于结果ret,在前面拼接64字节的0字节后再进行一次SHA-1得到第二次的结果ret。
ret = sha-1(param + ret.sub(0,8))
对于结果ret,在前面拼接64字节的0字节后再进行一次SHA-1得到最后的的结果ret。
4.生成帐号相关数据
该步骤首先读取帐号相关文件,对其分割之后进行URL解码以及BASE64解码,得到cipher
5.采用OTPID-SHA-1对第四步拿到的帐号数据进行AES解密,对明文进行两次运算
plain = AES(cipher, plain, ‘AES-128-CBC’)
plain = BASE64Decode(URLDecode(plain))
plain = BASE64Decode(URLDecode(plain))
6.计算SHA512结果
data = ‘Mobilians AHENDPRPWKDBFMF MOTP2 OTPGeneration Computation’.toytes()
data += GMTTime
data += deviceSHA-1
data += plain
data += 0
result = SHA-512(data)
7.最后得到结果
某软件OTP算法分析