From 8e47afc7f4f85b80d59d253378681cb85ec54d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 16 Apr 2013 20:12:13 +0200 Subject: Made SRP working with ProviderAPI methods more frequently than not in localhost, but I cannot succeed in api.bitmask.net with my personal account. Next step: add tests from api.bitmask.net. --- src/se/leap/leapclient/LeapSRPSession.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index abdf6b2c..6fc8b2b1 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -70,6 +70,8 @@ public class LeapSRPSession { */ this.a = new BigInteger(abytes); } + else + A_LEN = 64; // Calculate x = H(s | H(U | ':' | password)) byte[] salt_bytes = Util.trim(params.s); -- cgit v1.2.3 From f9b9827ec1975cb01e83826f0ad77542e514b21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 17 Apr 2013 21:17:22 +0200 Subject: This commit contains: - SRP algorithm improved (validate method uses trim, and some other trims have been added). - Refactored calculatePasswordHash, so that it receives a String instead of a char array, and now it is capable of escaping "\" correctly. - A 1000*2 successful logins, with a new test that performs 1000 trials for 2 different username/password/server trios. Next step: think about how the user is going to trigger the log in fragment. --- src/se/leap/leapclient/LeapSRPSession.java | 36 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 6fc8b2b1..d266cd7f 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -34,7 +34,7 @@ public class LeapSRPSession { @param password, the user clear text password @param params, the SRP parameters for the session */ - public LeapSRPSession(String username, char[] password, SRPParameters params) + public LeapSRPSession(String username, String password, SRPParameters params) { this(username, password, params, null); } @@ -47,7 +47,7 @@ public class LeapSRPSession { @param abytes, the random exponent used in the A public key. This must be 8 bytes in length. */ - public LeapSRPSession(String username, char[] password, SRPParameters params, + public LeapSRPSession(String username, String password, SRPParameters params, byte[] abytes) { try { // Initialize the secure random number and message digests @@ -117,11 +117,11 @@ public class LeapSRPSession { * @param salt the salt of the user * @return x */ - public byte[] calculatePasswordHash(String username, char[] password, byte[] salt) + public byte[] calculatePasswordHash(String username, String password, byte[] salt) { + password = password.replaceAll("\\\\", "\\\\\\\\"); // Calculate x = H(s | H(U | ':' | password)) MessageDigest x_digest = newDigest(); - // Try to convert the username to a byte[] using UTF-8 byte[] user = null; byte[] colon = {}; @@ -135,10 +135,10 @@ public class LeapSRPSession { colon = Util.trim(":".getBytes()); } - byte[] passBytes = new byte[2*password.length]; + byte[] passBytes = new byte[2*password.toCharArray().length]; int passBytesLength = 0; - for(int p = 0; p < password.length; p++) { - int c = (password[p] & 0x00FFFF); + for(int p = 0; p < password.toCharArray().length; p++) { + int c = (password.toCharArray()[p] & 0x00FFFF); // The low byte of the char byte b0 = (byte) (c & 0x0000FF); // The high byte of the char @@ -159,7 +159,7 @@ public class LeapSRPSession { x_digest.reset(); x_digest.update(salt); x_digest.update(h); - byte[] x_digest_bytes = Util.trim(x_digest.digest()); + byte[] x_digest_bytes = x_digest.digest(); return x_digest_bytes; } @@ -171,7 +171,8 @@ public class LeapSRPSession { */ private BigInteger calculateV(String k_string) { BigInteger k = new BigInteger(k_string, 16); - return k.multiply(g.modPow(x, N)); // g^x % N + BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N + return v; } public byte[] xor(byte[] b1, byte[] b2, int length) @@ -229,13 +230,13 @@ public class LeapSRPSession { // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm); - K = sessionDigest.digest(S_bytes); + K = Util.trim(sessionDigest.digest(S_bytes)); //K = Util.trim(K); //String K_bytes_string = new BigInteger(1, K).toString(16); // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); - byte[] M1 = clientHash.digest(); + byte[] M1 = Util.trim(clientHash.digest()); // serverHash = Astr + M + K serverHash.update(M1); @@ -250,10 +251,11 @@ public class LeapSRPSession { */ private BigInteger calculateS(byte[] Bbytes) { byte[] Abytes = Util.trim(A.toByteArray()); + Bbytes = Util.trim(Bbytes); byte[] u_bytes = getU(Abytes, Bbytes); - //ub = Util.trim(ub); BigInteger B = new BigInteger(1, Bbytes); + //String Bstring = B.toString(16); BigInteger u = new BigInteger(1, u_bytes); //String u_string = u.toString(16); @@ -273,9 +275,10 @@ public class LeapSRPSession { */ public byte[] getU(byte[] Abytes, byte[] Bbytes) { MessageDigest u_digest = newDigest(); - u_digest.update(Abytes); - u_digest.update(Bbytes); - return new BigInteger(1, u_digest.digest()).toByteArray(); + u_digest.update(Util.trim(Abytes)); + u_digest.update(Util.trim(Bbytes)); + byte[] u_digest_bytes = u_digest.digest();//Util.trim(u_digest.digest()); + return Util.trim(new BigInteger(1, u_digest_bytes).toByteArray()); } /** @@ -285,7 +288,8 @@ public class LeapSRPSession { public boolean verify(byte[] M2) { // M2 = H(A | M1 | K) - byte[] myM2 = serverHash.digest(); + M2 = Util.trim(M2); + byte[] myM2 = Util.trim(serverHash.digest()); boolean valid = Arrays.equals(M2, myM2); return valid; } -- cgit v1.2.3 From 09493a9dec5fb235d5c4914eb8f8142e3312e246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 29 Apr 2013 21:32:10 +0200 Subject: Changed the message shown when checking if the password is valid or not. Refactored LeapSRPSession so that there is no need to send A twice. --- src/se/leap/leapclient/LeapSRPSession.java | 94 ++++++++++++++++-------------- 1 file changed, 51 insertions(+), 43 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index d266cd7f..f9037de9 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -14,7 +14,10 @@ import org.jboss.security.srp.SRPPermission; public class LeapSRPSession { private SRPParameters params; + private String username; + private String password; private BigInteger N; + private byte[] N_bytes; private BigInteger g; private BigInteger x; private BigInteger v; @@ -58,9 +61,11 @@ public class LeapSRPSession { this.params = params; this.g = new BigInteger(1, params.g); - byte[] N_bytes = Util.trim(params.N); + N_bytes = Util.trim(params.N); this.N = new BigInteger(1, N_bytes); - + this.username = username; + this.password = password; + if( abytes != null ) { A_LEN = 8*abytes.length; /* TODO Why did they put this condition? @@ -73,41 +78,8 @@ public class LeapSRPSession { else A_LEN = 64; - // Calculate x = H(s | H(U | ':' | password)) - byte[] salt_bytes = Util.trim(params.s); - byte[] xb = calculatePasswordHash(username, password, salt_bytes); - this.x = new BigInteger(1, xb); - - // Calculate v = kg^x mod N - String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; - this.v = calculateV(k_string); - //String v_string = v.toString(16); - serverHash = newDigest(); clientHash = newDigest(); - - // H(N) - byte[] digest_of_n = newDigest().digest(N_bytes); - - // H(g) - byte[] digest_of_g = newDigest().digest(params.g); - - // clientHash = H(N) xor H(g) - byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); - //String hxg_string = new BigInteger(1, xor_digest).toString(16); - clientHash.update(xor_digest); - - // clientHash = H(N) xor H(g) | H(U) - byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); - username_digest = Util.trim(username_digest); - //String username_digest_string = new BigInteger(1, username_digest).toString(16); - clientHash.update(username_digest); - - // clientHash = H(N) xor H(g) | H(U) | s - //String salt_string = new BigInteger(1, salt_bytes).toString(16); - clientHash.update(salt_bytes); - - K = null; } /** @@ -198,13 +170,6 @@ public class LeapSRPSession { } A = g.modPow(a, N); Abytes = Util.trim(A.toByteArray()); - //String Abytes_string = new BigInteger(1, Abytes).toString(16); - - // clientHash = H(N) xor H(g) | H(U) | A - clientHash.update(Abytes); - - // serverHash = A - serverHash.update(Abytes); } return Abytes; } @@ -213,10 +178,52 @@ public class LeapSRPSession { * Calculates the parameter M1, to be sent to the SRP server. * It also updates hashes of client and server for further calculations in other methods. * @param Bbytes the parameter received from the server, in bytes + * @param bs * @return the parameter M1 * @throws NoSuchAlgorithmException */ - public byte[] response(byte[] Bbytes) throws NoSuchAlgorithmException { + public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException { + // Calculate x = H(s | H(U | ':' | password)) + byte[] xb = calculatePasswordHash(username, password, salt_bytes); + this.x = new BigInteger(1, xb); + + // Calculate v = kg^x mod N + String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; + this.v = calculateV(k_string); + //String v_string = v.toString(16); + + + // H(N) + byte[] digest_of_n = newDigest().digest(N_bytes); + + // H(g) + byte[] digest_of_g = newDigest().digest(params.g); + + // clientHash = H(N) xor H(g) + byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); + //String hxg_string = new BigInteger(1, xor_digest).toString(16); + clientHash.update(xor_digest); + + // clientHash = H(N) xor H(g) | H(U) + byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); + username_digest = Util.trim(username_digest); + //String username_digest_string = new BigInteger(1, username_digest).toString(16); + clientHash.update(username_digest); + + // clientHash = H(N) xor H(g) | H(U) | s + //String salt_string = new BigInteger(1, salt_bytes).toString(16); + clientHash.update(Util.trim(salt_bytes)); + + K = null; + + // clientHash = H(N) xor H(g) | H(U) | s | A | B + + byte[] Abytes = Util.trim(A.toByteArray()); + //String Abytes_string = new BigInteger(1, Abytes).toString(16); + + // clientHash = H(N) xor H(g) | H(U) | A + clientHash.update(Abytes); + // clientHash = H(N) xor H(g) | H(U) | s | A | B Bbytes = Util.trim(Bbytes); //String Bbytes_string = new BigInteger(1, Bbytes).toString(16); @@ -239,6 +246,7 @@ public class LeapSRPSession { byte[] M1 = Util.trim(clientHash.digest()); // serverHash = Astr + M + K + serverHash.update(Abytes); serverHash.update(M1); serverHash.update(K); return M1; -- cgit v1.2.3 From 80a8106afc8956008beb9d1ed9396f1d695d5b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 13 May 2013 20:39:34 +0200 Subject: A bit more clean. I've upper cased ConfigHelper constants. I've created a new method in ConfigHelper, to send requests to a server, that it's used when sending A and M1. --- src/se/leap/leapclient/LeapSRPSession.java | 39 ++++++------------------------ 1 file changed, 7 insertions(+), 32 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index f9037de9..7b32e791 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -47,8 +47,7 @@ public class LeapSRPSession { @param username, the user ID @param password, the user clear text password @param params, the SRP parameters for the session - @param abytes, the random exponent used in the A public key. This must be - 8 bytes in length. + @param abytes, the random exponent used in the A public key */ public LeapSRPSession(String username, String password, SRPParameters params, byte[] abytes) { @@ -177,8 +176,9 @@ public class LeapSRPSession { /** * Calculates the parameter M1, to be sent to the SRP server. * It also updates hashes of client and server for further calculations in other methods. + * It uses a predefined k. + * @param salt_bytes * @param Bbytes the parameter received from the server, in bytes - * @param bs * @return the parameter M1 * @throws NoSuchAlgorithmException */ @@ -190,8 +190,6 @@ public class LeapSRPSession { // Calculate v = kg^x mod N String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; this.v = calculateV(k_string); - //String v_string = v.toString(16); - // H(N) byte[] digest_of_n = newDigest().digest(N_bytes); @@ -201,54 +199,45 @@ public class LeapSRPSession { // clientHash = H(N) xor H(g) byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); - //String hxg_string = new BigInteger(1, xor_digest).toString(16); clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); username_digest = Util.trim(username_digest); - //String username_digest_string = new BigInteger(1, username_digest).toString(16); clientHash.update(username_digest); // clientHash = H(N) xor H(g) | H(U) | s - //String salt_string = new BigInteger(1, salt_bytes).toString(16); clientHash.update(Util.trim(salt_bytes)); K = null; - - // clientHash = H(N) xor H(g) | H(U) | s | A | B - - byte[] Abytes = Util.trim(A.toByteArray()); - //String Abytes_string = new BigInteger(1, Abytes).toString(16); // clientHash = H(N) xor H(g) | H(U) | A + byte[] Abytes = Util.trim(A.toByteArray()); clientHash.update(Abytes); // clientHash = H(N) xor H(g) | H(U) | s | A | B Bbytes = Util.trim(Bbytes); - //String Bbytes_string = new BigInteger(1, Bbytes).toString(16); clientHash.update(Bbytes); // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); byte[] S_bytes = Util.trim(S.toByteArray()); - //String S_bytes_string = new BigInteger(1, S_bytes).toString(16); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm); K = Util.trim(sessionDigest.digest(S_bytes)); - //K = Util.trim(K); - //String K_bytes_string = new BigInteger(1, K).toString(16); // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); + byte[] M1 = Util.trim(clientHash.digest()); // serverHash = Astr + M + K serverHash.update(Abytes); serverHash.update(M1); serverHash.update(K); + return M1; } @@ -263,13 +252,10 @@ public class LeapSRPSession { byte[] u_bytes = getU(Abytes, Bbytes); BigInteger B = new BigInteger(1, Bbytes); - //String Bstring = B.toString(16); BigInteger u = new BigInteger(1, u_bytes); - //String u_string = u.toString(16); BigInteger B_minus_v = B.subtract(v); BigInteger a_ux = a.add(u.multiply(x)); - //String a_ux_string = a_ux.toString(16); BigInteger S = B_minus_v.modPow(a_ux, N); return S; @@ -285,7 +271,7 @@ public class LeapSRPSession { MessageDigest u_digest = newDigest(); u_digest.update(Util.trim(Abytes)); u_digest.update(Util.trim(Bbytes)); - byte[] u_digest_bytes = u_digest.digest();//Util.trim(u_digest.digest()); + byte[] u_digest_bytes = u_digest.digest(); return Util.trim(new BigInteger(1, u_digest_bytes).toByteArray()); } @@ -302,17 +288,6 @@ public class LeapSRPSession { return valid; } - /** Returns the negotiated session K, K = SHA_Interleave(S) - @return the private session K byte[] - @throws SecurityException - if the current thread does not have an - getSessionKey SRPPermission. - */ - public byte[] getSessionKey() throws SecurityException - { - return K; - } - - /** * @return a new SHA-256 digest. */ -- cgit v1.2.3 From 7b75fbe9ca3b2d6175b124b26f5d8f527b15d1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 29 May 2013 19:54:26 +0200 Subject: Fixed passwords with strange characters? Using two test with values from my localhost leap_web deployment, I've achieved to login with passwords containing ! and $ without problems. This should fix bug #2348. --- src/se/leap/leapclient/LeapSRPSession.java | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 7b32e791..715e9de1 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -95,35 +95,24 @@ public class LeapSRPSession { MessageDigest x_digest = newDigest(); // Try to convert the username to a byte[] using UTF-8 byte[] user = null; + byte[] password_bytes = null; byte[] colon = {}; try { user = Util.trim(username.getBytes("UTF-8")); colon = Util.trim(":".getBytes("UTF-8")); + password_bytes = Util.trim(password.getBytes("UTF-8")); } catch(UnsupportedEncodingException e) { // Use the default platform encoding user = Util.trim(username.getBytes()); colon = Util.trim(":".getBytes()); + password_bytes = Util.trim(password.getBytes()); } - - byte[] passBytes = new byte[2*password.toCharArray().length]; - int passBytesLength = 0; - for(int p = 0; p < password.toCharArray().length; p++) { - int c = (password.toCharArray()[p] & 0x00FFFF); - // The low byte of the char - byte b0 = (byte) (c & 0x0000FF); - // The high byte of the char - byte b1 = (byte) ((c & 0x00FF00) >> 8); - passBytes[passBytesLength ++] = b0; - // Only encode the high byte if c is a multi-byte char - if( c > 255 ) - passBytes[passBytesLength ++] = b1; - } - + // Build the hash x_digest.update(user); x_digest.update(colon); - x_digest.update(passBytes, 0, passBytesLength); + x_digest.update(password_bytes); byte[] h = x_digest.digest(); //h = Util.trim(h); -- cgit v1.2.3 From ac47aab124d63add14189cb3d03e3a05361a7932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 4 Jun 2013 16:31:39 +0200 Subject: Fixed 2 important bugs. LeapSRPSession was doing bad SRP calculations when salt byte array started with a 0. Now I trimmed that array before using it. ProviderAPI was not timing out when a server didn't respond. Now, I use a timeout of 1 second to stop waiting for a response. --- src/se/leap/leapclient/LeapSRPSession.java | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 715e9de1..8d6f77bf 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -109,13 +109,29 @@ public class LeapSRPSession { password_bytes = Util.trim(password.getBytes()); } + /*byte[] passBytes = new byte[2*password.toCharArray().length]; + int passBytesLength = 0; + for(int p = 0; p < password.toCharArray().length; p++) { + int c = (password.toCharArray()[p] & 0x00FFFF); + // The low byte of the char + byte b0 = (byte) (c & 0x0000FF); + // The high byte of the char + byte b1 = (byte) ((c & 0x00FF00) >> 8); + passBytes[passBytesLength ++] = b0; + // Only encode the high byte if c is a multi-byte char + if( c > 255 ) + passBytes[passBytesLength ++] = b1; + }*/ + // Build the hash x_digest.update(user); x_digest.update(colon); x_digest.update(password_bytes); + //x_digest.update(passBytes, 0, passBytesLength); byte[] h = x_digest.digest(); + String hstr = new BigInteger(1, h).toString(16); //h = Util.trim(h); - + //25c19c2b903ff36dd5acd6e1136b8f3af008ceee45103ef9771334f4246d6226 x_digest.reset(); x_digest.update(salt); x_digest.update(h); @@ -173,8 +189,9 @@ public class LeapSRPSession { */ public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException { // Calculate x = H(s | H(U | ':' | password)) - byte[] xb = calculatePasswordHash(username, password, salt_bytes); + byte[] xb = calculatePasswordHash(username, password, Util.trim(salt_bytes)); this.x = new BigInteger(1, xb); + String xstr = x.toString(16); // Calculate v = kg^x mod N String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; @@ -211,6 +228,7 @@ public class LeapSRPSession { // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); byte[] S_bytes = Util.trim(S.toByteArray()); + String Sstr = S.toString(16); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; @@ -219,8 +237,10 @@ public class LeapSRPSession { // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); + String Kstr = new BigInteger(1, K).toString(16); byte[] M1 = Util.trim(clientHash.digest()); + String M1str = new BigInteger(1, M1).toString(16); // serverHash = Astr + M + K serverHash.update(Abytes); @@ -244,9 +264,10 @@ public class LeapSRPSession { BigInteger u = new BigInteger(1, u_bytes); BigInteger B_minus_v = B.subtract(v); + String vstr = v.toString(16); BigInteger a_ux = a.add(u.multiply(x)); + String xstr = x.toString(16); BigInteger S = B_minus_v.modPow(a_ux, N); - return S; } -- cgit v1.2.3 From 611bb7869ea6a98fe656b6e86ef98118d232fd45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 4 Jun 2013 20:42:05 +0200 Subject: Fixed SRP strange characters bugs. The problem was the encoding of the bytes when calculating the password hash. I supposed that it was UTF-8 (I already saw that encoding in the html code from leap_web), but not, it was ISO-8859-1 (trial/error). --- src/se/leap/leapclient/LeapSRPSession.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 8d6f77bf..77f43945 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -97,10 +97,11 @@ public class LeapSRPSession { byte[] user = null; byte[] password_bytes = null; byte[] colon = {}; + String encoding = "ISO-8859-1"; try { - user = Util.trim(username.getBytes("UTF-8")); - colon = Util.trim(":".getBytes("UTF-8")); - password_bytes = Util.trim(password.getBytes("UTF-8")); + user = Util.trim(username.getBytes(encoding)); + colon = Util.trim(":".getBytes(encoding)); + password_bytes = Util.trim(password.getBytes(encoding)); } catch(UnsupportedEncodingException e) { // Use the default platform encoding -- cgit v1.2.3 From d74a3ae14a27893572d170c138e18522b541866a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 5 Jun 2013 18:57:55 +0200 Subject: Fixed passwords with \ character. The substitution I was doing let me to pass my tests localhost, but was not valid for real use in Android emulator. This was so because JSONObject getString method understood \/ simply as /, while what I wanted was plain \/. This commit makes #2368 --- src/se/leap/leapclient/LeapSRPSession.java | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 77f43945..47dff276 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -90,10 +90,10 @@ public class LeapSRPSession { */ public byte[] calculatePasswordHash(String username, String password, byte[] salt) { - password = password.replaceAll("\\\\", "\\\\\\\\"); + //password = password.replaceAll("\\\\", "\\\\\\\\"); // Calculate x = H(s | H(U | ':' | password)) MessageDigest x_digest = newDigest(); - // Try to convert the username to a byte[] using UTF-8 + // Try to convert the username to a byte[] using ISO-8859-1 byte[] user = null; byte[] password_bytes = null; byte[] colon = {}; @@ -110,29 +110,12 @@ public class LeapSRPSession { password_bytes = Util.trim(password.getBytes()); } - /*byte[] passBytes = new byte[2*password.toCharArray().length]; - int passBytesLength = 0; - for(int p = 0; p < password.toCharArray().length; p++) { - int c = (password.toCharArray()[p] & 0x00FFFF); - // The low byte of the char - byte b0 = (byte) (c & 0x0000FF); - // The high byte of the char - byte b1 = (byte) ((c & 0x00FF00) >> 8); - passBytes[passBytesLength ++] = b0; - // Only encode the high byte if c is a multi-byte char - if( c > 255 ) - passBytes[passBytesLength ++] = b1; - }*/ - // Build the hash x_digest.update(user); x_digest.update(colon); x_digest.update(password_bytes); - //x_digest.update(passBytes, 0, passBytesLength); byte[] h = x_digest.digest(); - String hstr = new BigInteger(1, h).toString(16); - //h = Util.trim(h); - //25c19c2b903ff36dd5acd6e1136b8f3af008ceee45103ef9771334f4246d6226 + x_digest.reset(); x_digest.update(salt); x_digest.update(h); -- cgit v1.2.3 From e581c6f2c1844d5dd96b12413df91dbb06102282 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 22:50:07 -0600 Subject: Clean up some unused and some formatting --- src/se/leap/leapclient/LeapSRPSession.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 47dff276..8eb28c4d 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -7,9 +7,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.jboss.security.Util; -import org.jboss.security.srp.SRPClientSession; import org.jboss.security.srp.SRPParameters; -import org.jboss.security.srp.SRPPermission; public class LeapSRPSession { -- cgit v1.2.3 From 1e2470b1e940877f6fe247a65bccd2b62b621eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 10 Jun 2013 18:56:34 +0200 Subject: Removed unused methods and variables. Variables from LeapSRPSession were there because I used it while testing srp calculations, comparing that strings with the ones from javascript. Unused method from ProviderAPI was there because I foresee I'll have to implement it in the future, but I've removed it since it's already in the history. This fixes #2781. --- src/se/leap/leapclient/LeapSRPSession.java | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 8eb28c4d..0a8e735f 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -173,7 +173,6 @@ public class LeapSRPSession { // Calculate x = H(s | H(U | ':' | password)) byte[] xb = calculatePasswordHash(username, password, Util.trim(salt_bytes)); this.x = new BigInteger(1, xb); - String xstr = x.toString(16); // Calculate v = kg^x mod N String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; @@ -210,7 +209,6 @@ public class LeapSRPSession { // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); byte[] S_bytes = Util.trim(S.toByteArray()); - String Sstr = S.toString(16); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; @@ -219,10 +217,8 @@ public class LeapSRPSession { // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); - String Kstr = new BigInteger(1, K).toString(16); byte[] M1 = Util.trim(clientHash.digest()); - String M1str = new BigInteger(1, M1).toString(16); // serverHash = Astr + M + K serverHash.update(Abytes); @@ -246,9 +242,7 @@ public class LeapSRPSession { BigInteger u = new BigInteger(1, u_bytes); BigInteger B_minus_v = B.subtract(v); - String vstr = v.toString(16); BigInteger a_ux = a.add(u.multiply(x)); - String xstr = x.toString(16); BigInteger S = B_minus_v.modPow(a_ux, N); return S; } -- cgit v1.2.3 From d475ae617d8dc0994a1294be7c8cca338a68fd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 19 Jun 2013 19:05:12 +0200 Subject: First round of comments. This resolves the first step from issue #2908. Next step: Put user message strings into an appropiate place. --- src/se/leap/leapclient/LeapSRPSession.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 0a8e735f..beb286da 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -9,6 +9,14 @@ import java.util.Arrays; import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; +/** + * Implements all SRP algorithm logic. + * + * It's derived from JBoss implementation, with adjustments to make it work with LEAP platform. + * + * @author parmegv + * + */ public class LeapSRPSession { private SRPParameters params; @@ -133,7 +141,14 @@ public class LeapSRPSession { return v; } - public byte[] xor(byte[] b1, byte[] b2, int length) + /** + * Calculates the trimmed xor from two BigInteger numbers + * @param b1 the positive source to build first BigInteger + * @param b2 the positive source to build second BigInteger + * @param length + * @return + */ + public byte[] xor(byte[] b1, byte[] b2) { //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray(); @@ -185,7 +200,7 @@ public class LeapSRPSession { byte[] digest_of_g = newDigest().digest(params.g); // clientHash = H(N) xor H(g) - byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); + byte[] xor_digest = xor(digest_of_n, digest_of_g); clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) -- cgit v1.2.3 From 65e2f56a8a10877964fb9fc57963d1bf8104801a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 20 Jun 2013 17:47:07 +0200 Subject: No binary library needed. I've decided not to include any lib, but to copy the SRPParameters class to our codebase and Util.trim method to ConfigHelper. --- src/se/leap/leapclient/LeapSRPSession.java | 69 +++++++++++++++--------------- 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'src/se/leap/leapclient/LeapSRPSession.java') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index beb286da..d21ccffe 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -4,9 +4,9 @@ import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Arrays; -import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; /** @@ -30,6 +30,7 @@ public class LeapSRPSession { private BigInteger a; private BigInteger A; private byte[] K; + private SecureRandom pseudoRng; /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */ private MessageDigest clientHash; /** The M2 = H(A | M | K) hash */ @@ -57,20 +58,20 @@ public class LeapSRPSession { */ public LeapSRPSession(String username, String password, SRPParameters params, byte[] abytes) { - try { - // Initialize the secure random number and message digests - Util.init(); - } - catch(NoSuchAlgorithmException e) { - } - this.params = params; this.g = new BigInteger(1, params.g); - N_bytes = Util.trim(params.N); + N_bytes = ConfigHelper.trim(params.N); this.N = new BigInteger(1, N_bytes); this.username = username; this.password = password; + try { + pseudoRng = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if( abytes != null ) { A_LEN = 8*abytes.length; /* TODO Why did they put this condition? @@ -105,15 +106,15 @@ public class LeapSRPSession { byte[] colon = {}; String encoding = "ISO-8859-1"; try { - user = Util.trim(username.getBytes(encoding)); - colon = Util.trim(":".getBytes(encoding)); - password_bytes = Util.trim(password.getBytes(encoding)); + user = ConfigHelper.trim(username.getBytes(encoding)); + colon = ConfigHelper.trim(":".getBytes(encoding)); + password_bytes = ConfigHelper.trim(password.getBytes(encoding)); } catch(UnsupportedEncodingException e) { // Use the default platform encoding - user = Util.trim(username.getBytes()); - colon = Util.trim(":".getBytes()); - password_bytes = Util.trim(password.getBytes()); + user = ConfigHelper.trim(username.getBytes()); + colon = ConfigHelper.trim(":".getBytes()); + password_bytes = ConfigHelper.trim(password.getBytes()); } // Build the hash @@ -152,7 +153,7 @@ public class LeapSRPSession { { //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray(); - return Util.trim(xor_digest); + return ConfigHelper.trim(xor_digest); } /** @@ -166,11 +167,11 @@ public class LeapSRPSession { if( a == null ) { BigInteger one = BigInteger.ONE; do { - a = new BigInteger(A_LEN, Util.getPRNG()); + a = new BigInteger(A_LEN, pseudoRng); } while(a.compareTo(one) <= 0); } A = g.modPow(a, N); - Abytes = Util.trim(A.toByteArray()); + Abytes = ConfigHelper.trim(A.toByteArray()); } return Abytes; } @@ -186,7 +187,7 @@ public class LeapSRPSession { */ public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException { // Calculate x = H(s | H(U | ':' | password)) - byte[] xb = calculatePasswordHash(username, password, Util.trim(salt_bytes)); + byte[] xb = calculatePasswordHash(username, password, ConfigHelper.trim(salt_bytes)); this.x = new BigInteger(1, xb); // Calculate v = kg^x mod N @@ -204,36 +205,36 @@ public class LeapSRPSession { clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) - byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); - username_digest = Util.trim(username_digest); + byte[] username_digest = newDigest().digest(ConfigHelper.trim(username.getBytes())); + username_digest = ConfigHelper.trim(username_digest); clientHash.update(username_digest); // clientHash = H(N) xor H(g) | H(U) | s - clientHash.update(Util.trim(salt_bytes)); + clientHash.update(ConfigHelper.trim(salt_bytes)); K = null; // clientHash = H(N) xor H(g) | H(U) | A - byte[] Abytes = Util.trim(A.toByteArray()); + byte[] Abytes = ConfigHelper.trim(A.toByteArray()); clientHash.update(Abytes); // clientHash = H(N) xor H(g) | H(U) | s | A | B - Bbytes = Util.trim(Bbytes); + Bbytes = ConfigHelper.trim(Bbytes); clientHash.update(Bbytes); // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); - byte[] S_bytes = Util.trim(S.toByteArray()); + byte[] S_bytes = ConfigHelper.trim(S.toByteArray()); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm); - K = Util.trim(sessionDigest.digest(S_bytes)); + K = ConfigHelper.trim(sessionDigest.digest(S_bytes)); // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); - byte[] M1 = Util.trim(clientHash.digest()); + byte[] M1 = ConfigHelper.trim(clientHash.digest()); // serverHash = Astr + M + K serverHash.update(Abytes); @@ -249,8 +250,8 @@ public class LeapSRPSession { * @return the parameter S */ private BigInteger calculateS(byte[] Bbytes) { - byte[] Abytes = Util.trim(A.toByteArray()); - Bbytes = Util.trim(Bbytes); + byte[] Abytes = ConfigHelper.trim(A.toByteArray()); + Bbytes = ConfigHelper.trim(Bbytes); byte[] u_bytes = getU(Abytes, Bbytes); BigInteger B = new BigInteger(1, Bbytes); @@ -270,10 +271,10 @@ public class LeapSRPSession { */ public byte[] getU(byte[] Abytes, byte[] Bbytes) { MessageDigest u_digest = newDigest(); - u_digest.update(Util.trim(Abytes)); - u_digest.update(Util.trim(Bbytes)); + u_digest.update(ConfigHelper.trim(Abytes)); + u_digest.update(ConfigHelper.trim(Bbytes)); byte[] u_digest_bytes = u_digest.digest(); - return Util.trim(new BigInteger(1, u_digest_bytes).toByteArray()); + return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray()); } /** @@ -283,8 +284,8 @@ public class LeapSRPSession { public boolean verify(byte[] M2) { // M2 = H(A | M1 | K) - M2 = Util.trim(M2); - byte[] myM2 = Util.trim(serverHash.digest()); + M2 = ConfigHelper.trim(M2); + byte[] myM2 = ConfigHelper.trim(serverHash.digest()); boolean valid = Arrays.equals(M2, myM2); return valid; } -- cgit v1.2.3