新浪微博密码加密分析

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算法进行加密


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


原文:http://blog.163.com/wm_at163/blog/static/132173490201110744659292/



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值