⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soapsso.java

📁 JAVA解析MSNP15协议
💻 JAVA
字号:
package jm.framework.msn.protocol.soap;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import jm.framework.msn.util.Base64Coder;
import jm.framework.msn.util.Log;

/**
 * 使用https进行Passport的验证过程,获得登陆必需的ticket和BinarySecret。 msnp15采用了SSO的方式进行认证。
 * SSO,Single Sign-On,一次验证便可获取对应不同服务的ticket。 messengerclear.live.com:用于msn的认证
 * messenger.msn.com:msn网页认证 contacts.msn.com:Contact server 的认证
 * spaces.msn.com:msn spaces 的认证
 * 
 * @author ishome
 * @version 0.5.0.2
 */
public class SoapSSO {
	//    static
	//    {
	//        java.security.Security.addProvider(
	//            new com.sun.net.ssl.internal.ssl.Provider());
	//        System.setProperty( "java.protocol.handler.pkgs", 
	//            "com.sun.net.ssl.internal.www.protocol" );
	//    }
	/**
	 * RPS/SSO Authentication
	 * 
	 * @param username
	 *                用户名
	 * @param password
	 *                密码
	 * @param policy
	 *                标识
	 * @param nonce
	 *                通知信息 在USR 6 SSO S
	 *                处获得服务器发送的Nonce,就是MBI_KEY_OLD后面的那一串;然后在USR 7 SSO S 处发
	 * @return String <ticket> <base64 encoded response structure>
	 */
	public static String getRPS(String username, String password, String policy, String nonce) {
		final String server = "login.live.com";
		final String page = "/RST.srf";
		try {
			// UTF-8 encode account and password
			// account = URLEncoder.encode(account,"UTF-8");
			// password = URLEncoder.encode(password,"UTF-8");

			// create connection
			SSLSocketFactory ssl = (SSLSocketFactory) SSLSocketFactory.getDefault();
			SSLSocket socket = (SSLSocket) ssl.createSocket(server, 443);

			// make input and output stream
			BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));

			// create buffers
			StringBuffer buf = new StringBuffer();
			String postXML = loadConfigMap(username, password, policy);

			buf.append("POST " + page + " HTTP/1.1" + "\r\n");
			buf.append("Accept: text/*" + "\r\n");
			buf.append("User-Agent: LoginHelper/1.0" + "\r\n");
			buf.append("Host: " + server + "\r\n");
			buf.append("Content-Length: " + postXML.length() + "\r\n");
			buf.append("Connection: Keep-Alive" + "\r\n");
			buf.append("Cache-Control: no-cache" + "\r\n");
			buf.append("\r\n");
			buf.append(postXML.toString());
			Log.info("    SSO >>>>> " + buf.toString());
			// send
			out.print(buf.toString());
			out.flush();

			// read
			buf = new StringBuffer();

			int Length = 0;

			while (true) {
				String str = in.readLine();
				if (str != null && str.substring(0, 15).equals("Content-Length:")) {
					String[] DataArray = str.split(" ");
					Length = Integer.parseInt(DataArray[1]) + 2;
					for (int i = 0; i < Length; i++) {
						int c = in.read();
						buf.append((char) c);
					}
					// get ticket and binarysecret
					Log.info("    SSO <<<<< " + buf.toString());
					if ("".equals(nonce)) {
						return buf.toString();
					} else {
						return decode(buf.toString(), nonce);
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	/**
	 * 获得钥匙
	 * @param data
	 * @param nonce
	 * @return
	 */
	public static String decode(String data, String nonce) {
		data = data.substring(data.indexOf("messengerclear.live.com"));
		String[] temp = data.split("BinarySecurityToken");
		String ticket = temp[1];
		ticket = ticket.substring(15, (ticket.length() - 7));
		ticket = ticket.replaceAll("&amp;", "&");

		temp = data.split("BinarySecret");
		String secret = temp[1];
		secret = secret.substring(1, (secret.length() - 6));

		// fill random iv
		byte[] iv = new byte[8];

		for (int i = 0; i < 8; i++) {
			byte rand = (byte) Math.floor(Math.random() * 256);
			iv[i] = rand;
		}

		// fill the begining of the struct
		byte start[] = new byte[28];

		// uStructHeaderSize = 28
		start[0] = 0x1c;
		start[1] = 0x00;
		start[2] = 0x00;
		start[3] = 0x00;

		// uCryptMode = 1
		start[4] = 0x01;
		start[5] = 0x00;
		start[6] = 0x00;
		start[7] = 0x00;

		// uCipherType = 0x6603
		start[8] = 0x03;
		start[9] = 0x66;
		start[10] = 0x00;
		start[11] = 0x00;

		// uHashType = 0x8004
		start[12] = 0x04;
		start[13] = (byte) 0x80;
		start[14] = 0x00;
		start[15] = 0x00;

		// uIVLen = 8
		start[16] = 0x08;
		start[17] = 0x00;
		start[18] = 0x00;
		start[19] = 0x00;

		// uHashLen = 20
		start[20] = 0x14;
		start[21] = 0x00;
		start[22] = 0x00;
		start[23] = 0x00;

		// uCipherLen = 72
		start[24] = 0x48;
		start[25] = 0x00;
		start[26] = 0x00;
		start[27] = 0x00;

		// generate key's
		byte key1[] = Base64Coder.decode(secret);
		byte key2[] = derive_key(key1, "WS-SecureConversationSESSION KEY HASH".getBytes());
		byte key3[] = derive_key(key1, "WS-SecureConversationSESSION KEY ENCRYPTION".getBytes());

		// create hash
		byte hash[] = HMAC(key2, nonce.getBytes());

		// add 8 bytes to the nonce
		byte nonceFillup[] = new byte[8];
		for (int i = 0; i < 8; i++) {
			nonceFillup[i] = 0x08;
		}

		// create des3 thingy
		byte des[] = DES3(key3, byteCombine(nonce.getBytes(), nonceFillup), iv);

		// fill struct
		byte struct[] = byteCombine(byteCombine(byteCombine(start, iv), hash), des);

		// return stuff
		return ticket + " " + new String(Base64Coder.encode(struct));
	}

	/**
	 * 读取安全检验POST文件内容
	 * 
	 * @param username
	 * @param password
	 * @param policy
	 * @return
	 */
	public static String loadConfigMap(String username, String password, String policy) {
		// 数据初始化//配置文件读取
		final String XML_NAME = "data/protocol/" + "RPS.xml";
		final String USER_NAME = "JMUserName";
		final String PASSWORD = "JMPassWord";
		final String POLICY = "JMPolicy";
		try {
			StringBuffer buf2 = new StringBuffer();
			String dataline;
			InputStream setdata = new FileInputStream(new File(XML_NAME));
			BufferedReader in = new BufferedReader(new InputStreamReader(setdata));
			while ((dataline = in.readLine()) != null) {
				buf2.append(dataline);
			}
			setdata.close();
			in.close();
			dataline = buf2.toString();
			dataline = dataline.replaceAll(USER_NAME, username);
			dataline = dataline.replaceAll(PASSWORD, password);
			dataline = dataline.replaceAll(POLICY, policy);
			return new String(dataline.getBytes("utf-8"));
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
		return "";
	}

	private static byte[] derive_key(byte[] key, byte[] magic) {

		byte hash1[] = HMAC(key, magic);
		byte hash2[] = HMAC(key, byteCombine(hash1, magic));
		byte hash3[] = HMAC(key, hash1);
		byte hash4[] = HMAC(key, byteCombine(hash3, magic));
		byte out[] = new byte[4];
		out[0] = hash4[0];
		out[1] = hash4[1];
		out[2] = hash4[2];
		out[3] = hash4[3];

		return byteCombine(hash2, out);
	}

	private static byte[] HMAC(byte[] key, byte[] subject) {
		try {
			Mac mac = Mac.getInstance("HmacSHA1");
			SecretKeySpec sk = new SecretKeySpec(key, "HmacSHA1");

			mac.init(sk);
			return mac.doFinal(subject);
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		} catch (InvalidKeyException ex) {
			ex.printStackTrace();
		}

		return null;
	}

	private static byte[] byteCombine(byte[] front, byte[] back) {
		byte output[] = new byte[front.length + back.length];
		for (int i = 0; i < front.length; i++) {
			output[i] = front[i];
		}
		for (int i = 0; i < back.length; i++) {
			output[i + front.length] = back[i];
		}
		return output;
	}

	private static byte[] DES3(byte[] key, byte[] subject, byte[] iv) {
		try {
			Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
			SecretKeySpec sk = new SecretKeySpec(key, "DESede");
			IvParameterSpec sr = new IvParameterSpec(iv);
			cipher.init(Cipher.ENCRYPT_MODE, sk, sr);
			return cipher.doFinal(subject);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -