diff options
| -rw-r--r-- | src/se/leap/leapclient/ConfigHelper.java | 24 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ConfigurationWizard.java | 4 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ProviderAPI.java | 261 | 
3 files changed, 205 insertions, 84 deletions
| diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index c981051..41364e9 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -7,7 +7,6 @@ import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.FileWriter;  import java.io.IOException; -import java.io.InputStream;  import java.math.BigInteger;  import org.json.JSONException; @@ -18,10 +17,14 @@ import android.os.Environment;  import android.util.Log;  public class ConfigHelper { +     +    public static SharedPreferences shared_preferences;  	final static String downloadJsonFilesBundleExtra = "downloadJSONFiles";  	final static String downloadNewProviderDotJSON = "downloadNewProviderDotJSON"; -	final static String srpAuth = "srpAuth"; +	public static final String srpRegister = "srpRegister"; +	final public static String srpAuth = "srpAuth"; +	final public static String resultKey = "result";  	final static String provider_key = "provider";  	final static String cert_key = "cert";  	final static String eip_service_key = "eip"; @@ -38,12 +41,16 @@ public class ConfigHelper {  	final public static BigInteger g = BigInteger.valueOf(2);  	final public static int CUSTOM_PROVIDER_ADDED = 0; -	final public static int CORRECTLY_DOWNLOADED_JSON_FILES = 0; -	final public static int INCORRECTLY_DOWNLOADED_JSON_FILES = 0;  +	final public static int CORRECTLY_DOWNLOADED_JSON_FILES = 1; +	final public static int INCORRECTLY_DOWNLOADED_JSON_FILES = 2; +	final public static int SRP_AUTHENTICATION_SUCCESSFUL = 3; +	final public static int SRP_AUTHENTICATION_FAILED = 4; +	public static final int SRP_REGISTRATION_SUCCESSFUL = 5; +	public static final int SRP_REGISTRATION_FAILED = 6;  	static void saveSharedPref(String shared_preferences_key, JSONObject content) { -		SharedPreferences.Editor shared_preferences_editor = ConfigurationWizard.shared_preferences +		SharedPreferences.Editor shared_preferences_editor = shared_preferences  				.edit();  		shared_preferences_editor.putString(shared_preferences_key,  				content.toString()); @@ -51,7 +58,7 @@ public class ConfigHelper {  		System.out.println("Shared preferences updated: key = "  				+ shared_preferences_key  				+ " Content = " -				+ ConfigurationWizard.shared_preferences.getString( +				+ shared_preferences.getString(  						shared_preferences_key, "Default"));  	} @@ -92,4 +99,9 @@ public class ConfigHelper {  		}  		return input_stream;  	} + +	public static void setSharedPreferences( +			SharedPreferences shared_preferences) { +		ConfigHelper.shared_preferences = shared_preferences; +	}  } diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index e41eb5c..33ff31f 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -48,8 +48,6 @@ public class ConfigurationWizard extends Activity       * device.
       */
      private boolean mTwoPane;
 -    
 -    static SharedPreferences shared_preferences;
      public ProviderAPIResultReceiver providerAPI_result_receiver;
 @@ -59,8 +57,6 @@ public class ConfigurationWizard extends Activity          setContentView(R.layout.activity_configuration_wizard);
 -        shared_preferences = getSharedPreferences(ConfigHelper.PREFERENCES_KEY,MODE_PRIVATE);
 -        
          loadPreseededProviders();
          // Only create our fragments if we're not restoring a saved instance
 diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 19404c2..41612d1 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -12,6 +12,7 @@ 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; @@ -29,6 +30,7 @@ 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; @@ -38,7 +40,6 @@ public class ProviderAPI extends IntentService {  	public ProviderAPI() {  		super("ProviderAPI");  		Log.v("ClassName", "Provider API"); -		// TODO Auto-generated constructor stub  	}  	@Override @@ -72,51 +73,20 @@ public class ProviderAPI extends IntentService {  				e.printStackTrace();  			}  		} +		else if ((task = task_for.getBundleExtra(ConfigHelper.srpRegister)) != null) { +			if(!registerWithSRP(task)) +				receiver.send(ConfigHelper.SRP_REGISTRATION_FAILED, Bundle.EMPTY); +			else +				receiver.send(ConfigHelper.SRP_REGISTRATION_SUCCESSFUL, Bundle.EMPTY); +		}  		else if ((task = task_for.getBundleExtra(ConfigHelper.srpAuth)) != null) { -			String username = "username";//(String) task.get(ConfigHelper.username_key); -			String password = "password";//(String) task.get(ConfigHelper.password_key); -			String authentication_server = "localhost:3000";//(String) task.get(ConfigHelper.srp_server_url_key); -			SRP6Client srp_client = new SRP6Client(); -			srp_client.init(new BigInteger(ConfigHelper.NG_1024, 16), ConfigHelper.g, new SHA256Digest(), new SecureRandom()); -			// Receive salt from server -			Random random_number_generator = new Random(); -			int salt = random_number_generator.nextInt(Integer.valueOf(ConfigHelper.NG_1024)); -			byte[] salt_in_bytes = ByteBuffer.allocate(4).putInt(salt).array(); -			BigInteger clientA = srp_client.generateClientCredentials(salt_in_bytes, username.getBytes(), password.getBytes()); -			//Send A to the server. Doing a http response with cookies? -			//Receive server generated serverB -			try { -				BigInteger serverB = sendParameterToSRPServer(authentication_server, "A", clientA); -				BigInteger s = srp_client.calculateSecret(serverB); -				MessageDigest digest_of_S = MessageDigest.getInstance("SHA-256"); -				digest_of_S.update(s.toByteArray(), 0, s.toByteArray().length); -				BigInteger k = new BigInteger(digest_of_S.digest()); -				BigInteger m1 = generateM1(k, clientA, serverB, salt, username); -				BigInteger m2 = sendParameterToSRPServer(authentication_server, "M1", m1); -				sendM1(m2, k, clientA, serverB, salt, username); -				boolean verified = verifyM2(m2, k, clientA, serverB, salt, username); -				if(!verified) { -					 -				} -			} catch (ClientProtocolException e) { -				// TODO Auto-generated catch block -				e.printStackTrace(); -			} catch (IOException e) { -				// TODO Auto-generated catch block -				// From sendAToSRPServer or from sendM1ToSRPServer -				e.printStackTrace(); -			} catch (CryptoException e) { -				// TODO Auto-generated catch block -				// From calculateSecret -				e.printStackTrace(); -			} catch (NoSuchAlgorithmException e) { -				// TODO Auto-generated catch block -				// From MessageDigest.getInstance -				e.printStackTrace(); -			} +			if(!authenticateBySRP(task)) +				receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); +			else +				receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, Bundle.EMPTY);  		}  	} -	 +  	private boolean downloadJsonFiles(Bundle task) {  		String cert_url = (String) task.get(ConfigHelper.cert_key);  		String eip_service_json_url = (String) task.get(ConfigHelper.eip_service_key); @@ -140,13 +110,115 @@ public class ProviderAPI extends IntentService {  		}  	} -	private void sendM1(BigInteger m2, BigInteger k, BigInteger clientA, -			BigInteger serverB, int salt, String username) throws NoSuchAlgorithmException { -		BigInteger M1 = generateM1(k, clientA, serverB, salt, username); +	private boolean registerWithSRP(Bundle task) { +		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); +		 +		BigInteger ng_1024 = new BigInteger(ConfigHelper.NG_1024, 16); +		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(), 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); -	private BigInteger generateM1(BigInteger K, BigInteger clientA, BigInteger serverB, int salt, String username) throws NoSuchAlgorithmException { +		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.getString("errors").isEmpty()) { +				return false; +			} +			else if(json_response.getString("password_salt").equalsIgnoreCase(password_salt) && 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; +	} +	 +	private boolean authenticateBySRP(Bundle task) { +		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); +		SRP6Client srp_client = new SRP6Client(); +		srp_client.init(new BigInteger(ConfigHelper.NG_1024, 16), ConfigHelper.g, new SHA256Digest(), new SecureRandom()); +		// Receive salt from server +		Random random_number_generator = new Random(); +		BigInteger ng_1024 = new BigInteger(ConfigHelper.NG_1024, 16); +		byte[] salt_in_bytes = ng_1024.probablePrime(1024, null).toByteArray(); +		//int salt = random_number_generator.nextInt(Integer.parseInt(ConfigHelper.NG_1024, 16)); +		//byte[] salt_in_bytes = ByteBuffer.allocate(4).putInt(salt).array(); +		BigInteger clientA = srp_client.generateClientCredentials(salt_in_bytes, username.getBytes(), password.getBytes()); +		//Send A to the server. Doing a http response with cookies? +		//Receive server generated serverB +		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); +			MessageDigest digest_of_S = MessageDigest.getInstance("SHA-256"); +			digest_of_S.update(s.toByteArray(), 0, s.toByteArray().length); +			BigInteger k = new BigInteger(digest_of_S.digest()); +			BigInteger m1 = generateM1(k, clientA, serverB, username); +			BigInteger m2 = sendM1ToSRPServer(authentication_server, "M1", 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; +		} +	} + +	private BigInteger generateM1(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))) @@ -160,29 +232,21 @@ public class ProviderAPI extends IntentService {  			    //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 String(digest_of_N.digest()); +		String digest_of_N_as_string = new BigInteger(MessageDigest.getInstance("SHA-256").digest(ConfigHelper.NG_1024.getBytes())).toString(16); -		MessageDigest digest_of_G = MessageDigest.getInstance("SHA-256"); -		digest_of_G.update(ConfigHelper.g.toByteArray()); -		String digest_of_G_as_string = new String(digest_of_G.digest()); +		String digest_of_G_as_string = new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(ConfigHelper.g.toString(16).getBytes())).toString(16); +		//String digest_of_G_as_string = new BigInteger(MessageDigest.getInstance("SHA-256").digest(ConfigHelper.g.toByteArray())).toString(16);  		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 String(digest_of_username.digest()); +		String digest_of_username_as_string = new BigInteger(MessageDigest.getInstance("SHA-256").digest(username.getBytes())).toString(16); -		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(); +		String m1_source_string = xor_n_and_g + digest_of_username_as_string + clientA.toString(16) + serverB.toString(16) + K.toString(16); -		my_M1.update(m1_source_string.getBytes()); -		 -		return new BigInteger(my_M1.digest()); +		return new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(m1_source_string.getBytes()));  	} -	private boolean verifyM2(BigInteger M2, BigInteger K, BigInteger clientA, BigInteger serverB, int salt, String username) throws NoSuchAlgorithmException { +	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))) @@ -198,50 +262,99 @@ public class ProviderAPI extends IntentService {  		*/  		MessageDigest digest_of_N = MessageDigest.getInstance("SHA-256");  		digest_of_N.update(ConfigHelper.NG_1024.getBytes()); -		String digest_of_N_as_string = new String(digest_of_N.digest()); +		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 String(digest_of_G.digest()); +		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 String(digest_of_username.digest()); +		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 String(my_M1.digest()) + K.toString(); +		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) { +	private String hexXor(String a, String b) {  	    String str = "";  	    for (int i = 0; i < a.length(); i += 2) { -	      int xor = Integer.parseInt(a.substring(i, 2), 16) ^ Integer.parseInt(b.substring(i, 2), 16); +	      int xor = Integer.parseInt(a.substring(i, 2 + i), 16) ^ Integer.parseInt(b.substring(i, 2 + i), 16);  	      String xor_string = String.valueOf(Integer.valueOf(String.valueOf(xor), 16));  	      str += (xor_string.length() == 1) ? ("0" + xor) : xor_string;  	    } -	    return str; +	    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().toUpperCase(); +} -	private BigInteger sendParameterToSRPServer(String server_url, String parameter_name, BigInteger parameter) throws ClientProtocolException, IOException { +	private BigInteger sendAToSRPServer(String server_url, String username, BigInteger clientA) throws ClientProtocolException, IOException, NumberFormatException, JSONException { +		DefaultHttpClient client = new LeapHttpClient(getApplicationContext()); +		String parameter_chain = "A" + "=" + clientA.toString() + "&" + "login" + "=" + username; +		HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + parameter_chain); + +		HttpResponse 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")) { +			return BigInteger.ZERO; +		} +		List<Cookie> cookies = client.getCookieStore().getCookies(); +		if(!cookies.isEmpty()) { +			String session_id = cookies.get(0).getValue(); +		} +		return new BigInteger(json_response.getString("B"), 16); +	} +	private BigInteger sendM1ToSRPServer(String server_url, String parameter_name, BigInteger parameter) throws ClientProtocolException, IOException, JSONException {  		DefaultHttpClient client = new LeapHttpClient(getApplicationContext());  		String parameter_chain = parameter_name + "=" + parameter.toString(); -		HttpPost post = new HttpPost(server_url + "?" + parameter_chain); -		// TODO Look for how our srp server sends the serverB (as a cookie?) and how to fetch it from response. +		HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + parameter_chain); +		  		HttpResponse 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 BigInteger.ZERO; +		} +		  		List<Cookie> cookies = client.getCookieStore().getCookies(); -		return BigInteger.valueOf((Long.valueOf(cookies.get(0).getValue()))); +		String session_id = cookies.get(0).getValue(); +		return new BigInteger(json_response.getString("M2"), 16);  	}  	private String guessURL(String provider_main_url) { | 
