1. 准备加密条件
用户在新浪微博登陆的时候,密码其实被经过了三次sha1加密,所使用的到信息包括了用户的密码,服务端的时间发送过来的servertime和一个叫做nonce的字段,后面两个是在登陆的时候从服务端get过来的,例,下边是我在测试的时候截取的消息:
图示1
这个阶段发生在你点击登陆的时候,这样客户端就可以利用这个字段进行密码的加密。
2. 使用js文件的加密算法进行加密
其实在js文件中的加密算法就是sha1算法,该js文件名称为sso.js,如下图示2所示
图示2
通过搜索sha1,你可以找到,加密密码的字段,如图示3所示,从图中,我们可以看到它利用了password,servertime,和一个叫做nonce的字段进行加密,使用了三次sha1加密
图示3
3. 分析加密的源码
1)先分析一下js源码
由于文件函数比较多,我直接摘取了关键的源码,如下所示
var i = 0; var g = 8; this.hex_sha1 = function(j) { var retB = b(f(j), j.length * g); var retH = h(retB); return retH; }; var b = function(A, r) { A[r >> 5] |= 128 << (24 - r % 32); A[((r + 64 >> 9) << 4) + 15] = r; var B = Array(80); var z = 1732584193; var y = -271733879; var v = -1732584194; var u = 271733878; var s = -1009589776; for (var o = 0; o < A.length; o += 16) { var q = z; var p = y; var n = v; var m = u; var k = s; for (var l = 0; l < 80; l++) { if (l < 16) { B[l] = A[o + l] } else { B[l] = d(B[l - 3] ^ B[l - 8] ^ B[l - 14] ^ B[l - 16], 1) } var C = e(e(d(z, 5), a(l, y, v, u)), e(e(s, B[l]), c(l))); s = u; u = v; v = d(y, 30); y = z; z = C } z = e(z, q); y = e(y, p); v = e(v, n); u = e(u, m); s = e(s, k) } return Array(z, y, v, u, s) }; var a = function(k, j, m, l) { if (k < 20) { return (j & m) | ((~j) & l) } if (k < 40) { return j ^ m ^ l } if (k < 60) { return (j & m) | (j & l) | (m & l) } return j ^ m ^ l }; var c = function(j) { return (j < 20) ? 1518500249 : (j < 40) ? 1859775393 : (j < 60) ? -1894007588 : -899497514 }; var e = function(j, m) { var l = (j & 65535) + (m & 65535); var k = (j >> 16) + (m >> 16) + (l >> 16); return (k << 16) | (l & 65535) }; var d = function(j, k) { return (j << k) | (j >>> (32 - k)) }; var f = function(m) { var l = Array(); var j = (1 << g) - 1; for (var k = 0; k < m.length * g; k += g) { l[k >> 5] |= (m.charCodeAt(k / g) & j) << (24 - k % 32) } return l }; var h = function(l) { var k = i ? "0123456789ABCDEF": "0123456789abcdef"; var m = ""; for (var j = 0; j < l.length * 4; j++) { m += k.charAt((l[j >> 2] >> ((3 - j % 4) * 8 + 4)) & 15) + k.charAt((l[j >> 2] >> ((3 - j % 4) * 8)) & 15) } return m } //sinaSSOController.preloginCallBack({"retcode":0,"servertime":1312582940,"nonce":"BUW9I5"}) var password = "password"; //servertime 是服务器传过来的值 var servertime = "1312582940"; //nonce 这个也是从服务器那边传过来的值 var nonce = "BUW9I5"; //var result = hex_sha1("" + hex_sha1(hex_sha1(password)) + servertime + nonce); var first = hex_sha1(password); var second = hex_sha1(first); var third = hex_sha1(second + servertime + nonce); alert(third) //结果输出:960ec4d4b7ffe64e382c1af4fa915758a2f0d372其实,这整一个就是sha1的算法实现,在最后有一个测试的例子,下面,我使用java来编写这个算法实现,效果是一样的
2)使用java实现新浪微博密码加密算法
整个java就三个函数,实现也并不是很麻烦,其中,generateDigest函数主要是为了实现将内容用sha1算法进行加密
/** * * @author [email protected] * http://weibo.com/stuckin * 2011-8-6 */ public class Encoder { public static void main(String[] args) { Long servertime = new Long(1312582940); String nonce = "BUW9I5"; String password = "password"; Encoder encoder = new Encoder(); String firstDigest = encoder.generateDigest(password, "sha1"); //System.out.println(firstDigest); String secondDigest = encoder.generateDigest(firstDigest, "sha1"); //System.out.println(secondDigest); String encodedPassword = encoder.generateDigest(secondDigest + servertime + nonce, "sha1"); System.out.println(encodedPassword); } private final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public String generateDigest(String content, String algorithm) { MessageDigest digest = null; try { digest = java.security.MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { e.printStackTrace(System.out); } digest.update(content.getBytes()); byte[] hash = digest.digest(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < hash.length; i++) { sb.append(getByteAsHexString(hash[i])); } return sb.toString(); } private String getByteAsHexString(byte b) { char[] buf = new char[2]; int radix = 1 << 4; int mask = radix - 1; buf[1] = digits[(int) (b & mask)]; b >>>= 4; buf[0] = digits[(int) (b & mask)]; return new String(buf); } }运行结果和用js实现的效果一模一样。
4. 结论
呃,在做东西的时候,有时候也要停下来想想这个东西到底是怎么实现的,为什么会这样,我开始的时候就因为在firebug看到密码是一串字母和数字,就想看个究竟,后来就发现它使用了三次sha1加密了用户密码,这样又能多学一点东西啦~