mobile/android/base/fxa/login/Married.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 package org.mozilla.gecko.fxa.login;
michael@0 6
michael@0 7 import java.io.IOException;
michael@0 8 import java.io.UnsupportedEncodingException;
michael@0 9 import java.security.GeneralSecurityException;
michael@0 10 import java.security.InvalidKeyException;
michael@0 11 import java.security.NoSuchAlgorithmException;
michael@0 12 import java.util.ArrayList;
michael@0 13 import java.util.Collections;
michael@0 14 import java.util.HashMap;
michael@0 15
michael@0 16 import org.json.simple.parser.ParseException;
michael@0 17 import org.mozilla.gecko.background.fxa.FxAccountUtils;
michael@0 18 import org.mozilla.gecko.browserid.BrowserIDKeyPair;
michael@0 19 import org.mozilla.gecko.browserid.JSONWebTokenUtils;
michael@0 20 import org.mozilla.gecko.fxa.FxAccountConstants;
michael@0 21 import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate;
michael@0 22 import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.LogMessage;
michael@0 23 import org.mozilla.gecko.sync.ExtendedJSONObject;
michael@0 24 import org.mozilla.gecko.sync.NonObjectJSONException;
michael@0 25 import org.mozilla.gecko.sync.Utils;
michael@0 26 import org.mozilla.gecko.sync.crypto.KeyBundle;
michael@0 27
michael@0 28 public class Married extends TokensAndKeysState {
michael@0 29 private static final String LOG_TAG = Married.class.getSimpleName();
michael@0 30
michael@0 31 protected final String certificate;
michael@0 32 protected final String clientState;
michael@0 33
michael@0 34 public Married(String email, String uid, byte[] sessionToken, byte[] kA, byte[] kB, BrowserIDKeyPair keyPair, String certificate) {
michael@0 35 super(StateLabel.Married, email, uid, sessionToken, kA, kB, keyPair);
michael@0 36 Utils.throwIfNull(certificate);
michael@0 37 this.certificate = certificate;
michael@0 38 try {
michael@0 39 this.clientState = FxAccountUtils.computeClientState(kB);
michael@0 40 } catch (NoSuchAlgorithmException e) {
michael@0 41 // This should never occur.
michael@0 42 throw new IllegalStateException("Unable to compute client state from kB.");
michael@0 43 }
michael@0 44 }
michael@0 45
michael@0 46 @Override
michael@0 47 public ExtendedJSONObject toJSONObject() {
michael@0 48 ExtendedJSONObject o = super.toJSONObject();
michael@0 49 // Fields are non-null by constructor.
michael@0 50 o.put("certificate", certificate);
michael@0 51 return o;
michael@0 52 }
michael@0 53
michael@0 54 @Override
michael@0 55 public void execute(final ExecuteDelegate delegate) {
michael@0 56 delegate.handleTransition(new LogMessage("staying married"), this);
michael@0 57 }
michael@0 58
michael@0 59 public String generateAssertion(String audience, String issuer) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
michael@0 60 // We generate assertions with no iat and an exp after 2050 to avoid
michael@0 61 // invalid-timestamp errors from the token server.
michael@0 62 final long expiresAt = JSONWebTokenUtils.DEFAULT_FUTURE_EXPIRES_AT_IN_MILLISECONDS;
michael@0 63 String assertion = JSONWebTokenUtils.createAssertion(keyPair.getPrivate(), certificate, audience, issuer, null, expiresAt);
michael@0 64 if (!FxAccountConstants.LOG_PERSONAL_INFORMATION) {
michael@0 65 return assertion;
michael@0 66 }
michael@0 67
michael@0 68 try {
michael@0 69 FxAccountConstants.pii(LOG_TAG, "Generated assertion: " + assertion);
michael@0 70 ExtendedJSONObject a = JSONWebTokenUtils.parseAssertion(assertion);
michael@0 71 if (a != null) {
michael@0 72 FxAccountConstants.pii(LOG_TAG, "aHeader : " + a.getObject("header"));
michael@0 73 FxAccountConstants.pii(LOG_TAG, "aPayload : " + a.getObject("payload"));
michael@0 74 FxAccountConstants.pii(LOG_TAG, "aSignature: " + a.getString("signature"));
michael@0 75 String certificate = a.getString("certificate");
michael@0 76 if (certificate != null) {
michael@0 77 ExtendedJSONObject c = JSONWebTokenUtils.parseCertificate(certificate);
michael@0 78 FxAccountConstants.pii(LOG_TAG, "cHeader : " + c.getObject("header"));
michael@0 79 FxAccountConstants.pii(LOG_TAG, "cPayload : " + c.getObject("payload"));
michael@0 80 FxAccountConstants.pii(LOG_TAG, "cSignature: " + c.getString("signature"));
michael@0 81 // Print the relevant timestamps in sorted order with labels.
michael@0 82 HashMap<Long, String> map = new HashMap<Long, String>();
michael@0 83 map.put(a.getObject("payload").getLong("iat"), "aiat");
michael@0 84 map.put(a.getObject("payload").getLong("exp"), "aexp");
michael@0 85 map.put(c.getObject("payload").getLong("iat"), "ciat");
michael@0 86 map.put(c.getObject("payload").getLong("exp"), "cexp");
michael@0 87 ArrayList<Long> values = new ArrayList<Long>(map.keySet());
michael@0 88 Collections.sort(values);
michael@0 89 for (Long value : values) {
michael@0 90 FxAccountConstants.pii(LOG_TAG, map.get(value) + ": " + value);
michael@0 91 }
michael@0 92 } else {
michael@0 93 FxAccountConstants.pii(LOG_TAG, "Could not parse certificate!");
michael@0 94 }
michael@0 95 } else {
michael@0 96 FxAccountConstants.pii(LOG_TAG, "Could not parse assertion!");
michael@0 97 }
michael@0 98 } catch (Exception e) {
michael@0 99 FxAccountConstants.pii(LOG_TAG, "Got exception dumping assertion debug info.");
michael@0 100 }
michael@0 101 return assertion;
michael@0 102 }
michael@0 103
michael@0 104 public KeyBundle getSyncKeyBundle() throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
michael@0 105 // TODO Document this choice for deriving from kB.
michael@0 106 return FxAccountUtils.generateSyncKeyBundle(kB);
michael@0 107 }
michael@0 108
michael@0 109 public String getClientState() {
michael@0 110 if (FxAccountConstants.LOG_PERSONAL_INFORMATION) {
michael@0 111 FxAccountConstants.pii(LOG_TAG, "Client state: " + this.clientState);
michael@0 112 }
michael@0 113 return this.clientState;
michael@0 114 }
michael@0 115
michael@0 116 public State makeCohabitingState() {
michael@0 117 return new Cohabiting(email, uid, sessionToken, kA, kB, keyPair);
michael@0 118 }
michael@0 119 }

mercurial