From 5b9e20dca5f70289a2fcdfaa9f45fabd28887726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 5 Mar 2013 21:13:27 +0100 Subject: Registering method from ProviderAPI implemented and tested. M1 is not OK, because errors (with null description, awkward) are received from posting M1 to the server instead of M2. Next step: purge user database from leap_webapp and start testing again. --- src/se/leap/leapclient/ConfigHelper.java | 24 ++- src/se/leap/leapclient/ConfigurationWizard.java | 4 - src/se/leap/leapclient/ProviderAPI.java | 261 +++++++++++++++++------- 3 files changed, 205 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index c9810519..41364e96 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 e41eb5cf..33ff31fe 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 19404c2b..41612d16 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 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 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) { -- cgit v1.2.3