From 54ad71d09d6cb61fad62d1376cd7b3bf237e16f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Fri, 29 Mar 2013 16:30:39 +0100 Subject: Tried to implement SRP with JBoss: discarded because it needs RMI to get the salt, and because of our messageflow I cannot obtain it before starting Authentication. That's why on line 132 from ProviderAPI I tried to get a new SRPClientSession using the newly obtained salt, but of course it fails since A cannot be restored from previous initialization. Next step: try with srpforjava. Next next step: if srpforjava does not work for us, use lower level methods to implement our own http srp flow. --- src/se/leap/leapclient/ProviderAPI.java | 270 +++++--------------------------- 1 file changed, 35 insertions(+), 235 deletions(-) (limited to 'src') diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index eb3afcfa..aa1ce305 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 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 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); -- cgit v1.2.3