工作,日常对接API,大多数接口都要求有签名字段,安全需要吧,绝大多数签名要用到MD5,今天就被一个demo坑了,其实是自己不够了解MD5,对方用的java,我用的PHP。
一半签名是拼拼参数,有直接拼的,有的还要加上&=这鬼符号,我平时用php,想偷懒用个http_build_query生成临时字符串A,这方法处理会将字符串A进行url加密,后面再用到拼好的字符串A进行md5时,得到的签名也就不能用了,所以还是循环着拼一拼吧,还要记得把后面的&去掉。。。
这还没到我今天的坑,我看了对方的签名描述,有点懵逼。这样的:
其他的都好说,这个转16进制什么鬼,我之前从没见过,问下度娘,发现java大神们都是这样写的,但是我不知道为什么要这样干,搜到的全是如何转换成16进制,这一点比较郁闷。等熟悉java的朋友指导一下吧,嘿嘿。
那就从MD5定义看吧,可以问度娘,太长了,我就记得个生成128位的信息摘要,java有封装好的信息摘要类,具体用法我就不说了,没用过,过程是这样的:
把生成的信息摘要存在bytes数组,byte类型长度8位,每个byte可以生成两个16进制字符(高位都是0的要在生成的字符前补0,还要注意整数是32位长度,每个byte跟0xff按位与),这样就有16个byte了,然后把这些byte转成16进制的,这样就得到32个16进制字符,这是大家常见的MD5,还有16位长度的MD5字符,是吧32位的前8位,后8位去掉了:
那就照着java的思路来吧,我把字符串md5之后,又拆成一个个字符,转成16进制,在拼成字符串,进行签名的最后一步,base64编码。调用了下对方的接口,喜闻乐见的签名错误,我还问对方怎么回事,他看了我的签名,说你这base64编码后的字符长度就不对(我后来才知道base64编码的长度有规律的,⌈n/3⌉*4,⌈⌉是向上取整,n是原字符长度,用java的基本功还是好啊)
后来知道了php的md5方法,就是把字符串转成32位16进制字符串了,真是尴尬。
$tmp = md5($str);
我之前是把32位字符再转成16进制(生成64位的字符),再base64,最后字符长度是88位。正确长度的是44(32位md5字符串base64一下)。
记录一下,看来自己每天用的,其实有很多都不理解,都只是会用而已。