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 chen-hongqin@163.com
* 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加密了用户密码,这样又能多学一点东西啦~