mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Bug 1240919 - Part 2: Cull more client v1 code. r=rnewman
--HG-- extra : commitid : E7CbKng8xVK extra : rebase_source : 5da5f88d34a8e34993a93b925b2f6a3b39678b0f
This commit is contained in:
parent
f6a7d4a9a4
commit
d6d1fb59c0
@ -781,8 +781,6 @@ sync_java_files = [TOPSRCDIR + '/mobile/android/services/src/main/java/org/mozil
|
||||
'background/common/telemetry/TelemetryWrapper.java',
|
||||
'background/db/CursorDumper.java',
|
||||
'background/db/Tab.java',
|
||||
'background/fxa/FxAccount10AuthDelegate.java',
|
||||
'background/fxa/FxAccount10CreateDelegate.java',
|
||||
'background/fxa/FxAccount20CreateDelegate.java',
|
||||
'background/fxa/FxAccount20LoginDelegate.java',
|
||||
'background/fxa/FxAccountClient.java',
|
||||
|
@ -1,218 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.background.fxa;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.net.SRPConstants;
|
||||
|
||||
public class FxAccount10AuthDelegate implements FxAccountClient10.AuthDelegate {
|
||||
// Fixed by protocol.
|
||||
protected final BigInteger N;
|
||||
protected final BigInteger g;
|
||||
protected final int modNLengthBytes;
|
||||
|
||||
// Configured at construction time.
|
||||
protected final String email;
|
||||
protected final byte[] stretchedPWBytes;
|
||||
|
||||
// Encapsulate state.
|
||||
protected static class AuthState {
|
||||
protected String srpToken;
|
||||
protected String mainSalt;
|
||||
protected String srpSalt;
|
||||
|
||||
protected BigInteger x;
|
||||
protected BigInteger A;
|
||||
protected byte[] Kbytes;
|
||||
protected byte[] Mbytes;
|
||||
}
|
||||
|
||||
// State should be written exactly once.
|
||||
protected AuthState internalAuthState = null;
|
||||
|
||||
public FxAccount10AuthDelegate(String email, byte[] stretchedPWBytes) {
|
||||
this.email = email;
|
||||
this.stretchedPWBytes = stretchedPWBytes;
|
||||
this.N = SRPConstants._2048.N;
|
||||
this.g = SRPConstants._2048.g;
|
||||
this.modNLengthBytes = SRPConstants._2048.byteLength;
|
||||
}
|
||||
|
||||
protected BigInteger generateSecretValue() {
|
||||
return Utils.generateBigIntegerLessThan(N);
|
||||
}
|
||||
|
||||
public static class FxAccountClientMalformedAuthException extends FxAccountClientException {
|
||||
private static final long serialVersionUID = 3585262174699395505L;
|
||||
|
||||
public FxAccountClientMalformedAuthException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONObject getAuthStartBody() throws FxAccountClientException {
|
||||
try {
|
||||
final JSONObject body = new JSONObject();
|
||||
body.put("email", FxAccountUtils.bytes(email));
|
||||
return body;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new FxAccountClientException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthStartResponse(final ExtendedJSONObject body) throws FxAccountClientException {
|
||||
if (this.internalAuthState != null) {
|
||||
throw new FxAccountClientException("auth must not be written before calling onAuthStartResponse");
|
||||
}
|
||||
|
||||
String srpToken = null;
|
||||
String srpSalt = null;
|
||||
String srpB = null;
|
||||
String mainSalt = null;
|
||||
|
||||
try {
|
||||
srpToken = body.getString("srpToken");
|
||||
if (srpToken == null) {
|
||||
throw new FxAccountClientMalformedAuthException("srpToken must be a non-null object");
|
||||
}
|
||||
ExtendedJSONObject srp = body.getObject("srp");
|
||||
if (srp == null) {
|
||||
throw new FxAccountClientMalformedAuthException("srp must be a non-null object");
|
||||
}
|
||||
srpSalt = srp.getString("salt");
|
||||
if (srpSalt == null) {
|
||||
throw new FxAccountClientMalformedAuthException("srp.salt must not be null");
|
||||
}
|
||||
srpB = srp.getString("B");
|
||||
if (srpB == null) {
|
||||
throw new FxAccountClientMalformedAuthException("srp.B must not be null");
|
||||
}
|
||||
ExtendedJSONObject passwordStretching = body.getObject("passwordStretching");
|
||||
if (passwordStretching == null) {
|
||||
throw new FxAccountClientMalformedAuthException("passwordStretching must be a non-null object");
|
||||
}
|
||||
mainSalt = passwordStretching.getString("salt");
|
||||
if (mainSalt == null) {
|
||||
throw new FxAccountClientMalformedAuthException("srp.passwordStretching.salt must not be null");
|
||||
}
|
||||
throwIfParametersAreBad(passwordStretching);
|
||||
|
||||
this.internalAuthState = authStateFromParameters(srpToken, mainSalt, srpSalt, srpB, generateSecretValue());
|
||||
} catch (FxAccountClientException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new FxAccountClientException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect object like:
|
||||
* "passwordStretching": {
|
||||
* "type": "PBKDF2/scrypt/PBKDF2/v1",
|
||||
* "PBKDF2_rounds_1": 20000,
|
||||
* "scrypt_N": 65536,
|
||||
* "scrypt_r": 8,
|
||||
* "scrypt_p": 1,
|
||||
* "PBKDF2_rounds_2": 20000,
|
||||
* "salt": "996bc6b1aa63cd69856a2ec81cbf19d5c8a604713362df9ee15c2bf07128efab"
|
||||
* }
|
||||
* @param params to verify.
|
||||
* @throws FxAccountClientMalformedAuthException
|
||||
*/
|
||||
protected void throwIfParametersAreBad(ExtendedJSONObject params) throws FxAccountClientMalformedAuthException {
|
||||
if (params == null ||
|
||||
params.size() != 7 ||
|
||||
params.getString("salt") == null ||
|
||||
!("PBKDF2/scrypt/PBKDF2/v1".equals(params.getString("type"))) ||
|
||||
20000 != params.getLong("PBKDF2_rounds_1") ||
|
||||
65536 != params.getLong("scrypt_N") ||
|
||||
8 != params.getLong("scrypt_r") ||
|
||||
1 != params.getLong("scrypt_p") ||
|
||||
20000 != params.getLong("PBKDF2_rounds_2")) {
|
||||
throw new FxAccountClientMalformedAuthException("malformed passwordStretching parameters: '" + params.toJSONString() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All state is written in this method.
|
||||
*/
|
||||
protected AuthState authStateFromParameters(String srpToken, String mainSalt, String srpSalt, String srpB, BigInteger a) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
AuthState authState = new AuthState();
|
||||
authState.srpToken = srpToken;
|
||||
authState.mainSalt = mainSalt;
|
||||
authState.srpSalt = srpSalt;
|
||||
|
||||
authState.x = FxAccountUtils.srpVerifierLowercaseX(email.getBytes("UTF-8"), this.stretchedPWBytes, Utils.hex2Byte(srpSalt, FxAccountUtils.SALT_LENGTH_BYTES));
|
||||
|
||||
authState.A = g.modPow(a, N);
|
||||
String srpA = FxAccountUtils.hexModN(authState.A, N);
|
||||
BigInteger B = new BigInteger(srpB, 16);
|
||||
|
||||
byte[] srpABytes = Utils.hex2Byte(srpA, modNLengthBytes);
|
||||
byte[] srpBBytes = Utils.hex2Byte(srpB, modNLengthBytes);
|
||||
|
||||
// u = H(pad(A) | pad(B))
|
||||
byte[] uBytes = Utils.sha256(Utils.concatAll(
|
||||
srpABytes,
|
||||
srpBBytes));
|
||||
BigInteger u = new BigInteger(Utils.byte2Hex(uBytes, FxAccountUtils.HASH_LENGTH_HEX), 16);
|
||||
|
||||
// S = (B - k*g^x)^(a u*x) % N
|
||||
// k = H(pad(N) | pad(g))
|
||||
int byteLength = (N.bitLength() + 7) / 8;
|
||||
byte[] kBytes = Utils.sha256(Utils.concatAll(
|
||||
Utils.hex2Byte(N.toString(16), byteLength),
|
||||
Utils.hex2Byte(g.toString(16), byteLength)));
|
||||
BigInteger k = new BigInteger(Utils.byte2Hex(kBytes, FxAccountUtils.HASH_LENGTH_HEX), 16);
|
||||
|
||||
BigInteger base = B.subtract(k.multiply(g.modPow(authState.x, N)).mod(N)).mod(N);
|
||||
BigInteger pow = a.add(u.multiply(authState.x));
|
||||
BigInteger S = base.modPow(pow, N);
|
||||
String srpS = FxAccountUtils.hexModN(S, N);
|
||||
|
||||
byte[] sBytes = Utils.hex2Byte(srpS, modNLengthBytes);
|
||||
|
||||
// M = H(pad(A) | pad(B) | pad(S))
|
||||
authState.Mbytes = Utils.sha256(Utils.concatAll(
|
||||
srpABytes,
|
||||
srpBBytes,
|
||||
sBytes));
|
||||
|
||||
// K = H(pad(S))
|
||||
authState.Kbytes = Utils.sha256(sBytes);
|
||||
|
||||
return authState;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONObject getAuthFinishBody() throws FxAccountClientException {
|
||||
if (internalAuthState == null) {
|
||||
throw new FxAccountClientException("auth must be successfully written before calling getAuthFinishBody.");
|
||||
}
|
||||
JSONObject body = new JSONObject();
|
||||
body.put("srpToken", internalAuthState.srpToken);
|
||||
body.put("A", FxAccountUtils.hexModN(internalAuthState.A, N));
|
||||
body.put("M", Utils.byte2Hex(internalAuthState.Mbytes, FxAccountUtils.HASH_LENGTH_HEX));
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getSharedBytes() throws FxAccountClientException {
|
||||
if (internalAuthState == null) {
|
||||
throw new FxAccountClientException("auth must be successfully finished before calling getSharedBytes.");
|
||||
}
|
||||
return internalAuthState.Kbytes;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.background.fxa;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient10.CreateDelegate;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.net.SRPConstants;
|
||||
|
||||
public class FxAccount10CreateDelegate implements CreateDelegate {
|
||||
protected final String email;
|
||||
protected final String mainSalt;
|
||||
protected final String srpSalt;
|
||||
protected final BigInteger v;
|
||||
|
||||
public FxAccount10CreateDelegate(String email, byte[] stretchedPWBytes, String mainSalt, String srpSalt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
this.email = email;
|
||||
this.mainSalt = mainSalt;
|
||||
this.srpSalt = srpSalt;
|
||||
byte[] srpSaltBytes = Utils.hex2Byte(srpSalt, FxAccountUtils.SALT_LENGTH_BYTES);
|
||||
this.v = FxAccountUtils.srpVerifierLowercaseV(email.getBytes("UTF-8"), stretchedPWBytes, srpSaltBytes, SRPConstants._2048.g, SRPConstants._2048.N);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONObject getCreateBody() throws FxAccountClientException {
|
||||
final JSONObject body = new JSONObject();
|
||||
try {
|
||||
body.put("email", FxAccountUtils.bytes(email));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new FxAccountClientException(e);
|
||||
}
|
||||
|
||||
final JSONObject stretching = new JSONObject();
|
||||
stretching.put("type", "PBKDF2/scrypt/PBKDF2/v1");
|
||||
stretching.put("PBKDF2_rounds_1", 20000);
|
||||
stretching.put("scrypt_N", 65536);
|
||||
stretching.put("scrypt_r", 8);
|
||||
stretching.put("scrypt_p", 1);
|
||||
stretching.put("PBKDF2_rounds_2", 20000);
|
||||
stretching.put("salt", mainSalt);
|
||||
body.put("passwordStretching", stretching);
|
||||
|
||||
final JSONObject srp = new JSONObject();
|
||||
srp.put("type", "SRP-6a/SHA256/2048/v1");
|
||||
srp.put("verifier", FxAccountUtils.hexModN(v, SRPConstants._2048.N));
|
||||
srp.put("salt", srpSalt);
|
||||
body.put("srp", srp);
|
||||
return body;
|
||||
}
|
||||
}
|
@ -4,14 +4,13 @@
|
||||
|
||||
package org.mozilla.gecko.background.fxa;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient10.CreateDelegate;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
public class FxAccount20CreateDelegate implements CreateDelegate {
|
||||
public class FxAccount20CreateDelegate {
|
||||
protected final byte[] emailUTF8;
|
||||
protected final byte[] authPW;
|
||||
protected final boolean preVerified;
|
||||
@ -36,7 +35,6 @@ public class FxAccount20CreateDelegate implements CreateDelegate {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONObject getCreateBody() throws FxAccountClientException {
|
||||
final JSONObject body = new JSONObject();
|
||||
try {
|
||||
|
@ -8,14 +8,13 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient10.CreateDelegate;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
/**
|
||||
* An abstraction around providing an email and authorization token to the auth
|
||||
* server.
|
||||
*/
|
||||
public class FxAccount20LoginDelegate implements CreateDelegate {
|
||||
public class FxAccount20LoginDelegate {
|
||||
protected final byte[] emailUTF8;
|
||||
protected final byte[] authPW;
|
||||
|
||||
@ -25,7 +24,6 @@ public class FxAccount20LoginDelegate implements CreateDelegate {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONObject getCreateBody() throws FxAccountClientException {
|
||||
final JSONObject body = new JSONObject();
|
||||
try {
|
||||
|
@ -154,25 +154,6 @@ public class FxAccountClient10 {
|
||||
public void handleSuccess(T result);
|
||||
}
|
||||
|
||||
/**
|
||||
* A <code>CreateDelegate</code> produces the body of a /create request.
|
||||
*/
|
||||
public interface CreateDelegate {
|
||||
public JSONObject getCreateBody() throws FxAccountClientException;
|
||||
}
|
||||
|
||||
/**
|
||||
* A <code>AuthDelegate</code> produces the bodies of an /auth/{start,finish}
|
||||
* request pair and exposes state generated by a successful response.
|
||||
*/
|
||||
public interface AuthDelegate {
|
||||
public JSONObject getAuthStartBody() throws FxAccountClientException;
|
||||
public void onAuthStartResponse(ExtendedJSONObject body) throws FxAccountClientException;
|
||||
public JSONObject getAuthFinishBody() throws FxAccountClientException;
|
||||
|
||||
public byte[] getSharedBytes() throws FxAccountClientException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thin container for two cryptographic keys.
|
||||
*/
|
||||
@ -364,142 +345,6 @@ public class FxAccountClient10 {
|
||||
throw new FxAccountClientRemoteException(response, code, errno, error, message, info, body);
|
||||
}
|
||||
|
||||
public void createAccount(final String email, final byte[] stretchedPWBytes,
|
||||
final String srpSalt, final String mainSalt,
|
||||
final RequestDelegate<String> delegate) {
|
||||
try {
|
||||
createAccount(new FxAccount10CreateDelegate(email, stretchedPWBytes, srpSalt, mainSalt), delegate);
|
||||
} catch (final Exception e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected void createAccount(final CreateDelegate createDelegate, final RequestDelegate<String> delegate) {
|
||||
JSONObject body = null;
|
||||
try {
|
||||
body = createDelegate.getCreateBody();
|
||||
} catch (FxAccountClientException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
BaseResource resource;
|
||||
try {
|
||||
resource = getBaseResource("account/create");
|
||||
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
resource.delegate = new ResourceDelegate<String>(resource, delegate) {
|
||||
@Override
|
||||
public void handleSuccess(int status, HttpResponse response, ExtendedJSONObject body) {
|
||||
String uid = body.getString("uid");
|
||||
if (uid == null) {
|
||||
delegate.handleError(new FxAccountClientException("uid must be a non-null string"));
|
||||
return;
|
||||
}
|
||||
delegate.handleSuccess(uid);
|
||||
}
|
||||
};
|
||||
post(resource, body, delegate);
|
||||
}
|
||||
|
||||
protected void authStart(final AuthDelegate authDelegate, final RequestDelegate<AuthDelegate> delegate) {
|
||||
JSONObject body;
|
||||
try {
|
||||
body = authDelegate.getAuthStartBody();
|
||||
} catch (FxAccountClientException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
BaseResource resource;
|
||||
try {
|
||||
resource = getBaseResource("auth/start");
|
||||
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
resource.delegate = new ResourceDelegate<AuthDelegate>(resource, delegate) {
|
||||
@Override
|
||||
public void handleSuccess(int status, HttpResponse response, ExtendedJSONObject body) {
|
||||
try {
|
||||
authDelegate.onAuthStartResponse(body);
|
||||
delegate.handleSuccess(authDelegate);
|
||||
} catch (Exception e) {
|
||||
delegate.handleError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
post(resource, body, delegate);
|
||||
}
|
||||
|
||||
protected void authFinish(final AuthDelegate authDelegate, RequestDelegate<byte[]> delegate) {
|
||||
JSONObject body;
|
||||
try {
|
||||
body = authDelegate.getAuthFinishBody();
|
||||
} catch (FxAccountClientException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
BaseResource resource;
|
||||
try {
|
||||
resource = getBaseResource("auth/finish");
|
||||
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
resource.delegate = new ResourceDelegate<byte[]>(resource, delegate) {
|
||||
@Override
|
||||
public void handleSuccess(int status, HttpResponse response, ExtendedJSONObject body) {
|
||||
try {
|
||||
byte[] authToken = new byte[32];
|
||||
unbundleBody(body, authDelegate.getSharedBytes(), FxAccountUtils.KW("auth/finish"), authToken);
|
||||
delegate.handleSuccess(authToken);
|
||||
} catch (Exception e) {
|
||||
delegate.handleError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
post(resource, body, delegate);
|
||||
}
|
||||
|
||||
public void login(final String email, final byte[] stretchedPWBytes, final RequestDelegate<byte[]> delegate) {
|
||||
login(new FxAccount10AuthDelegate(email, stretchedPWBytes), delegate);
|
||||
}
|
||||
|
||||
protected void login(final AuthDelegate authDelegate, final RequestDelegate<byte[]> delegate) {
|
||||
authStart(authDelegate, new RequestDelegate<AuthDelegate>() {
|
||||
@Override
|
||||
public void handleSuccess(AuthDelegate srpSession) {
|
||||
authFinish(srpSession, delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(final Exception e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(final FxAccountClientRemoteException e) {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delegate.handleFailure(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't call this directly. Use <code>unbundleBody</code> instead.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user