def change_password(self, oldpwd, newpwd): stretched_oldpwd = quick_stretch_password(self.email, oldpwd) resp = self.start_password_change(stretched_oldpwd) keys = self.fetch_keys(resp["keyFetchToken"], stretched_oldpwd) token = resp["passwordChangeToken"] stretched_newpwd = quick_stretch_password(self.email, newpwd) new_wrapkb = xor(keys[1], derive_key(stretched_newpwd, "unwrapBkey")) self.finish_password_change(token, stretched_newpwd, new_wrapkb)
def change_password(self, oldpwd, newpwd): stretched_oldpwd = quick_stretch_password(self.email, oldpwd) resp = self.start_password_change(stretched_oldpwd) keys = self.fetch_keys(resp["keyFetchToken"], stretched_oldpwd) token = resp["passwordChangeToken"] stretched_newpwd = quick_stretch_password(self.email, newpwd) new_wrapkb = xor(keys[1], derive_key(stretched_newpwd, "unwrapBkey")) self.finish_password_change(token, stretched_newpwd, new_wrapkb)
def test_password_stretching_and_key_derivation(self): # These are the test vectors from the onepw protocol document. email = "andr\[email protected]" self.assertEqual( email.encode("utf8"), dehexlify(""" 616e6472c3a94065 78616d706c652e6f 7267 """)) pwd = "p\xe4ssw\xf6rd" self.assertEqual( pwd.encode("utf8"), dehexlify(""" 70c3a4737377c3b6 7264 """)) qspwd = quick_stretch_password(email, pwd) self.assertEqual( qspwd, dehexlify(""" e4e8889bd8bd61ad 6de6b95c059d56e7 b50dacdaf62bd846 44af7e2add84345d """)) authpw = derive_key(qspwd, "authPW") self.assertEqual( authpw, dehexlify(""" 247b675ffb4c4631 0bc87e26d712153a be5e1c90ef00a478 4594f97ef54f2375 """)) ubkey = derive_key(qspwd, "unwrapBkey") self.assertEqual( ubkey, dehexlify(""" de6a2648b78284fc b9ffa81ba9580330 9cfba7af583c01a8 a1a63e567234dd28 """))
def _get_stretched_password(self, email, password=None, stretchpwd=None): if password is not None: if stretchpwd is not None: msg = "must specify exactly one of 'password' or 'stretchpwd'" raise ValueError(msg) stretchpwd = quick_stretch_password(email, password) elif stretchpwd is None: raise ValueError("must specify one of 'password' or 'stretchpwd'") return stretchpwd
def _get_stretched_password(self, email, password=None, stretchpwd=None): if password is not None: if stretchpwd is not None: msg = "must specify exactly one of 'password' or 'stretchpwd'" raise ValueError(msg) stretchpwd = quick_stretch_password(email, password) elif stretchpwd is None: raise ValueError("must specify one of 'password' or 'stretchpwd'") return stretchpwd
def test_change_password(self): # Change the password. newpwd = mutate_one_byte(DUMMY_PASSWORD) self.stretchpwd = quick_stretch_password(self.acct.email, newpwd) self.session.change_password(DUMMY_PASSWORD, newpwd) # Check that we can use the new password. session2 = self.client.login(self.acct.email, newpwd, keys=True) # Check that encryption keys have been preserved. session2.fetch_keys() self.assertEquals(self.session.keys, session2.keys)
def test_change_password(self): # Change the password. newpwd = mutate_one_byte(DUMMY_PASSWORD) self.stretchpwd = quick_stretch_password(self.acct.email, newpwd) self.session.change_password(DUMMY_PASSWORD, newpwd) # Check that we can use the new password. session2 = self.client.login(self.acct.email, newpwd, keys=True) # Check that encryption keys have been preserved. session2.fetch_keys() self.assertEquals(self.session.keys, session2.keys)
def tearDown(self): for acct in self._accounts_to_delete: acct.clear() try: stretchpwd = acct.stretchpwd except AttributeError: try: password = acct.password stretchpwd = quick_stretch_password(acct.email, password) except AttributeError: stretchpwd = DUMMY_STRETCHED_PASSWORD self.client.destroy_account(acct.email, stretchpwd=stretchpwd)
def tearDown(self): for acct in self._accounts_to_delete: acct.clear() try: stretchpwd = acct.stretchpwd except AttributeError: try: password = acct.password stretchpwd = quick_stretch_password(acct.email, password) except AttributeError: stretchpwd = DUMMY_STRETCHED_PASSWORD self.client.destroy_account(acct.email, stretchpwd=stretchpwd)
def __get_session_bulk_keys(self): """ Get session decrypt keys @return keys as (b"", b"") """ if self.__session is None: self.__session = FxASession( self.__mozilla_sync.fxa_client, self.__username, quick_stretch_password(self.__username, self.__password), self.__uid, self.__token) self.__session.keys = [b"", self.__keyB] self.__session.check_session_status() bid_assertion, key = self.__mozilla_sync.get_browserid_assertion( self.__session) bulk_keys = self.__mozilla_sync.connect(bid_assertion, key) return bulk_keys
def get_client_and_key(username, password): fxa_client = FxAClient() pickle_filename = username + '.pickle' prev_session = None try: prev_session = pickle.load(open(pickle_filename, 'rb')) except Exception: pass if prev_session: session = FxASession(fxa_client, username, quick_stretch_password(username, password), prev_session.uid, prev_session.token) session.keys = prev_session.keys session.check_session_status() else: session = fxa_client.login(username, password, keys=True) session.fetch_keys() pickle.dump(session, open(pickle_filename, 'wb')) bid_assertion_args = get_browserid_assertion(session) client = SyncClient(*bid_assertion_args) sync_keys = KeyBundle.fromMasterKey( session.keys[1], b"identity.mozilla.com/picl/v1/oldsync") # Fetch the sync bundle keys out of storage. # They're encrypted with the account-level key. keys = decrypt_payload(client.get_record('crypto', 'keys')['payload'], sync_keys) # There's some provision for using separate key bundles # for separate collections # but I haven't bothered digging through to see what that's about because # it doesn't seem to be in use, at least on my account. if keys["collections"]: raise RuntimeError("no support for per-collection key bundles") bulk_keys = KeyBundle(base64.b64decode(keys["default"][0]), base64.b64decode(keys["default"][1])) return (client, bulk_keys)
def test_change_password(self): # Change the password. newpwd = mutate_one_byte(DUMMY_PASSWORD) self.stretchpwd = quick_stretch_password(self.acct.email, newpwd) self.session.change_password(DUMMY_PASSWORD, newpwd) # Check that we can use the new password. session2 = self.client.login(self.acct.email, newpwd, keys=True) if not session2.get_email_status().get("verified"): def has_verify_code(m): return "x-verify-code" in m["headers"] m = self.acct.wait_for_email(has_verify_code) if not m: raise RuntimeError("Verification email was not received") self.acct.clear() session2.verify_email_code(m["headers"]["x-verify-code"]) # Check that encryption keys have been preserved. session2.fetch_keys() self.assertEquals(self.session.keys, session2.keys)
def test_change_password(self): # Change the password. newpwd = mutate_one_byte(DUMMY_PASSWORD) self.stretchpwd = quick_stretch_password(self.acct.email, newpwd) self.session.change_password(DUMMY_PASSWORD, newpwd) # Check that we can use the new password. session2 = self.client.login(self.acct.email, newpwd, keys=True) if not session2.get_email_status().get("verified"): def has_verify_code(m): return "x-verify-code" in m["headers"] m = self.acct.wait_for_email(has_verify_code) if not m: raise RuntimeError("Verification email was not received") self.acct.clear() session2.verify_email_code(m["headers"]["x-verify-code"]) # Check that encryption keys have been preserved. session2.fetch_keys() self.assertEquals(self.session.keys, session2.keys)
def test_password_stretching_and_key_derivation(self): # These are the test vectors from the onepw protocol document. email = u"andr\[email protected]" self.assertEqual(email.encode("utf8"), dehexlify(""" 616e6472c3a94065 78616d706c652e6f 7267 """)) pwd = u"p\xe4ssw\xf6rd" self.assertEqual(pwd.encode("utf8"), dehexlify(""" 70c3a4737377c3b6 7264 """)) qspwd = quick_stretch_password(email, pwd) self.assertEqual(qspwd, dehexlify(""" e4e8889bd8bd61ad 6de6b95c059d56e7 b50dacdaf62bd846 44af7e2add84345d """)) authpw = derive_key(qspwd, "authPW") self.assertEqual(authpw, dehexlify(""" 247b675ffb4c4631 0bc87e26d712153a be5e1c90ef00a478 4594f97ef54f2375 """)) ubkey = derive_key(qspwd, "unwrapBkey") self.assertEqual(ubkey, dehexlify(""" de6a2648b78284fc b9ffa81ba9580330 9cfba7af583c01a8 a1a63e567234dd28 """))
def setUp(self): self.client = Client(self.server_url) # Create a fresh testing account. self.acct = TestEmailAccount() self.stretchpwd = quick_stretch_password( self.acct.email, DUMMY_PASSWORD, ) self.session = self.client.create_account( email=self.acct.email, stretchpwd=self.stretchpwd, keys=True, ) # Verify the account so that we can actually use the session. m = self.acct.wait_for_email(lambda m: "x-verify-code" in m["headers"]) if not m: raise RuntimeError("Verification email was not received") self.session.verify_email_code(m["headers"]["x-verify-code"]) # Fetch the keys. self.session.fetch_keys() self.assertEqual(len(self.session.keys), 2) self.assertEqual(len(self.session.keys[0]), 32) self.assertEqual(len(self.session.keys[1]), 32)
def setUp(self): self.client = Client(self.server_url) # Create a fresh testing account. self.acct = TestEmailAccount() self.stretchpwd = quick_stretch_password( self.acct.email, DUMMY_PASSWORD, ) self.session = self.client.create_account( email=self.acct.email, stretchpwd=self.stretchpwd, keys=True, ) # Verify the account so that we can actually use the session. m = self.acct.wait_for_email(lambda m: "x-verify-code" in m["headers"]) if not m: raise RuntimeError("Verification email was not received") self.session.verify_email_code(m["headers"]["x-verify-code"]) # Fetch the keys. self.session.fetch_keys() self.assertEqual(len(self.session.keys), 2) self.assertEqual(len(self.session.keys[0]), 32) self.assertEqual(len(self.session.keys[1]), 32)
def test_dummy_credentials(self): qspwd = quick_stretch_password(DUMMY_EMAIL, DUMMY_PASSWORD) self.assertEqual(qspwd, DUMMY_STRETCHED_PASSWORD)