diff --git a/browserid/static/dialog/resources/browserid-identities.js b/browserid/static/dialog/resources/browserid-identities.js
index f902a72dd2939b33c5680d8b4f4a01566b3da72c..2430e84b241d0b96d167e8c167e86b76bfff0c8e 100644
--- a/browserid/static/dialog/resources/browserid-identities.js
+++ b/browserid/static/dialog/resources/browserid-identities.js
@@ -93,7 +93,7 @@ BrowserID.Identities = (function() {
     $('body')[func]('authenticated');
 
     if (!authenticated) {
-      storage.clearEmails();
+      storage.clear();
     }
   }
 
@@ -591,7 +591,7 @@ BrowserID.Identities = (function() {
      * @method clearStoredEmailKeypairs
      */
     clearStoredEmailKeypairs: function() {
-      storage.clearEmails();
+      storage.clear();
     },
 
 
diff --git a/browserid/static/dialog/resources/storage.js b/browserid/static/dialog/resources/storage.js
index 1a42ffa1749bbce52e72bc4ad43ffa90a0f74702..809f912a404b44e6590fd4c0d8f73552cae6247f 100644
--- a/browserid/static/dialog/resources/storage.js
+++ b/browserid/static/dialog/resources/storage.js
@@ -47,8 +47,12 @@ BrowserID.Storage = (function() {
     window.localStorage.emails = JSON.stringify(emails);
   }
 
-  function clearEmails() {
+  function clear() {
     storeEmails({});
+    var localStorage = window.localStorage;
+    localStorage.removeItem("tempKeypair");
+    localStorage.removeItem("stagedOnBehalfOf");
+    localStorage.removeItem("sitesToEmail");
   }
 
   function getEmails() {
@@ -60,10 +64,16 @@ BrowserID.Storage = (function() {
     }
     
     // if we had a problem parsing or the emails are null
-    clearEmails();
+    clear();
     return {};
   }
 
+  function getEmail(email) {
+    var ids = getEmails();
+
+    return ids && ids[email];
+  }
+
   function addEmail(email, obj) {
     var emails = getEmails();
     emails[email] = obj;
@@ -72,18 +82,35 @@ BrowserID.Storage = (function() {
 
   function removeEmail(email) {
     var emails = getEmails();
-    delete emails[email];
-    storeEmails(emails);
+    if(emails[email]) {
+      delete emails[email];
+      storeEmails(emails);
+
+      // remove any sites associated with this email address.
+      var sitesToEmail = JSON.parse(localStorage.sitesToEmail || "{}");
+      for(var site in sitesToEmail) {
+        if(sitesToEmail[site] === email) {
+          delete sitesToEmail[site];
+        }
+      }
+      localStorage.sitesToEmail = JSON.stringify(sitesToEmail);
+    }
+    else {
+      throw "unknown email address";
+    }
   }
 
   function invalidateEmail(email) {
-    var id = getEmails()[email];
+    var id = getEmail(email);
     if (id) {
       delete id.priv;
       delete id.pub;
       delete id.cert;
       addEmail(email, id);
     }
+    else {
+      throw "unknown email address";
+    }
   }
 
   function storeTemporaryKeypair(keypair) {
@@ -133,12 +160,73 @@ BrowserID.Storage = (function() {
     return origin;
   }
 
+  function setSiteEmail(site, email) {
+    if(getEmail(email)) {
+      var localStorage = window.localStorage;
+
+      var sitesToEmail = JSON.parse(localStorage.sitesToEmail || "{}");
+      sitesToEmail[site] = email;
+
+      localStorage.sitesToEmail = JSON.stringify(sitesToEmail);
+    }
+    else {
+      throw "unknown email address";
+    }
+  }
+
+  function getSiteEmail(site) {
+    var sitesToEmail = JSON.parse(localStorage.sitesToEmail || "{}");
+    return sitesToEmail[site];
+  }
+
   return {
-    getEmails: getEmails,
+    /**
+     * Add an email address and optional key pair.
+     * @method addEmail
+     */
     addEmail: addEmail,
+    /**
+     * Get all email addresses and their associated key pairs
+     * @method getEmails
+     */
+    getEmails: getEmails,
+    /**
+     * Get one email address and its key pair, if found.  Returns undefined if 
+     * not found.
+     * @method getEmail
+     */
+    getEmail: getEmail,
+    /**
+     * Remove an email address, its key pairs, and any sites associated with 
+     * email address.
+     * @throws "unknown email address" if email address is not known.
+     * @method removeEmail
+     */
     removeEmail: removeEmail,
+    /**
+     * Remove the key information for an email address.
+     * @throws "unknown email address" if email address is not known.
+     * @method invalidateEmail
+     */
     invalidateEmail: invalidateEmail,
-    clearEmails: clearEmails,
+    /**
+     * Set the associated email address for a site
+     * @throws "uknown email address" if the email address is not known.
+     * @method setSiteEmail
+     */
+    setSiteEmail: setSiteEmail,
+    /**
+     * Get the associated email address for a site, if known.  If not known, 
+     * return undefined.
+     * @method getSiteEmail
+     */
+    getSiteEmail: getSiteEmail,
+    /**
+     * Clear all stored data - email addresses, key pairs, temporary key pairs, 
+     * site/email associations.
+     * @method clear
+     */
+    clear: clear,
     storeTemporaryKeypair: storeTemporaryKeypair,
     retrieveTemporaryKeypair: retrieveTemporaryKeypair,
     setStagedOnBehalfOf: setStagedOnBehalfOf,
diff --git a/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js b/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js
index 50be6a8b48e2a723b129a131920e1e6a32be8079..2487d06272719e391a93f09fbe6541dfe3904b8c 100644
--- a/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js
+++ b/browserid/static/dialog/test/qunit/browserid-identities_unit_test.js
@@ -375,7 +375,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   test("authenticateAndSync with valid authentication", function() {
     credentialsValid = true;
     keyRefresh = ["testuser@testuser.com"]; 
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
 
     lib.authenticateAndSync("testuser@testuser.com", "testuser", function() {
     }, function(authenticated) {
@@ -393,7 +393,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   test("authenticateAndSync with invalid authentication", function() {
     credentialsValid = false;
     keyRefresh = ["testuser@testuser.com"]; 
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
 
     lib.authenticateAndSync("testuser@testuser.com", "testuser", function() {
     }, function(authenticated) {
@@ -444,7 +444,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncEmailKeypair with successful sync", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
 
     syncValid = true;
     lib.syncEmailKeypair("testemail@testemail.com", function(keypair) {
@@ -459,7 +459,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncEmailKeypair with invalid sync", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
 
     syncValid = false;
     lib.syncEmailKeypair("testemail@testemail.com", function(keypair) {
@@ -556,7 +556,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("removeEmail that is not added", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
 
     lib.removeEmail("testemail@testemail.com", function() {
       var identities = lib.getStoredEmailKeypairs();
@@ -570,7 +570,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncEmails with no pre-loaded identities and no identities to add", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     userEmails = {};
 
     lib.syncEmails(function onSuccess() {
@@ -584,7 +584,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   });
 
   test("syncEmails with no pre-loaded identities and identities to add", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     userEmails = {"testuser@testuser.com": {}};
 
     lib.syncEmails(function onSuccess() {
@@ -598,7 +598,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   });
 
   test("syncEmails with identities preloaded and none to add", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     userEmails = {"testuser@testuser.com": {}};
     storage.addEmail("testuser@testuser.com", {});
     lib.syncEmails(function onSuccess() {
@@ -613,7 +613,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncEmails with identities preloaded and one to add", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     storage.addEmail("testuser@testuser.com", {pubkey: pubkey, cert: random_cert});
     userEmails = {"testuser@testuser.com": {pubkey: pubkey, cert: random_cert},
                   "testuser2@testuser.com": {pubkey: pubkey, cert: random_cert}};
@@ -631,7 +631,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("syncEmails with identities preloaded and one to remove", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     storage.addEmail("testuser@testuser.com", {pub: pubkey, cert: random_cert});
     storage.addEmail("testuser2@testuser.com", {pub: pubkey, cert: random_cert});
     userEmails = {"testuser@testuser.com":  { pub: pubkey, cert: random_cert}};
@@ -649,7 +649,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("getAssertion with known email that has key", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     var keypair = jwk.KeyPair.generate("RS",64);
     lib.certifyEmailKeypair("testuser@testuser.com", keypair, function() {
       lib.getAssertion("testuser@testuser.com", function onSuccess(assertion) {
@@ -663,7 +663,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("getAssertion with known email that does not have a key", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     lib.persistEmail("testuser@testuser.com", function() {
       lib.getAssertion("testuser@testuser.com", function onSuccess(assertion) {
         equal("string", typeof assertion, "we have an assertion!");
@@ -676,7 +676,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
 
 
   test("getAssertion with unknown email", function() {
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
     var keypair = jwk.KeyPair.generate("RS",64);
     lib.certifyEmailKeypair("testuser@testuser.com", keypair, function() {
       lib.getAssertion("testuser2@testuser.com", function onSuccess(assertion) {
@@ -691,7 +691,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid-iden
   test("logoutUser", function(onSuccess) {
     credentialsValid = true;
     keyRefresh = ["testuser@testuser.com"]; 
-    storage.clearEmails();
+    lib.clearStoredEmailKeypairs();
 
     lib.authenticateAndSync("testuser@testuser.com", "testuser", function() {
     }, function(authenticated) {
diff --git a/browserid/static/dialog/test/qunit/storage_unit_test.js b/browserid/static/dialog/test/qunit/storage_unit_test.js
index 2c2f3c2d63564ec0bc83c5a10a122b4fc73d3aa2..305239e3422861f6ac9cfcb2998d2a3189b562f2 100644
--- a/browserid/static/dialog/test/qunit/storage_unit_test.js
+++ b/browserid/static/dialog/test/qunit/storage_unit_test.js
@@ -39,11 +39,11 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/storage", func
 
   module("BrowserID.Storage", {
     setup: function() {
-      storage.clearEmails();
+      storage.clear();
     },
 
     teardown: function() {
-      storage.clearEmails();
+      storage.clear();
     }
   });
 
@@ -54,14 +54,16 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/storage", func
     equal(_.size(emails), 0, "object should be empty");
   });
 
-  test("addEmail, getEmails", function() {
+  test("addEmail, getEmails, getEmail", function() {
     storage.addEmail("testuser@testuser.com", {priv: "key"});
 
     var emails = storage.getEmails();
     equal(_.size(emails), 1, "object should have one item");
     ok("testuser@testuser.com" in emails, "added email address is there");
-  });
 
+    var id = storage.getEmail("testuser@testuser.com");
+    equal("key", id.priv, "email that was added is retrieved");
+  });
 
   test("removeEmail, getEmails", function() {
     storage.addEmail("testuser@testuser.com", {priv: "key"});
@@ -71,25 +73,90 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/storage", func
     equal(_.size(emails), 0, "object should have no items");
   });
 
+  test("removeEmail with invalid address", function() {
+    var error;
+    try {
+      storage.removeEmail("testuser@testuser.com");
+    }
+    catch(e) {
+      error = e;
+    }
+    equal(error.toString(), "unknown email address", "removing an unknown email address");
+  });
+
 
-  test("clearEmails", function() {
+  test("clear", function() {
     storage.addEmail("testuser@testuser.com", {priv: "key"});
-    storage.clearEmails();
+    storage.clear();
 
     var emails = storage.getEmails();
     equal(_.size(emails), 0, "object should have no items");
   });
 
-  test("invalidateEmail", function() {
+  test("invalidateEmail with valid email address", function() {
     storage.addEmail("testuser@testuser.com", {priv: "key", pub: "pub", cert: "cert"});
 
     storage.invalidateEmail("testuser@testuser.com");
-    var id = storage.getEmails()["testuser@testuser.com"];
+    var id = storage.getEmail("testuser@testuser.com");
     ok(id && !("priv" in id), "private key was removed");
     ok(id && !("pub" in id), "public key was removed");
     ok(id && !("cert" in id), "cert was removed");
   });
 
+  test("invalidateEmail with invalid email address", function() {
+    var error;
+    try {
+      storage.invalidateEmail("testuser@testuser.com");
+    }
+    catch(e) {
+      error = e;
+    }
+    equal(error.toString(), "unknown email address", "Invalidating an unknown email address");
+  });
+
+  test("getSiteEmail with site not found", function() {
+    var email = storage.getSiteEmail("www.testsite.com");
+
+    equal(typeof email, "undefined", "if site not found, returned undefined");
+  });
+
+  test("setSiteEmail with email that is not known about", function() {
+    var error;
+    try {
+      storage.setSiteEmail("www.testsite.com", "testuser@testuser.com");
+    } catch(e) {
+      error = e; 
+    }
+    
+    equal(error.toString(), "unknown email address", "An unknown email address was added");
+  });
+
+  test("setSiteEmail with valid email", function() {
+    storage.addEmail("testuser@testuser.com", {});
+    storage.setSiteEmail("www.testsite.com", "testuser@testuser.com");
+    var email = storage.getSiteEmail("www.testsite.com");
+
+    equal(email, "testuser@testuser.com", "set/get have the same email for the site");
+  });
+
+  test("removeEmail after setSiteEmail removes site", function() {
+    storage.addEmail("testuser@testuser.com", {});
+    storage.setSiteEmail("www.testsite.com", "testuser@testuser.com");
+    storage.removeEmail("testuser@testuser.com");
+    var email = storage.getSiteEmail("www.testsite.com");
+
+    equal(typeof email, "undefined", "after removing an email address, email for site is no longer available");
+  });
+
+  test("clear clears site email info", function() {
+    storage.addEmail("testuser@testuser.com", {});
+    storage.setSiteEmail("www.testsite.com", "testuser@testuser.com");
+    storage.clear();
+    var email = storage.getSiteEmail("www.testsite.com");
+
+    equal(typeof email, "undefined", "after clearing, site email is not found");
+  });
+
   test("storeTemporaryKeypair", function() {
     // XXX needs a test
   });