mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 722496, Bug 722579, Bug 722482, Bug 722541. r=rnewman
This commit is contained in:
parent
26e9ab663b
commit
aacf3c37de
@ -40,9 +40,10 @@ package org.mozilla.gecko.sync;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
import org.mozilla.apache.commons.codec.binary.Base32;
|
import org.mozilla.apache.commons.codec.binary.Base32;
|
||||||
import org.mozilla.apache.commons.codec.binary.Base64;
|
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||||
@ -56,6 +57,8 @@ public class Utils {
|
|||||||
|
|
||||||
private static final String LOG_TAG = "Utils";
|
private static final String LOG_TAG = "Utils";
|
||||||
|
|
||||||
|
private static SecureRandom sharedSecureRandom = new SecureRandom();
|
||||||
|
|
||||||
// See <http://developer.android.com/reference/android/content/Context.html#getSharedPreferences%28java.lang.String,%20int%29>
|
// See <http://developer.android.com/reference/android/content/Context.html#getSharedPreferences%28java.lang.String,%20int%29>
|
||||||
public static final int SHARED_PREFERENCES_MODE = 0;
|
public static final int SHARED_PREFERENCES_MODE = 0;
|
||||||
|
|
||||||
@ -104,13 +107,35 @@ public class Utils {
|
|||||||
return new String(encodedBytes).replace("+", "-").replace("/", "_");
|
return new String(encodedBytes).replace("+", "-").replace("/", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] generateRandomBytes(int length) {
|
/*
|
||||||
|
* Helper to generate secure random bytes.
|
||||||
|
*
|
||||||
|
* @param length Number of bytes to generate.
|
||||||
|
*/
|
||||||
|
public static byte[] generateRandomBytes(int length) {
|
||||||
byte[] bytes = new byte[length];
|
byte[] bytes = new byte[length];
|
||||||
Random random = new Random(System.nanoTime());
|
sharedSecureRandom.nextBytes(bytes);
|
||||||
random.nextBytes(bytes);
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper to generate a random integer in a specified range.
|
||||||
|
*
|
||||||
|
* @param r Generate an integer between 0 and r-1 inclusive.
|
||||||
|
*/
|
||||||
|
public static BigInteger generateBigIntegerLessThan(BigInteger r) {
|
||||||
|
int maxBytes = (int) Math.ceil(((double) r.bitLength()) / 8);
|
||||||
|
BigInteger randInt = new BigInteger(generateRandomBytes(maxBytes));
|
||||||
|
return randInt.mod(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper to reseed the shared secure random number generator.
|
||||||
|
*/
|
||||||
|
public static void reseedSharedRandom() {
|
||||||
|
sharedSecureRandom.setSeed(sharedSecureRandom.generateSeed(8));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper to convert Byte Array to a Hex String
|
* Helper to convert Byte Array to a Hex String
|
||||||
* Input: byte[] array
|
* Input: byte[] array
|
||||||
|
@ -245,7 +245,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
channelRequest = new JPakeRequest(jpakeServer + "new_channel",
|
channelRequest = new JPakeRequest(jpakeServer + "new_channel",
|
||||||
makeRequestResourceDelegate());
|
makeRequestResourceDelegate());
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
e.printStackTrace();
|
Log.e(LOG_TAG, "URISyntaxException", e);
|
||||||
abort(Constants.JPAKE_ERROR_CHANNEL);
|
abort(Constants.JPAKE_ERROR_CHANNEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
putRequest = new JPakeRequest(channelUrl,
|
putRequest = new JPakeRequest(channelUrl,
|
||||||
makeRequestResourceDelegate());
|
makeRequestResourceDelegate());
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
e.printStackTrace();
|
Log.e(LOG_TAG, "URISyntaxException", e);
|
||||||
abort(Constants.JPAKE_ERROR_CHANNEL);
|
abort(Constants.JPAKE_ERROR_CHANNEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -283,7 +283,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
/*
|
/*
|
||||||
* Step One of J-PAKE protocol.
|
* Step One of J-PAKE protocol.
|
||||||
*/
|
*/
|
||||||
private void computeStepOne() {
|
private void computeStepOne() throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||||
Log.d(LOG_TAG, "Computing round 1.");
|
Log.d(LOG_TAG, "Computing round 1.");
|
||||||
|
|
||||||
JPakeCrypto.round1(jParty, numGen);
|
JPakeCrypto.round1(jParty, numGen);
|
||||||
@ -321,7 +321,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
* Verifies message computed by other party in their Step One. Creates Step
|
* Verifies message computed by other party in their Step One. Creates Step
|
||||||
* Two message to be sent.
|
* Two message to be sent.
|
||||||
*/
|
*/
|
||||||
private void computeStepTwo() {
|
private void computeStepTwo() throws NonObjectJSONException {
|
||||||
Log.d(LOG_TAG, "Computing round 2.");
|
Log.d(LOG_TAG, "Computing round 2.");
|
||||||
|
|
||||||
// Check incoming message sender.
|
// Check incoming message sender.
|
||||||
@ -332,44 +332,32 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check incoming message fields.
|
// Check incoming message fields.
|
||||||
ExtendedJSONObject iPayload = null;
|
ExtendedJSONObject iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD);
|
||||||
try {
|
if (iPayload == null) {
|
||||||
iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD);
|
|
||||||
if (iPayload == null
|
|
||||||
|| iPayload.getObject(Constants.ZKP_KEY_ZKP_X1) == null
|
|
||||||
|| !theirSignerId.equals(iPayload.getObject(Constants.ZKP_KEY_ZKP_X1)
|
|
||||||
.get(Constants.ZKP_KEY_ID))
|
|
||||||
|| iPayload.getObject(Constants.ZKP_KEY_ZKP_X2) == null
|
|
||||||
|| !theirSignerId.equals(iPayload.getObject(Constants.ZKP_KEY_ZKP_X2)
|
|
||||||
.get(Constants.ZKP_KEY_ID))) {
|
|
||||||
Log.e(LOG_TAG, "Invalid round 1 message: " + jIncoming.toJSONString());
|
Log.e(LOG_TAG, "Invalid round 1 message: " + jIncoming.toJSONString());
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (NonObjectJSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract message fields.
|
ExtendedJSONObject zkpPayload3 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X1);
|
||||||
jParty.gx3 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX1),
|
ExtendedJSONObject zkpPayload4 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X2);
|
||||||
16);
|
|
||||||
jParty.gx4 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX2),
|
|
||||||
16);
|
|
||||||
|
|
||||||
ExtendedJSONObject zkpPayload3 = null;
|
|
||||||
ExtendedJSONObject zkpPayload4 = null;
|
|
||||||
try {
|
|
||||||
zkpPayload3 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X1);
|
|
||||||
zkpPayload4 = iPayload.getObject(Constants.ZKP_KEY_ZKP_X2);
|
|
||||||
if (zkpPayload3 == null || zkpPayload4 == null) {
|
if (zkpPayload3 == null || zkpPayload4 == null) {
|
||||||
Log.e(LOG_TAG, "Invalid round 1 zkpPayload message");
|
Log.e(LOG_TAG, "Invalid round 1 zkpPayload message");
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (NonObjectJSONException e) {
|
|
||||||
e.printStackTrace();
|
if (!theirSignerId.equals(zkpPayload3.get(Constants.ZKP_KEY_ID)) ||
|
||||||
|
!theirSignerId.equals(zkpPayload4.get(Constants.ZKP_KEY_ID))) {
|
||||||
|
Log.e(LOG_TAG, "Invalid round 1 zkpPayload message");
|
||||||
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract message fields.
|
||||||
|
jParty.gx3 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX1), 16);
|
||||||
|
jParty.gx4 = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_GX2), 16);
|
||||||
|
|
||||||
// Extract ZKPs.
|
// Extract ZKPs.
|
||||||
String zkp3_gr = (String) zkpPayload3.get(Constants.ZKP_KEY_GR);
|
String zkp3_gr = (String) zkpPayload3.get(Constants.ZKP_KEY_GR);
|
||||||
String zkp3_b = (String) zkpPayload3.get(Constants.ZKP_KEY_B);
|
String zkp3_b = (String) zkpPayload3.get(Constants.ZKP_KEY_B);
|
||||||
@ -379,14 +367,12 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
String zkp4_b = (String) zkpPayload4.get(Constants.ZKP_KEY_B);
|
String zkp4_b = (String) zkpPayload4.get(Constants.ZKP_KEY_B);
|
||||||
String zkp4_id = (String) zkpPayload4.get(Constants.ZKP_KEY_ID);
|
String zkp4_id = (String) zkpPayload4.get(Constants.ZKP_KEY_ID);
|
||||||
|
|
||||||
jParty.zkp3 = new Zkp(new BigInteger(zkp3_gr, 16), new BigInteger(zkp3_b,
|
jParty.zkp3 = new Zkp(new BigInteger(zkp3_gr, 16), new BigInteger(zkp3_b, 16), zkp3_id);
|
||||||
16), zkp3_id);
|
jParty.zkp4 = new Zkp(new BigInteger(zkp4_gr, 16), new BigInteger(zkp4_b, 16), zkp4_id);
|
||||||
jParty.zkp4 = new Zkp(new BigInteger(zkp4_gr, 16), new BigInteger(zkp4_b,
|
|
||||||
16), zkp4_id);
|
|
||||||
|
|
||||||
// Jpake round 2
|
// J-PAKE round 2.
|
||||||
try {
|
try {
|
||||||
JPakeCrypto.round2(secret, jParty, numGen);
|
JPakeCrypto.round2(JPakeClient.secretAsBigInteger(secret), jParty, numGen);
|
||||||
} catch (Gx3OrGx4IsZeroOrOneException e) {
|
} catch (Gx3OrGx4IsZeroOrOneException e) {
|
||||||
Log.e(LOG_TAG, "gx3 and gx4 cannot equal 0 or 1.");
|
Log.e(LOG_TAG, "gx3 and gx4 cannot equal 0 or 1.");
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
@ -395,14 +381,21 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
Log.e(LOG_TAG, "ZKP mismatch");
|
Log.e(LOG_TAG, "ZKP mismatch");
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
return;
|
return;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
Log.e(LOG_TAG, "NoSuchAlgorithmException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Log.e(LOG_TAG, "UnsupportedEncodingException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make outgoing payload.
|
// Make outgoing payload.
|
||||||
Zkp zkpA = jParty.thisZkpA;
|
Zkp zkpA = jParty.thisZkpA;
|
||||||
ExtendedJSONObject oPayload = new ExtendedJSONObject();
|
ExtendedJSONObject oPayload = new ExtendedJSONObject();
|
||||||
ExtendedJSONObject jZkpA = makeJZkp(zkpA.gr, zkpA.b, zkpA.id);
|
ExtendedJSONObject jZkpA = makeJZkp(zkpA.gr, zkpA.b, zkpA.id);
|
||||||
oPayload.put(Constants.ZKP_KEY_A,
|
oPayload.put(Constants.ZKP_KEY_A, BigIntegerHelper.toEvenLengthHex(jParty.thisA));
|
||||||
BigIntegerHelper.toEvenLengthHex(jParty.thisA));
|
|
||||||
oPayload.put(Constants.ZKP_KEY_ZKP_A, jZkpA);
|
oPayload.put(Constants.ZKP_KEY_ZKP_A, jZkpA);
|
||||||
|
|
||||||
// Make outgoing message.
|
// Make outgoing message.
|
||||||
@ -429,7 +422,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
* Verifies message computed by other party in Step Two. Creates or fetches
|
* Verifies message computed by other party in Step Two. Creates or fetches
|
||||||
* encrypted message for verification of successful key exchange.
|
* encrypted message for verification of successful key exchange.
|
||||||
*/
|
*/
|
||||||
private void computeFinal() {
|
private void computeFinal() throws NonObjectJSONException {
|
||||||
Log.d(LOG_TAG, "Computing final round.");
|
Log.d(LOG_TAG, "Computing final round.");
|
||||||
// Check incoming message type.
|
// Check incoming message type.
|
||||||
if (!jIncoming.get(Constants.JSON_KEY_TYPE).equals(theirSignerId + "2")) {
|
if (!jIncoming.get(Constants.JSON_KEY_TYPE).equals(theirSignerId + "2")) {
|
||||||
@ -439,53 +432,49 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check incoming message fields.
|
// Check incoming message fields.
|
||||||
ExtendedJSONObject iPayload = null;
|
ExtendedJSONObject iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD);
|
||||||
try {
|
if (iPayload == null ||
|
||||||
iPayload = jIncoming.getObject(Constants.JSON_KEY_PAYLOAD);
|
iPayload.getObject(Constants.ZKP_KEY_ZKP_A) == null) {
|
||||||
if (iPayload == null
|
|
||||||
|| iPayload.getObject(Constants.ZKP_KEY_ZKP_A) == null
|
|
||||||
|| !theirSignerId.equals(iPayload.getObject(Constants.ZKP_KEY_ZKP_A)
|
|
||||||
.get(Constants.ZKP_KEY_ID))) {
|
|
||||||
Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString());
|
Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString());
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (NonObjectJSONException e) {
|
ExtendedJSONObject zkpPayload = iPayload.getObject(Constants.ZKP_KEY_ZKP_A);
|
||||||
e.printStackTrace();
|
if (!theirSignerId.equals(zkpPayload.get(Constants.ZKP_KEY_ID))) {
|
||||||
|
Log.e(LOG_TAG, "Invalid round 2 message: " + jIncoming.toJSONString());
|
||||||
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Extract fields.
|
|
||||||
jParty.otherA = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_A),
|
|
||||||
16);
|
|
||||||
|
|
||||||
ExtendedJSONObject zkpPayload = null;
|
// Extract fields.
|
||||||
try {
|
jParty.otherA = new BigInteger((String) iPayload.get(Constants.ZKP_KEY_A), 16);
|
||||||
zkpPayload = iPayload.getObject(Constants.ZKP_KEY_ZKP_A);
|
|
||||||
} catch (NonObjectJSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
// Extract ZKP.
|
// Extract ZKP.
|
||||||
String gr = (String) zkpPayload.get(Constants.ZKP_KEY_GR);
|
String gr = (String) zkpPayload.get(Constants.ZKP_KEY_GR);
|
||||||
String b = (String) zkpPayload.get(Constants.ZKP_KEY_B);
|
String b = (String) zkpPayload.get(Constants.ZKP_KEY_B);
|
||||||
String id = (String) zkpPayload.get(Constants.ZKP_KEY_ID);
|
String id = (String) zkpPayload.get(Constants.ZKP_KEY_ID);
|
||||||
|
|
||||||
jParty.otherZkpA = new Zkp(new BigInteger(gr, 16), new BigInteger(b, 16),
|
jParty.otherZkpA = new Zkp(new BigInteger(gr, 16), new BigInteger(b, 16), id);
|
||||||
id);
|
|
||||||
|
|
||||||
myKeyBundle = null;
|
myKeyBundle = null;
|
||||||
try {
|
try {
|
||||||
myKeyBundle = JPakeCrypto.finalRound(secret, jParty);
|
myKeyBundle = JPakeCrypto.finalRound(JPakeClient.secretAsBigInteger(secret), jParty);
|
||||||
} catch (IncorrectZkpException e) {
|
} catch (IncorrectZkpException e) {
|
||||||
Log.e(LOG_TAG, "ZKP mismatch");
|
Log.e(LOG_TAG, "ZKP mismatch");
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
e.printStackTrace();
|
return;
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
Log.e(LOG_TAG, "NoSuchAlgorithmException", e);
|
Log.e(LOG_TAG, "NoSuchAlgorithmException", e);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
e.printStackTrace();
|
return;
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
Log.e(LOG_TAG, "InvalidKeyException", e);
|
Log.e(LOG_TAG, "InvalidKeyException", e);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
e.printStackTrace();
|
return;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Log.e(LOG_TAG, "UnsupportedEncodingException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pairWithPin) { // Wait for other device to send verification of keys.
|
if (pairWithPin) { // Wait for other device to send verification of keys.
|
||||||
@ -498,12 +487,10 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Log.e(LOG_TAG, "Failed to encrypt key verification value.", e);
|
Log.e(LOG_TAG, "Failed to encrypt key verification value.", e);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
return;
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
Log.e(LOG_TAG, "Failed to encrypt key verification value.", e);
|
Log.e(LOG_TAG, "Failed to encrypt key verification value.", e);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,13 +510,6 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
Log.d(LOG_TAG, "Encrypting key verification value.");
|
Log.d(LOG_TAG, "Encrypting key verification value.");
|
||||||
// KeyBundle not null
|
// KeyBundle not null
|
||||||
ExtendedJSONObject jPayload = encryptPayload(JPAKE_VERIFY_VALUE, keyBundle);
|
ExtendedJSONObject jPayload = encryptPayload(JPAKE_VERIFY_VALUE, keyBundle);
|
||||||
Log.d(
|
|
||||||
LOG_TAG,
|
|
||||||
"enc key64: "
|
|
||||||
+ new String(Base64.encodeBase64(keyBundle.getEncryptionKey())));
|
|
||||||
Log.e(LOG_TAG,
|
|
||||||
"hmac64: " + new String(Base64.encodeBase64(keyBundle.getHMACKey())));
|
|
||||||
|
|
||||||
ExtendedJSONObject result = new ExtendedJSONObject();
|
ExtendedJSONObject result = new ExtendedJSONObject();
|
||||||
result.put(Constants.JSON_KEY_TYPE, mySignerId + "3");
|
result.put(Constants.JSON_KEY_TYPE, mySignerId + "3");
|
||||||
result.put(Constants.JSON_KEY_VERSION, KEYEXCHANGE_VERSION);
|
result.put(Constants.JSON_KEY_VERSION, KEYEXCHANGE_VERSION);
|
||||||
@ -546,8 +526,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
NonObjectJSONException {
|
NonObjectJSONException {
|
||||||
if (!verificationObject.get(Constants.JSON_KEY_TYPE).equals(
|
if (!verificationObject.get(Constants.JSON_KEY_TYPE).equals(
|
||||||
theirSignerId + "3")) {
|
theirSignerId + "3")) {
|
||||||
Log.e(LOG_TAG,
|
Log.e(LOG_TAG, "Invalid round 3 message: " + verificationObject.toJSONString());
|
||||||
"Invalid round 3 message: " + verificationObject.toJSONString());
|
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -609,9 +588,11 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Log.e(LOG_TAG, "Failed to encrypt data.", e);
|
Log.e(LOG_TAG, "Failed to encrypt data.", e);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
Log.e(LOG_TAG, "Failed to encrypt data.", e);
|
Log.e(LOG_TAG, "Failed to encrypt data.", e);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
jOutgoing = new ExtendedJSONObject();
|
jOutgoing = new ExtendedJSONObject();
|
||||||
jOutgoing.put(Constants.JSON_KEY_TYPE, mySignerId + "3");
|
jOutgoing.put(Constants.JSON_KEY_TYPE, mySignerId + "3");
|
||||||
@ -636,6 +617,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt payload and verify HMAC.
|
// Decrypt payload and verify HMAC.
|
||||||
@ -645,6 +627,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
} catch (NonObjectJSONException e1) {
|
} catch (NonObjectJSONException e1) {
|
||||||
Log.e(LOG_TAG, "Invalid round 3 data.", e1);
|
Log.e(LOG_TAG, "Invalid round 3 data.", e1);
|
||||||
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
abort(Constants.JPAKE_ERROR_WRONGMESSAGE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Log.d(LOG_TAG, "Decrypting data.");
|
Log.d(LOG_TAG, "Decrypting data.");
|
||||||
String cleartext = null;
|
String cleartext = null;
|
||||||
@ -653,9 +636,11 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
} catch (UnsupportedEncodingException e1) {
|
} catch (UnsupportedEncodingException e1) {
|
||||||
Log.e(LOG_TAG, "Failed to decrypt data.", e1);
|
Log.e(LOG_TAG, "Failed to decrypt data.", e1);
|
||||||
abort(Constants.JPAKE_ERROR_INTERNAL);
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
} catch (CryptoException e1) {
|
} catch (CryptoException e1) {
|
||||||
Log.e(LOG_TAG, "Failed to decrypt data.", e1);
|
Log.e(LOG_TAG, "Failed to decrypt data.", e1);
|
||||||
abort(Constants.JPAKE_ERROR_KEYMISMATCH);
|
abort(Constants.JPAKE_ERROR_KEYMISMATCH);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
JSONObject jCreds = null;
|
JSONObject jCreds = null;
|
||||||
try {
|
try {
|
||||||
@ -679,7 +664,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
ssActivity.onComplete(jCreds);
|
ssActivity.onComplete(jCreds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* JpakeRequestDelegate methods */
|
// JPakeRequestDelegate methods.
|
||||||
@Override
|
@Override
|
||||||
public void onRequestFailure(HttpResponse res) {
|
public void onRequestFailure(HttpResponse res) {
|
||||||
JPakeResponse response = new JPakeResponse(res);
|
JPakeResponse response = new JPakeResponse(res);
|
||||||
@ -718,16 +703,14 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
onRequestSuccess(res);
|
onRequestSuccess(res);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(LOG_TAG, "Could not retrieve data. Server responded with HTTP "
|
Log.e(LOG_TAG, "Could not retrieve data. Server responded with HTTP " + statusCode);
|
||||||
+ statusCode);
|
|
||||||
abort(Constants.JPAKE_ERROR_SERVER);
|
abort(Constants.JPAKE_ERROR_SERVER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pollTries = 0;
|
pollTries = 0;
|
||||||
break;
|
break;
|
||||||
case PUT:
|
case PUT:
|
||||||
Log.e(LOG_TAG, "Could not upload data. Server responded with HTTP "
|
Log.e(LOG_TAG, "Could not upload data. Server responded with HTTP " + response.getStatusCode());
|
||||||
+ response.getStatusCode());
|
|
||||||
abort(Constants.JPAKE_ERROR_SERVER);
|
abort(Constants.JPAKE_ERROR_SERVER);
|
||||||
break;
|
break;
|
||||||
case ABORT:
|
case ABORT:
|
||||||
@ -777,7 +760,17 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
|
|
||||||
// Set up next step.
|
// Set up next step.
|
||||||
this.state = State.RCVR_STEP_ONE;
|
this.state = State.RCVR_STEP_ONE;
|
||||||
|
try {
|
||||||
computeStepOne();
|
computeStepOne();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
Log.e(LOG_TAG, "NoSuchAlgorithmException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Log.e(LOG_TAG, "UnsupportedEncodingException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Results from GET request. Continue flow depending on case.
|
// Results from GET request. Continue flow depending on case.
|
||||||
@ -794,8 +787,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
etagHeaders = response.httpResponse().getHeaders("etag");
|
etagHeaders = response.httpResponse().getHeaders("etag");
|
||||||
if (etagHeaders == null) {
|
if (etagHeaders == null) {
|
||||||
try {
|
try {
|
||||||
Log.e(LOG_TAG,
|
Log.e(LOG_TAG, "Server did not supply ETag for message: " + response.body());
|
||||||
"Server did not supply ETag for message: " + response.body());
|
|
||||||
abort(Constants.JPAKE_ERROR_SERVER);
|
abort(Constants.JPAKE_ERROR_SERVER);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -822,16 +814,37 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
Log.d(LOG_TAG, "incoming message: " + jIncoming.toJSONString());
|
Log.d(LOG_TAG, "incoming message: " + jIncoming.toJSONString());
|
||||||
|
|
||||||
if (this.state == State.SNDR_STEP_ZERO) {
|
if (this.state == State.SNDR_STEP_ZERO) {
|
||||||
|
try {
|
||||||
computeStepOne();
|
computeStepOne();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
Log.e(LOG_TAG, "NoSuchAlgorithmException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Log.e(LOG_TAG, "UnsupportedEncodingException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INTERNAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (this.state == State.RCVR_STEP_ONE
|
} else if (this.state == State.RCVR_STEP_ONE
|
||||||
|| this.state == State.SNDR_STEP_ONE) {
|
|| this.state == State.SNDR_STEP_ONE) {
|
||||||
|
try {
|
||||||
computeStepTwo();
|
computeStepTwo();
|
||||||
|
} catch (NonObjectJSONException e) {
|
||||||
|
Log.e(LOG_TAG, "NonObjectJSONException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INVALID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (this.state == State.SNDR_STEP_TWO) {
|
} else if (this.state == State.SNDR_STEP_TWO) {
|
||||||
stateContext = state;
|
stateContext = state;
|
||||||
state = State.PUT;
|
state = State.PUT;
|
||||||
putStep();
|
putStep();
|
||||||
} else if (this.state == State.RCVR_STEP_TWO) {
|
} else if (this.state == State.RCVR_STEP_TWO) {
|
||||||
|
try {
|
||||||
computeFinal();
|
computeFinal();
|
||||||
|
} catch (NonObjectJSONException e) {
|
||||||
|
abort(Constants.JPAKE_ERROR_INVALID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (this.state == State.VERIFY_KEY) {
|
} else if (this.state == State.VERIFY_KEY) {
|
||||||
decryptData(myKeyBundle);
|
decryptData(myKeyBundle);
|
||||||
} else if (this.state == State.VERIFY_PAIRING) {
|
} else if (this.state == State.VERIFY_PAIRING) {
|
||||||
@ -864,11 +877,23 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
ssActivity.onPaired();
|
ssActivity.onPaired();
|
||||||
}
|
}
|
||||||
if (state == State.SNDR_STEP_ONE) {
|
if (state == State.SNDR_STEP_ONE) {
|
||||||
|
try {
|
||||||
computeStepTwo();
|
computeStepTwo();
|
||||||
|
} catch (NonObjectJSONException e) {
|
||||||
|
Log.e(LOG_TAG, "NonObjectJSONException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INVALID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
return; // No need to wait for response from PUT request.
|
return; // No need to wait for response from PUT request.
|
||||||
}
|
}
|
||||||
if (state == State.SNDR_STEP_TWO) {
|
if (state == State.SNDR_STEP_TWO) {
|
||||||
|
try {
|
||||||
computeFinal();
|
computeFinal();
|
||||||
|
} catch (NonObjectJSONException e) {
|
||||||
|
Log.e(LOG_TAG, "NonObjectJSONException", e);
|
||||||
|
abort(Constants.JPAKE_ERROR_INVALID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
return; // No need to wait for response from PUT request.
|
return; // No need to wait for response from PUT request.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,20 +917,20 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
|
|
||||||
/* ResourceDelegate that handles Resource responses */
|
/* ResourceDelegate that handles Resource responses */
|
||||||
public ResourceDelegate makeRequestResourceDelegate() {
|
public ResourceDelegate makeRequestResourceDelegate() {
|
||||||
return new JpakeRequestResourceDelegate(this);
|
return new JPakeRequestResourceDelegate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class JpakeRequestResourceDelegate implements ResourceDelegate {
|
public class JPakeRequestResourceDelegate implements ResourceDelegate {
|
||||||
|
|
||||||
private JPakeRequestDelegate requestDelegate;
|
private JPakeRequestDelegate requestDelegate;
|
||||||
|
|
||||||
public JpakeRequestResourceDelegate(JPakeRequestDelegate delegate) {
|
public JPakeRequestResourceDelegate(JPakeRequestDelegate delegate) {
|
||||||
this.requestDelegate = delegate;
|
this.requestDelegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCredentials() {
|
public String getCredentials() {
|
||||||
// Jpake setup has no credentials
|
// J-PAKE setup has no credentials
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,7 +1088,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
* Generates and sets a clientId for communications with JPAKE setup server.
|
* Generates and sets a clientId for communications with JPAKE setup server.
|
||||||
*/
|
*/
|
||||||
private void setClientId() {
|
private void setClientId() {
|
||||||
byte[] rBytes = generateRandomBytes(JPAKE_LENGTH_CLIENTID / 2);
|
byte[] rBytes = Utils.generateRandomBytes(JPAKE_LENGTH_CLIENTID / 2);
|
||||||
StringBuilder id = new StringBuilder();
|
StringBuilder id = new StringBuilder();
|
||||||
|
|
||||||
for (byte b : rBytes) {
|
for (byte b : rBytes) {
|
||||||
@ -1085,7 +1110,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
String key = "23456789abcdefghijkmnpqrstuvwxyz";
|
String key = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||||
int keylen = key.length();
|
int keylen = key.length();
|
||||||
|
|
||||||
byte[] rBytes = generateRandomBytes(JPAKE_LENGTH_SECRET);
|
byte[] rBytes = Utils.generateRandomBytes(JPAKE_LENGTH_SECRET);
|
||||||
StringBuilder secret = new StringBuilder();
|
StringBuilder secret = new StringBuilder();
|
||||||
for (byte b : rBytes) {
|
for (byte b : rBytes) {
|
||||||
secret.append(key.charAt(Math.abs(b) * keylen / 256));
|
secret.append(key.charAt(Math.abs(b) * keylen / 256));
|
||||||
@ -1133,7 +1158,7 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
try {
|
try {
|
||||||
getRequest = new JPakeRequest(channelUrl, makeRequestResourceDelegate());
|
getRequest = new JPakeRequest(channelUrl, makeRequestResourceDelegate());
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
e.printStackTrace();
|
Log.e(LOG_TAG, "URISyntaxException", e);
|
||||||
abort(Constants.JPAKE_ERROR_CHANNEL);
|
abort(Constants.JPAKE_ERROR_CHANNEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1156,17 +1181,13 @@ public class JPakeClient implements JPakeRequestDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper to generate random bytes
|
* Helper for turning a string secret into a numeric secret.
|
||||||
*
|
|
||||||
* @param length Number of bytes to generate
|
|
||||||
*/
|
*/
|
||||||
private static byte[] generateRandomBytes(int length) {
|
public static BigInteger secretAsBigInteger(String secretString) throws UnsupportedEncodingException {
|
||||||
byte[] bytes = new byte[length];
|
return new BigInteger(secretString.getBytes("UTF-8"));
|
||||||
Random random = new Random(System.nanoTime());
|
|
||||||
random.nextBytes(bytes);
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function to generate a JSON encoded ZKP.
|
* Helper function to generate a JSON encoded ZKP.
|
||||||
*/
|
*/
|
||||||
|
@ -101,8 +101,9 @@ public class JPakeCrypto {
|
|||||||
*
|
*
|
||||||
* @param mySignerId
|
* @param mySignerId
|
||||||
* @param valuesOut
|
* @param valuesOut
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public static void round1(JPakeParty jp, JPakeNumGenerator gen) {
|
public static void round1(JPakeParty jp, JPakeNumGenerator gen) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||||
// Randomly select x1 from [0,q), x2 from [1,q).
|
// Randomly select x1 from [0,q), x2 from [1,q).
|
||||||
BigInteger x1 = gen.generateFromRange(Q); // [0, q)
|
BigInteger x1 = gen.generateFromRange(Q); // [0, q)
|
||||||
BigInteger x2 = jp.x2 = BigInteger.ONE.add(gen.generateFromRange(Q
|
BigInteger x2 = jp.x2 = BigInteger.ONE.add(gen.generateFromRange(Q
|
||||||
@ -132,9 +133,11 @@ public class JPakeCrypto {
|
|||||||
* @param zkp3
|
* @param zkp3
|
||||||
* @param zkp4
|
* @param zkp4
|
||||||
* @throws IncorrectZkpException
|
* @throws IncorrectZkpException
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public static void round2(String secret, JPakeParty jp,
|
public static void round2(BigInteger secretValue, JPakeParty jp, JPakeNumGenerator gen)
|
||||||
JPakeNumGenerator gen) throws IncorrectZkpException, Gx3OrGx4IsZeroOrOneException {
|
throws IncorrectZkpException, NoSuchAlgorithmException,
|
||||||
|
Gx3OrGx4IsZeroOrOneException, UnsupportedEncodingException {
|
||||||
|
|
||||||
Log.d(LOG_TAG, "round2 started.");
|
Log.d(LOG_TAG, "round2 started.");
|
||||||
|
|
||||||
@ -150,13 +153,7 @@ public class JPakeCrypto {
|
|||||||
|
|
||||||
// Compute a = g^[(x1+x3+x4)*(x2*secret)].
|
// Compute a = g^[(x1+x3+x4)*(x2*secret)].
|
||||||
BigInteger y1 = jp.gx3.multiply(jp.gx4).mod(P).multiply(jp.gx1).mod(P);
|
BigInteger y1 = jp.gx3.multiply(jp.gx4).mod(P).multiply(jp.gx1).mod(P);
|
||||||
BigInteger y2 = null;
|
BigInteger y2 = jp.x2.multiply(secretValue).mod(P);
|
||||||
try {
|
|
||||||
y2 = jp.x2.multiply(new BigInteger(secret.getBytes("US-ASCII"))).mod(P);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger a = y1.modPow(y2, P);
|
BigInteger a = y1.modPow(y2, P);
|
||||||
jp.thisZkpA = createZkp(y1, y2, a, jp.signerId, gen);
|
jp.thisZkpA = createZkp(y1, y2, a, jp.signerId, gen);
|
||||||
@ -175,8 +172,8 @@ public class JPakeCrypto {
|
|||||||
* @return KeyBundle
|
* @return KeyBundle
|
||||||
* @throws IncorrectZkpException
|
* @throws IncorrectZkpException
|
||||||
*/
|
*/
|
||||||
public static KeyBundle finalRound(String secret, JPakeParty jp)
|
public static KeyBundle finalRound(BigInteger secretValue, JPakeParty jp)
|
||||||
throws IncorrectZkpException, NoSuchAlgorithmException, InvalidKeyException {
|
throws IncorrectZkpException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
|
||||||
Log.d(LOG_TAG, "Final round started.");
|
Log.d(LOG_TAG, "Final round started.");
|
||||||
BigInteger gb = jp.gx1.multiply(jp.gx2).mod(P).multiply(jp.gx3)
|
BigInteger gb = jp.gx1.multiply(jp.gx2).mod(P).multiply(jp.gx3)
|
||||||
.mod(P);
|
.mod(P);
|
||||||
@ -184,7 +181,7 @@ public class JPakeCrypto {
|
|||||||
|
|
||||||
// Calculate shared key g^(x1+x3)*x2*x4*secret, which is equivalent to
|
// Calculate shared key g^(x1+x3)*x2*x4*secret, which is equivalent to
|
||||||
// (B/g^(x2*x4*s))^x2 = (B*(g^x4)^x2^s^-1)^2.
|
// (B/g^(x2*x4*s))^x2 = (B*(g^x4)^x2^s^-1)^2.
|
||||||
BigInteger k = jp.gx4.modPow(jp.x2.multiply(new BigInteger(secret.getBytes())).negate().mod(Q), P).multiply(jp.otherA)
|
BigInteger k = jp.gx4.modPow(jp.x2.multiply(secretValue).negate().mod(Q), P).multiply(jp.otherA)
|
||||||
.modPow(jp.x2, P);
|
.modPow(jp.x2, P);
|
||||||
|
|
||||||
byte[] enc = new byte[32];
|
byte[] enc = new byte[32];
|
||||||
@ -217,7 +214,7 @@ public class JPakeCrypto {
|
|||||||
* pass in gx to save on an exponentiation of g^x)
|
* pass in gx to save on an exponentiation of g^x)
|
||||||
*/
|
*/
|
||||||
private static Zkp createZkp(BigInteger g, BigInteger x, BigInteger gx,
|
private static Zkp createZkp(BigInteger g, BigInteger x, BigInteger gx,
|
||||||
String id, JPakeNumGenerator gen) {
|
String id, JPakeNumGenerator gen) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||||
// Generate random r for exponent.
|
// Generate random r for exponent.
|
||||||
BigInteger r = gen.generateFromRange(Q);
|
BigInteger r = gen.generateFromRange(Q);
|
||||||
|
|
||||||
@ -238,7 +235,7 @@ public class JPakeCrypto {
|
|||||||
* Verify ZKP.
|
* Verify ZKP.
|
||||||
*/
|
*/
|
||||||
private static void checkZkp(BigInteger g, BigInteger gx, Zkp zkp)
|
private static void checkZkp(BigInteger g, BigInteger gx, Zkp zkp)
|
||||||
throws IncorrectZkpException {
|
throws IncorrectZkpException, NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||||
|
|
||||||
BigInteger h = computeBHash(g, zkp.gr, gx, zkp.id);
|
BigInteger h = computeBHash(g, zkp.gr, gx, zkp.id);
|
||||||
|
|
||||||
@ -278,10 +275,8 @@ public class JPakeCrypto {
|
|||||||
* form hash.
|
* form hash.
|
||||||
*/
|
*/
|
||||||
private static BigInteger computeBHash(BigInteger g, BigInteger gr, BigInteger gx,
|
private static BigInteger computeBHash(BigInteger g, BigInteger gr, BigInteger gx,
|
||||||
String id) {
|
String id) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||||
MessageDigest sha = null;
|
MessageDigest sha = MessageDigest.getInstance("SHA-256");
|
||||||
try {
|
|
||||||
sha = MessageDigest.getInstance("SHA-256");
|
|
||||||
sha.reset();
|
sha.reset();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -291,20 +286,11 @@ public class JPakeCrypto {
|
|||||||
* item with its byte length, but I've omitted that here.
|
* item with its byte length, but I've omitted that here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
hashByteArrayWithLength(sha,
|
hashByteArrayWithLength(sha, BigIntegerHelper.BigIntegerToByteArrayWithoutSign(g));
|
||||||
BigIntegerHelper.BigIntegerToByteArrayWithoutSign(g));
|
hashByteArrayWithLength(sha, BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gr));
|
||||||
hashByteArrayWithLength(sha,
|
hashByteArrayWithLength(sha, BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gx));
|
||||||
BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gr));
|
hashByteArrayWithLength(sha, id.getBytes("UTF-8"));
|
||||||
hashByteArrayWithLength(sha,
|
|
||||||
BigIntegerHelper.BigIntegerToByteArrayWithoutSign(gx));
|
|
||||||
hashByteArrayWithLength(sha, id.getBytes("US-ASCII"));
|
|
||||||
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
byte[] hash = sha.digest();
|
byte[] hash = sha.digest();
|
||||||
|
|
||||||
return BigIntegerHelper.ByteArrayToBigIntegerWithoutSign(hash);
|
return BigIntegerHelper.ByteArrayToBigIntegerWithoutSign(hash);
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
package org.mozilla.gecko.sync.jpake;
|
package org.mozilla.gecko.sync.jpake;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
import org.mozilla.gecko.sync.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper Function to generate a uniformly random value in [0, r).
|
* Helper Function to generate a uniformly random value in [0, r).
|
||||||
@ -47,14 +48,6 @@ public class JPakeNumGeneratorRandom implements JPakeNumGenerator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigInteger generateFromRange(BigInteger r) {
|
public BigInteger generateFromRange(BigInteger r) {
|
||||||
int maxBytes = (int) Math.ceil(((double) r.bitLength()) / 8);
|
return Utils.generateBigIntegerLessThan(r);
|
||||||
|
|
||||||
byte[] bytes = new byte[maxBytes];
|
|
||||||
new SecureRandom().nextBytes(bytes);
|
|
||||||
BigInteger randInt = new BigInteger(bytes);
|
|
||||||
// TODO: is this going to be very slow?
|
|
||||||
// bit shifting/masking to decrease mod computation
|
|
||||||
return randInt.mod(r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
|
|||||||
final String authority,
|
final String authority,
|
||||||
final ContentProviderClient provider,
|
final ContentProviderClient provider,
|
||||||
final SyncResult syncResult) {
|
final SyncResult syncResult) {
|
||||||
|
Utils.reseedSharedRandom(); // Make sure we don't work with the same random seed for too long.
|
||||||
|
|
||||||
long delay = delayMilliseconds();
|
long delay = delayMilliseconds();
|
||||||
if (delay > 0) {
|
if (delay > 0) {
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user