新浪微博密码加密分析

1. 准备加密条件

用户在新浪微博登陆的时候,密码其实被经过了三次sha1加密,所使用的到信息包括了用户的密码,服务端的时间发送过来的servertime和一个叫做nonce的字段,后面两个是在登陆的时候从服务端get过来的,例,下边是我在测试的时候截取的消息:



图示1

这个阶段发生在你点击登陆的时候,这样客户端就可以利用这个字段进行密码的加密。

2. 使用js文件的加密算法进行加密

其实在js文件中的加密算法就是sha1算法,该js文件名称为sso.js,如下图示2所示

新浪微博密码加密分析_第1张图片


图示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加密了用户密码,这样又能多学一点东西啦~






你可能感兴趣的:(算法,加密,新浪微博,String,function,hex)