diff options
| -rw-r--r-- | src/se/leap/leapclient/ProviderAPI.java | 270 | 
1 files changed, 35 insertions, 235 deletions
diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index eb3afcf..aa1ce30 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -2,20 +2,11 @@ package se.leap.leapclient;  import java.io.IOException;  import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; +import java.util.ArrayList;  import java.util.List; -import java.util.Random;  import java.util.Scanner; -import org.bouncycastle.crypto.CryptoException; -import org.bouncycastle.crypto.agreement.srp.SRP6Client; -import org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator; -import org.bouncycastle.crypto.digests.SHA256Digest; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.jcajce.provider.digest.Whirlpool.Digest;  import org.apache.http.HttpEntity;  import org.apache.http.HttpResponse;  import org.apache.http.client.ClientProtocolException; @@ -24,6 +15,9 @@ import org.apache.http.client.methods.HttpPost;  import org.apache.http.client.methods.HttpPut;  import org.apache.http.cookie.Cookie;  import org.apache.http.impl.client.DefaultHttpClient; +import org.jboss.security.srp.SRPClientSession; +import org.jboss.security.srp.SRPParameters; +import org.jboss.security.srp.SRPServerInterface;  import org.json.JSONException;  import org.json.JSONObject; @@ -31,7 +25,6 @@ import se.leap.leapclient.ProviderListContent.ProviderItem;  import android.app.IntentService;  import android.content.Intent; -import android.content.SharedPreferences;  import android.os.Bundle;  import android.os.ResultReceiver;  import android.util.Log; @@ -120,44 +113,6 @@ public class ProviderAPI extends IntentService {  		BigInteger salt = ng_1024.probablePrime(1024, null);  		byte[] salt_in_bytes = salt.toByteArray(); -		SRP6VerifierGenerator verifier_generator = new SRP6VerifierGenerator(); -		verifier_generator.init(ng_1024, ConfigHelper.g, new SHA256Digest()); -		BigInteger verifier = verifier_generator.generateVerifier(salt_in_bytes, username.getBytes(), password.getBytes()); -		 -		return sendRegisterMessage(authentication_server, salt.toString(16), verifier.toString(16), username); -	} -	 -	private boolean sendRegisterMessage(String server_url, String password_salt, String password_verifier, String login) { -		DefaultHttpClient client = new LeapHttpClient(getApplicationContext()); -		String parameter_chain = "user[password_salt]" + "=" + password_salt + "&" + "user[password_verifier]" + "=" + password_verifier + "&" + "user[login]" + "=" + login; -		HttpPost post = new HttpPost(server_url + "/users.json" + "?" + parameter_chain); - -		HttpResponse getResponse; -		try { -			getResponse = client.execute(post); -			HttpEntity responseEntity = getResponse.getEntity(); -			String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); -			JSONObject json_response = new JSONObject(plain_response); -			if(!json_response.isNull("errors") || json_response.has("errors")) { -				return false; -			} -			//else if(json_response.getString("password_salt").equalsIgnoreCase(password_salt) && json_response.getString("login").equalsIgnoreCase(login)) -			else if(json_response.getBoolean("ok") && json_response.getString("login").equalsIgnoreCase(login)) -				return true; -		} catch (ClientProtocolException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -			return false; -		} catch (IOException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -			return false; -		} catch (JSONException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -			return false; -		} -		  		return false;  	} @@ -165,12 +120,17 @@ public class ProviderAPI extends IntentService {  		String username = (String) task.get(ConfigHelper.username_key);  		String password = (String) task.get(ConfigHelper.password_key);  		String authentication_server = (String) task.get(ConfigHelper.srp_server_url_key); -		 -		SRPParameters params = new SRPParameters(ConfigHelper.NG_1024.getBytes(), "2".getBytes(), null); + +		SRPParameters params = new SRPParameters(ConfigHelper.NG_1024.getBytes(), "2".getBytes(), "salt".getBytes(), "SHA-256");  		SRPClientSession client = new SRPClientSession(username, password.toCharArray(), params);  		byte[] A = client.exponential();  		try { -			byte[] B = sendAToSRPServer(authentication_server, username, A); +			JSONObject saltAndB = sendAToSRPServer(authentication_server, username, getHexString(A)); +			byte[] B = saltAndB.getString("B").getBytes(); +			String salt = saltAndB.getString("salt"); +			params = new SRPParameters(ConfigHelper.NG_1024.getBytes(), "2".getBytes(), salt.getBytes(), "SHA-256"); +			client = new SRPClientSession(username, password.toCharArray(), params); +			client.exponential();  			byte[] M1 = client.response(B);  			byte[] M2 = sendM1ToSRPServer(authentication_server, username, M1);  			if( client.verify(M2) == false ) @@ -179,78 +139,39 @@ public class ProviderAPI extends IntentService {  		} catch (ClientProtocolException e1) {  			// TODO Auto-generated catch block  			e1.printStackTrace(); +			return false;  		} catch (IOException e1) {  			// TODO Auto-generated catch block  			e1.printStackTrace(); +			return false;  		} catch (JSONException e1) {  			// TODO Auto-generated catch block  			e1.printStackTrace(); -		} catch (NoSuchAlgorithmException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -		} -		 -		SRP6Client srp_client = new SRP6Client(); -		BigInteger n = new BigInteger(ConfigHelper.NG_1024, 16); -		srp_client.init(n, ConfigHelper.g, new SHA256Digest(), new SecureRandom()); - -		BigInteger salt = BigInteger.probablePrime(1024, null); - -		BigInteger clientA = srp_client.generateClientCredentials(salt.toString(16).getBytes(), username.getBytes(), password.getBytes()); - -		try { -			BigInteger serverB = sendAToSRPServer(authentication_server, username, clientA); - -			if(serverB == BigInteger.ZERO) -				return false; // TODO Show error: error trying to start authentication with provider -			 -			BigInteger s = srp_client.calculateSecret(serverB); -			 -			BigInteger k = new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(s.toByteArray())); -			 -			BigInteger m1 = generateM1(k, salt, clientA, serverB, username); -			 -			BigInteger m2 = sendM1ToSRPServer(authentication_server, username, m1); -			 -			if(m2 == BigInteger.ZERO) -				return false; // TODO Show error: error in M1 -			 -			boolean verified = verifyM2(m2, k, clientA, serverB, username); -			 -			return verified; // TODO If false, Username or password are not correct -> Show a warning and get back to login fragment -		} catch (ClientProtocolException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -			return false; -		} catch (IOException e) { -			// TODO Auto-generated catch block -			// From sendAToSRPServer or from sendM1ToSRPServer -			e.printStackTrace(); -			return false; -		} catch (CryptoException e) { -			// TODO Auto-generated catch block -			// From calculateSecret -			e.printStackTrace();  			return false;  		} catch (NoSuchAlgorithmException e) {  			// TODO Auto-generated catch block -			// From MessageDigest.getInstance -			e.printStackTrace(); -			return false; -		} catch (NumberFormatException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -			return false; -		} catch (JSONException e) { -			// TODO Auto-generated catch block  			e.printStackTrace();  			return false;  		}  	} +	 +	public static String getHexString(byte[] b) { +		  String result = ""; +		  StringBuffer sb = new StringBuffer(); +			for (byte tmp : b) { +				sb.append(Integer.toHexString((int) (tmp & 0xff))); +			} +			return sb.toString(); +//		  for (int i=0; i < b.length; i++) { +//		    result += +//		          Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 ); +//		  } +//		  return result; +		} -	private BigInteger sendAToSRPServer(String server_url, String username, BigInteger clientA) throws ClientProtocolException, IOException, NumberFormatException, JSONException { +	private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException {  		DefaultHttpClient client = new LeapHttpClient(getApplicationContext()); -		String parameter_chain = "A" + "=" + clientA.toString(16) + "&" + "login" + "=" + username; +		String parameter_chain = "A" + "=" + clientA + "&" + "login" + "=" + username;  		HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + parameter_chain);  		HttpResponse getResponse = client.execute(post); @@ -258,18 +179,18 @@ public class ProviderAPI extends IntentService {  		String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next();  		JSONObject json_response = new JSONObject(plain_response);  		if(!json_response.isNull("errors") || json_response.has("errors")) { -			return BigInteger.ZERO; +			return new JSONObject();  		}  		List<Cookie> cookies = client.getCookieStore().getCookies();  		if(!cookies.isEmpty()) {  			String session_id = cookies.get(0).getValue();  		} -		return new BigInteger(json_response.getString("B"), 16); +		return json_response;  	} -	 +  	private byte[] sendAToSRPServer(String server_url, String username, byte[] clientA) throws ClientProtocolException, IOException, JSONException {  		DefaultHttpClient client = new LeapHttpClient(getApplicationContext()); -		String parameter_chain = "A" + "=" + new String(clientA) + "&" + "login" + "=" + username; +		String parameter_chain = "A" + "=" + getHexString(clientA) + "&" + "login" + "=" + username;  		HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + parameter_chain);  		HttpResponse getResponse = client.execute(post); @@ -286,130 +207,9 @@ public class ProviderAPI extends IntentService {  		return json_response.getString("B").getBytes();  	} -	public BigInteger generateM1(BigInteger K, BigInteger salt, BigInteger clientA, BigInteger serverB, String username) throws NoSuchAlgorithmException { -		String digest_of_N_as_string = new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(hex2ascii(ConfigHelper.NG_1024).getBytes())).toString(16); - -		String digest_of_G_as_string = new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(ConfigHelper.g.toString(16).getBytes())).toString(16); - -		String xor_n_and_g = hexXor(digest_of_N_as_string, digest_of_G_as_string); - -		String digest_of_username_as_string = new BigInteger(MessageDigest.getInstance("SHA-256").digest(username.getBytes())).toString(16); -		 -		String m1_source_string = xor_n_and_g + digest_of_username_as_string + salt.toString(16) + clientA.toString(16) + serverB.toString(16) + K.toString(16); -		 -		return new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(m1_source_string.getBytes())); -	} - -	private boolean verifyM2(BigInteger M2, BigInteger K, BigInteger clientA, BigInteger serverB, String username) throws NoSuchAlgorithmException { -		/* https://github.com/leapcode/srp_js/blob/master/src/srp_session.js -		var hashN = SHA256(hex2a(N.toString(16))) -			    var hashG = SHA256(hex2a(g.toString(16))) -			    var hexString = hexXor(hashN, hashG); -			    hexString += SHA256(I); -			    hexString += salt; -			    hexString += Astr; -			    hexString += Bstr; -			    hexString += K -			    M = SHA256(hex2a(hexString)); -			    //M2 = H(A, M, K) -			    M2 = SHA256(hex2a(Astr + M + K)); -		*/ -		MessageDigest digest_of_N = MessageDigest.getInstance("SHA-256"); -		digest_of_N.update(ConfigHelper.NG_1024.getBytes()); -		String digest_of_N_as_string = new BigInteger(digest_of_N.digest()).toString(); -		 -		MessageDigest digest_of_G = MessageDigest.getInstance("SHA-256"); -		digest_of_G.update(ConfigHelper.g.toByteArray()); -		String digest_of_G_as_string = new BigInteger(digest_of_G.digest()).toString(); -		 -		String xor_n_and_g = hexXor(digest_of_N_as_string, digest_of_G_as_string); -		 -		MessageDigest digest_of_username = MessageDigest.getInstance("SHA-256"); -		digest_of_username.update(username.getBytes()); -		String digest_of_username_as_string = new BigInteger(digest_of_username.digest()).toString(); -		 -		MessageDigest my_M1 = MessageDigest.getInstance("SHA-256"); -		String m1_source_string = xor_n_and_g + digest_of_username_as_string + clientA.toString() + serverB.toString() + K.toString(); -		my_M1.update(m1_source_string.getBytes()); -		 -		MessageDigest my_own_M2 = MessageDigest.getInstance("SHA-256"); -		String m2_source_string = clientA.toString() + new BigInteger(my_M1.digest()).toString() + K.toString(); -		 -		my_own_M2.update(m2_source_string.getBytes()); -		 -		return M2 == new BigInteger(my_own_M2.digest()); -	} - -	private String hexXor(String a, String b) { -	    String str = ""; -	    for (int i = 0; i < a.length(); i += 2) { -	    	int xor = 0; -	    	if(a.length() > i + 2) -	    		xor = Integer.parseInt(a.substring(i, 2 + i), 16) ^ Integer.parseInt(b.substring(i, 2 + i), 16); -	    	else -	    		xor = Integer.parseInt(a.substring(i, 1 + i), 16) ^ Integer.parseInt(b.substring(i, 1 + i), 16); -	      String xor_string = String.valueOf(Integer.valueOf(String.valueOf(xor), 16)); -	      str += (xor_string.length() == 1) ? ("0" + xor) : xor_string; -	    } -	    return stringToHex(str); -	  } -	 -	private String stringToHex(String base) -    { -     StringBuffer buffer = new StringBuffer(); -     int intValue; -     for(int x = 0; x < base.length(); x++) -         { -         int cursor = 0; -         intValue = base.charAt(x); -         String binaryChar = new String(Integer.toBinaryString(base.charAt(x))); -         for(int i = 0; i < binaryChar.length(); i++) -             { -             if(binaryChar.charAt(i) == '1') -                 { -                 cursor += 1; -             } -         } -         if((cursor % 2) > 0) -             { -             intValue += 128; -         } -         buffer.append(Integer.toHexString(intValue) + ""); -     } -     return buffer.toString(); -} -	 -	private String hex2ascii(String hex) { -		StringBuilder output = new StringBuilder(); -	    for (int i = 0; i < hex.length(); i+=2) { -	        String str = hex.substring(i, i+2); -	        output.append((char)Integer.parseInt(str, 16)); -	    } -	    String debug = output.toString(); -	    return output.toString(); -	} - -	private BigInteger sendM1ToSRPServer(String server_url, String username, BigInteger m1) throws ClientProtocolException, IOException, JSONException { -		DefaultHttpClient client = new LeapHttpClient(getApplicationContext()); -		String parameter_chain = "client_auth" + "=" + m1.toString(16); -		HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + parameter_chain); -		 -		HttpResponse getResponse = client.execute(put); -		HttpEntity responseEntity = getResponse.getEntity(); -		String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); -		JSONObject json_response = new JSONObject(plain_response); -		if(!json_response.isNull("errors") || json_response.has("errors")) { -			return BigInteger.ZERO; -		} -		 -		List<Cookie> cookies = client.getCookieStore().getCookies(); -		String session_id = cookies.get(0).getValue(); -		return new BigInteger(json_response.getString("M2"), 16); -	} -  	private byte[] sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException {  		DefaultHttpClient client = new LeapHttpClient(getApplicationContext()); -		String parameter_chain = "client_auth" + "=" + new String(m1); +		String parameter_chain = "client_auth" + "=" + getHexString(m1);  		HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + parameter_chain);  		HttpResponse getResponse = client.execute(put);  | 
