summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2013-02-25 21:30:42 +0100
committerParménides GV <parmegv@sdf.org>2013-02-25 21:30:42 +0100
commit5964b1ffec270b99cdbc962cd0c4aefa2c5fcb4d (patch)
treef8f833c518da35953daae13ab6ad4baaa694979c
parent1868e180e8f56c310a52f4ed399dc9e34284957e (diff)
Finished first implementation of SRP.
Next step: get cookies understood, how do I get server's sent parameters?
-rw-r--r--src/se/leap/leapclient/ConfigHelper.java1
-rw-r--r--src/se/leap/leapclient/ProviderAPI.java154
2 files changed, 147 insertions, 8 deletions
diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java
index 533a426f..7649fcae 100644
--- a/src/se/leap/leapclient/ConfigHelper.java
+++ b/src/se/leap/leapclient/ConfigHelper.java
@@ -28,6 +28,7 @@ public class ConfigHelper {
public static final String PREFERENCES_KEY = "LEAPPreferences";
public static final String user_directory = "leap_android";
public static String provider_key_url = "provider_main_url";
+ final public static String srp_server_url_key = "srp_server_url";
final public static String username_key = "username";
final public static String password_key = "password";
final public static String eip_service_api_path = "/config/eip-service.json";
diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java
index e83e9e6e..39bb50ec 100644
--- a/src/se/leap/leapclient/ProviderAPI.java
+++ b/src/se/leap/leapclient/ProviderAPI.java
@@ -2,15 +2,25 @@ 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.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.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;
import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
@@ -76,22 +86,150 @@ public class ProviderAPI extends IntentService {
else if ((task = task_for.getBundleExtra(ConfigHelper.srpAuth)) != null) {
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
- String salt = getSaltFromSRPServer();
- BigInteger A = srp_client.generateClientCredentials(salt.getBytes(), username.getBytes(), password.getBytes());
+ 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
- //S = calculateSecret(BigInteger serverB)
- //K = H(S)
- //Now the two parties have a shared, strong session key K. To complete authentication, they need to prove to each other that their keys match.
+ 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();
+ }
}
}
+
+ 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 String getSaltFromSRPServer() {
- // TODO Auto-generated method stub
- return null;
+ private BigInteger generateM1(BigInteger K, BigInteger clientA, BigInteger serverB, int salt, 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 String(digest_of_N.digest());
+
+ 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 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());
+
+ 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());
+
+ return new BigInteger(my_M1.digest());
+ }
+
+ private boolean verifyM2(BigInteger M2, BigInteger K, BigInteger clientA, BigInteger serverB, int salt, 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 String(digest_of_N.digest());
+
+ 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 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());
+
+ 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();
+
+ 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 = Integer.parseInt(a.substring(i, 2), 16) ^ Integer.parseInt(b.substring(i, 2), 16);
+ String xor_string = String.valueOf(Integer.valueOf(String.valueOf(xor), 16));
+ str += (xor_string.length() == 1) ? ("0" + xor) : xor_string;
+ }
+ return str;
+ }
+
+ private BigInteger sendParameterToSRPServer(String server_url, String parameter_name, BigInteger parameter) throws ClientProtocolException, IOException {
+ 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.
+ HttpResponse getResponse = client.execute(post);
+ HttpEntity responseEntity = getResponse.getEntity();
+ List<Cookie> cookies = client.getCookieStore().getCookies();
+ return BigInteger.valueOf((Long.valueOf(cookies.get(0).getValue())));
}
private String guessURL(String provider_main_url) {