summaryrefslogtreecommitdiff
path: root/src/se/leap/leapclient/ProviderAPI.java
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2013-03-05 21:13:27 +0100
committerParménides GV <parmegv@sdf.org>2013-03-05 21:13:27 +0100
commit5b9e20dca5f70289a2fcdfaa9f45fabd28887726 (patch)
tree120f68ce96a085bb39c568c96847b82996277898 /src/se/leap/leapclient/ProviderAPI.java
parent018eb179f820b09d2e65c5ede1d4a867957bbce4 (diff)
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.
Diffstat (limited to 'src/se/leap/leapclient/ProviderAPI.java')
-rw-r--r--src/se/leap/leapclient/ProviderAPI.java261
1 files changed, 187 insertions, 74 deletions
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<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) {