def upload_passwords_data(passdata, assertion, kB): """ Upload the passdata passwords to the Firefox Account :param passdata: The list of formated Firefox compatible password data :param assertion: :param kB: :return: """ # Connect to sync. xcs = hexlify(hashlib.sha256(kB).digest()[:16]) client = SyncClient(assertion, xcs) # Fetch /crypto/keys. raw_sync_key = fxa.crypto.derive_key(kB, "oldsync", 64) root_key_bundle = KeyBundle( raw_sync_key[:32], raw_sync_key[32:], ) keys_bso = client.get_record("crypto", "keys") keys = root_key_bundle.decrypt_bso(keys_bso) default_key_bundle = KeyBundle( base64.b64decode(keys["default"][0]), base64.b64decode(keys["default"][1]), ) for data in tqdm(passdata): encrypted_data = default_key_bundle.encrypt_bso(data) assert default_key_bundle.decrypt_bso(encrypted_data) == data client.put_record("passwords", encrypted_data) logging.debug("Synced password records: %d" % len(client.get_records("passwords"))) logging.info("Done!")
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)