折腾:
【未解决】Python实现小花生中addSignature的md5加密生成签名的逻辑
期间,已经用:
【已解决】Python中计算字符串的md5值
用Python去计算出32字节的md5值了,但是却和小花生原先的getMD5Str算出来的32位字符不一样
去找找什么原因。是不是自己此处的Python的m5搞错了。
python md5
难道是str的encode时需要指定编码?比如utf-8?
把逻辑换:
if (j == 0) { paramString = new StringBuilder(); paramString.append(l); paramString.append((String)localObject); paramString.append(“AyGt7ohMR!xxx#N"); paramString = StringUtil.md5(paramString.toString()); }
试试
strToCalc = timestamp + localObject + fixedSault # md5Hexdigest=321ed614f7211147be90a45bbca94127
结果是:
321ed614f7211147be90a45bbca94127
也不对
突然看到:
好像是此处搞错了:
localObject
不是:
“/Reading.svc/parentChildReadingBookQuery2”
而是:
Object localObject = paramString;
的paramString的值=J的值
-》结果是:
defc3b231167e16932ea923d616e2d40
也不对
给encode加上utf-8试试
结果,和上面一样:defc3b231167e16932ea923d616e2d40
“hash.update(data)¶
Update the hash object with the bytes-like object. Repeated calls are equivalent to a single call with the concatenation of all the arguments: m.update(a); m.update(b) is equivalent to m.update(a+b).”
“一. 使用md5包
import md5
src = ‘this is a md5 test.’
m1 = md5.new()
m1.update(src)
print m1.hexdigest()
二. 使用hashlib
import hashlib
m2 = hashlib.md5()
m2.update(src)
print m2.hexdigest()
推荐使用第二种方法。”
换成最新的md5.update
“import hashlib
md5 = hashlib.md5()
md5.update(‘how to use md5 in python hashlib?’)
print md5.hexdigest()”
试试:
md5Result = md5() md5Result.update(strToCalc)
结果,python 3.6中报错:
发生异常: TypeError Unicode-objects must be encoded before hashing File "/Users/crifan/dev/dev_root/company/xxx/projects/crawl_data/小花生app/debug/pythonAddSignature/pythonAddSignature.py", line 79, in generateSignature md5Result.update(strToCalc) File "/Users/crifan/dev/dev_root/company/xxx/projects/crawl_data/小花生app/debug/pythonAddSignature/pythonAddSignature.py", line 95, in <module> generatedSignature = generateSignature(timestampInt, paramString) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 85, in _run_code exec(code, run_globals) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 96, in _run_module_code mod_name, mod_spec, pkg_name, script_name) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 263, in run_path pkg_name=pkg_name, script_name=fname)
所以:
先去换用python2试试
结果没报错,但是和前面结果一样:
md5Hexdigest=defc3b231167e16932ea923d616e2d40
把J值的反斜杠去掉:
# paramString = "{\"userId\":\"1134723\",\"fieldName\":\"\",\"fieldValue\":\"全部类别\",\"theStageOfTheChild\":\"\",\"parentalEnglishLevel\":\"\",\"supportingResources\":\"有音频\",\"offset\":20,\"limit\":10}" paramString = """{"userId":"1134723","fieldName":"","fieldValue":"全部类别","theStageOfTheChild":"","parentalEnglishLevel":"","supportingResources":"有音频","offset":20,"limit":10}"""
结果依旧是:
md5Hexdigest=defc3b231167e16932ea923d616e2d40
实在不行,或许可以考虑:
去让原先java代码运行起来,看看输出的md值到底是多少
然后也看到:
public static final String getMD5Str(String paramString)
中,好像是在计算了md5:
paramString = paramString.getBytes(); Object localObject = MessageDigest.getInstance("MD5"); ((MessageDigest)localObject).update(paramString); paramString = ((MessageDigest)localObject).digest();
后,又去处理了一下
int i = paramString.length; localObject = new char[i * 2]; int j = 0; int k = 0; while (j < i) { int m = paramString[j]; int n = k + 1; localObject[k] = ((char)arrayOfChar[(m >> 4 & 0xF)]); k = n + 1; localObject[n] = ((char)arrayOfChar[(m & 0xF)]); j++; } paramString = new String((char[])localObject); return paramString; }
而具体的逻辑,不是很懂。
不过,好像是:
此处的arrayOfChar是16个字节的?
而
最后返回的是:32个字节
-》md5计算出来的,好像也只有16字节?
-》再去扩大到32个字节,其中用到了:
md值和arrayOfChar
去处理,得到的32字节
-》去搞清楚:
【已解决】java中md5值的长度是16位(字节)还是32位(字节)及两者之间关系
在此期间:
md5在线解密破解,md5解密加密
试试之前的测试效果
输入:
11347231553845899{"userId":"1134723","fieldName":"","fieldValue":"全部类别","theStageOfTheChild":"","parentalEnglishLevel":"","supportingResources":"有音频","offset":20,"limit":10}{"userId":"1134723","fieldName":"","fieldValue":"全部类别","theStageOfTheChild":"","parentalEnglishLevel":"","supportingResources":"有音频","offset":20,"limit":10}AyGt7ohMR!xx#N
结果:
还真是我们Python中计算出来的
md5: defc3b231167e16932ea923d616e2d40
-》说明python的md5算法是正确的
-》不过还有其他很多了类型的值
找找是否有希望的:c687d5dfa015246e6bdc6b3c27c2afea
结果没有
突然想到,可以利用:
md5在线解密破解,md5解密加密
去解密上面抓包得到的:
c687d5dfa015246e6bdc6b3c27c2afea
看看原始字符串是啥
结果解密失败
查询结果:
未查到
已加入本站后台解密,请等待最多5天,如果解密成功将自动给你发送邮件通知,否则表示解密失败。请注意本站实时查询已经非常强大,实时查询未查到则后台解密成功的希望并不大
那用我上面的md5值,看看是否能解密
结果同样现象:
【已解决】java中md5值的长度是16位(字节)还是32位(字节)及两者之间关系
的结论是:
目前看来,算法都是一样的,应该不是算法问题。
所以感觉倒是:
不是此处Python的md5算法和java不一样,而是:
原始的字符串不一样
或者是此处java的getMD5Str的加密逻辑不太一样?
继续研究代码
貌似自己搞错逻辑了?
此处的paramString实际上已经是被赋值为
paramString = getToken(MainActivity.userId);
继续研究
【总结】
此处,Python中md5值和Java中md5值计算逻辑是一样的。
之所以此处md5值不同,是因为Python代码中缺少了java代码中的一部分的逻辑,少了传入userId调用getToken得到的值,导致后续计算出来的md5不对。
分析:
为何会漏看了这个 paramString 的逻辑呢?
-》因为之前代码被折叠起来了:
以及:
此处反编译出来的代码(如果原始代码没有被混淆的情况下)
这里的代码,写的很烂,变量的定义和使用不够清晰
传入的参数paramString和临时变量localObject
没有做到见名知意,且先后多次混用
导致代码逻辑不够清晰,所以容易误判
-》而对于:为何会去折叠代码呢?
-》因为是,在截图说明问题时,为了单个页面能截到下面的md5字符串参数生成的逻辑,所以把前面不重要的代码折叠起来了
-》以后如何避免类似问题?
-》对于此处,调用StringUtil.md5之前的,看似逻辑不太复杂的代码,尤其代码本身写的不够好的,逻辑稍微有点混乱的时候,也要,更要:
更加仔细和认真的分析代码逻辑
-》最好是每一步都模拟分析一遍,确认逻辑足够清晰了
-》就不会粗心,漏掉此处的paramString参数了
所以接下来的问题转换为:
找到此处的getToken的逻辑:
【已解决】小花生中如何得到getToken的计算逻辑以便得到正确的md5值可以正常请求接口