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!")
Exemple #2
0
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)