Skip to content

trezor-graveyard/trezor-chrome-extension

Repository files navigation

TREZOR Chrome Extension

Build Status gitter

Chrome extension for Bitcoin TREZOR by SatoshiLabs.

About

TREZOR Chrome Extension has two different purposes.

First, it has a built-in device management functionality, for wiping/recovery/initialization/.... It doesn't connect to any outside sources, all the data (including TREZOR firmware) is bundled with the app, so it works completely offline (if you somehow manage to install Chrome without an internet connection).

Second, it's a transport layer between websites (such as our own webwallet TREZOR Wallet) and TREZOR devices. It's possible to send Chrome messages (see chrome messages API documentation) to the extension, and the extension resends it to TREZOR hardware and back.

The messages are encoded through protobuf.js library and sent to the actual hardware via Chrome USB HID API.

The API of the extensions is described below. For development of web apps for TREZOR, it is recommended to use trezor.js javascript API, which has separate javascript calls for most common usecases; or TREZOR Connect, which is even more high level. However, the end user still needs to install either the extension or trezord.

Install via Web store

Extension is available for download at Google Web store (and is automatically offered on webwallet TREZOR Wallet).

Install via ZIP

If you don't trust Google Web store (or want to use an offline machine), you can download the ZIP file extension.zip, unzip it, go to chrome://extensions/ in Chrome, enable "Developer mode", click "Load upacked extension" and find the directory.

The ZIP file in the repo will be updated simultaneously with the updates in Google Web Store; it might not be up-to-date with the master branch.

Install from source

Checking out sources

git clone --recursive https://github.com/trezor/chrome-extension.git

Or, if you already cloned the repository but not the submodules

git submodule update --init --recursive

Building

Building works on OS X and Linux and uses make.

You need to have flow installed for type checking. If you don't want to install it, edit the flow-check in Makefile to something like true.

You also need python3 and npm and have them in $PATH.

(You need to be online for the build because of npm install and git update that happen in the build.)

make npm-install # needed only the first time
make clear # if you built before
make zip

Source

The source code of the transport layer is using flow type annotations and some features of ECMAScript 6.

Most of the logic is now in trezor-link npm package, the extension just do data validation and so on.

The source code of the device management is an angular app. If it seems a little "over-blown", it's because it was created as a clone of the whole myTREZOR app, which handles more than device management, and then functionality was stripped off.

Caveats

On Mac OS X, Windows and Chrome OS, installing the extension should work without any root privileges. Unfortunately, on GNU/Linux, you have install so-called udev rules as a root.

If you are using wallet.trezor.io, we are trying to detect the errors and offer you an easy package for the two most popular packaging systems (DEB and RPM).

If you don't want to or can't install that, please refer to our documentation

http://doc.satoshilabs.com/trezor-user/settingupchromeonlinux.html

UDP connection

Connect to UDP TREZOR emulator (will be released soon-ish) by opening extension background page in chrome://extensions and typing into console

window.setUdp([21324, ...])

with the list of ports of the virtual devices. The devices are immediately added and are registered as connected; if an app (like myTREZOR) is running, it will see them and try to communicate with them. To simulate disconnect, just type

window.setUdp([])

and the device are marked as disconnected.

Allowed ports are 21324, 21325 and 21326.

Note: there is a known bug - if you set up UDP connection, but turn off the emulator, the HID device listing might get stuck on webpage reloads. If you notice this, set wuindow.setUdp([]) or turn on the emulator.

API

If installed using some of the described methods, the extension has an id jcjjhjgimijdkoamemaghajlhegmoclj.

You send the messages to the extension using chrome messages API (read the note about whitelisting below).

The messages are javacript Objects with type property and body property; type is always string, body varies depending on the type.

The response is a javascript Object with type property, which is either "response" or "error"; in the response case, the object has body with type depending on message; in the error case, the object has message with error message.

So, the code, communicating with the extension, might look like this:

chrome.runtime.sendMessage('jcjjhjgimijdkoamemaghajlhegmoclj', {type: "info"},
  function(response) {
    if (response.type === "error") {
      handleError(response.type);
    } else {
      handleInfo(response.body);
    }
  }
);

The possible messages are:

type body response type description
info {version: string,
configured: boolean}
Returns current version of bridge and info about configuration.
See configure for more info.
configure config, as hex string "Success" Before any advanced call, configuration file needs to be loaded to extension.
Configuration file is signed by SatoshiLabs and the validity of the signature is limited.
Current config should be in this repo, or on AWS here.
enumerate Array<{path: number,
session: number | null}>
Lists devices.
path uniquely defines device between more connected devices. It usually increases on reconnect until restart of browser, but there is no guarantee.
If session is null, nobody else is using the device; if it's number, it identifies who is using it.
listen previous, as JSON like enumerate Listen to changes and returns either on change or after 30 second timeout. Compares change from previous that is sent as a parameter. "Change" is both connecting/disconnecting and session change.

previous must be exactly the output from the previous enumerate, even if the devices have additional properties that are not described above
acquire {path: path of device,
previous: previous session (or null)
{session: number} Acquires the device at path. By "acquiring" the device, you are claiming the device for yourself.
Before acquiring, checks that the current session is previous.
If two applications call acquire on a newly connected device at the same time, only one of them succeed.
release {session: session to release} "Success" Releases the device with the given session.
By "releasing" the device, you claim that you don't want to use the device anymore.
call {id: session to call,
type: string,
message: object}
{type: string, body: object} Calls the message and returns the response from TREZOR.
Messages are defined in this protobuf file.
type in request is, for example, GetFeatures; type in response is, for example, Features

Whitelisting

You cannot connect to the extension from anywhere on the internet. Your URL needs to be specifically whitelisted; whitelist is baked-in in the extension manifest.

localhost is specifically whitelisted, so you can experiment on http://localhost. If you want to add your url in order to make a TREZOR web app, make a pull request to this file.

License

GPLv3

some code from sowbug/trhid and throughnothing/chrome-trezor