A framework for collecting and viewing graphical browser fingerprints.
JavaScript Ruby CSS
Switch branches/tags
Nothing to show
Failed to load latest commit information.
mt_config Change defaults to not point at my server May 22, 2012
scripts now calculates distribution entropy for groups May 16, 2012
static Fix ActiveRecord method deprecation issues Sep 2, 2014
.gitignore Sinatra/ActiveRecord/jQuery playing together nicely Feb 3, 2012
README.md Fix ActiveRecord method deprecation issues Sep 2, 2014
compare.rb Fix ActiveRecord method deprecation issues Sep 2, 2014
config.ru Added page-ready notification to diffs.haml Feb 29, 2012
experiments.rb Fix ActiveRecord method deprecation issues Sep 2, 2014
index.db Fixed the single-submission workflow Jun 28, 2012
list_results.haml actually commit the list views Feb 8, 2012
model.rb Fixed the single-submission workflow Jun 28, 2012
print_table.rb Added extra cleanup work to print_table May 16, 2012


Canvas Fingerprinting

This is a small webapp to facilitate collecting <canvas>-based fingerprints from many disparate users, as well as view and group the resulting images.

Quick Start

  1. Install dependencies:

    gem install activerecord sinatra sinatra-contrib json sqlite3 thin haml facets rmagick

  2. Start Sinatra:

    ruby compare.rb

  3. Visit localhost:4567.


Currently, index.db contains the anonymized results of our experiments on Mechanical Turk. We collected data from 300 users for the tests canvas_text_arial, canvas_text_arial_px, canvas_text_webfont, canvas_text_webfont_px, canvas_text_nonsense, and webgl-teapot experiments.

If you want an empty database, delete index.db and run ./scripts/make_db.rb.

If you run a Mechanical Turk experiment, you'll need to reimport the data that your workers uploaded to Amazon. Due to the large size of the PNGs, Mechanical Turk's data export tools fail to work. As a workaround, we provide ./scripts/import_results_html.rb. To use this script, first navigate to the "Approved" tab in the "Review HIT" section of the Mechanical Turk Requester site. Next, save this page to disk as an HTML file. (You may need to do this multiple times, due to pagination). Finally, run the import script and pass in all the saved HTML files. When you next start the server, your MT data will be available for viewing.

Adding a New Experiment

  1. Create a new directory under /static/experiments/. Let's call ours foo.

  2. Create the file /static/experiments/foo/run.js:

    registerExperiment("foo", function(name, canvasid) {
       var canvas = document.getElementById(canvasid);
       // draw something on this canvas
       // ...
       fillForm(name, canvas);

    This hooks your experiment into the client-side collection framework, which handles extracting pixel data, encoding, and passing the results back to the server. As an added bonus, this allows your experiment to coexist peacefully alongside other fingerprinting experiments on the same page.

  3. Now, we need to tell Sinatra about the new experiment. Create /static/experiments/foo/exp.rb:

    foo = Experiment.where(name: 'foo').first_or_create
    foo.name = "foo"
    foo.canvas_size = {:width => 415, :height => 30}
    foo.scripts = ["/experiments/foo/run.js"]
    foo.links = []
    foo.mt = true

    These few lines characterize this experiment and its dependencies. Any elements in scripts will be included via <script> tags in the resulting output. links is similar, but requires a hash characterizing the link, which will be placed in the document's <head> (e.g. foo.links = [ {:href=>"http://fonts.googleapis.com/css?family=Lusitana", :rel=>'stylesheet', :type=>"text/css"} ]). mt indicates if this experiment should be included in Mechanical Turk mode.

    Upon startup, the server will check for and execute code in any Ruby files under /static, so we don't need to register this experiment anywhere else.

  4. Restart the Sinatra server. Your new experiment should now happily exist.

Running on Amazon Mechanical Turk

Mechanical Turk mode allows you to quickly run a number of <canvas> fingerprints from a single page, as well as collect alternate form data from the Mechanical Turk worker. Any experiment whose mt parameter is true will be included, although the results are not shown to the user being fingerprinted.

This mode is accessed at http://yourserver/mt.

1. Set up a Thin server

Run $ thin --debug --rackup config.ru start -p 4567. config.ru disables the X-Frame HTTP header, which allows Mechanical Turk to frame your survey in their worker UI.

Test your server by going to http://yourserver:4567/mt.

2. Configure Mechanical Turk

Edit the js_hit.properties and js_hit.question files in /mt_config/. Refer to the Amazon Mechanical Turk documentation for the proper options. Make sure that your server's URL is in js_hit.question.

Next, edit views/mt.haml to point to the appropriate endpoint. Uncomment the endpoint you'd like to target: local, sandbox, or live. Local will submit results back to your local server; sandbox allows you to test against the MT sandbox; live is what you'll use during actual surveying.

3. Load your experiment into Mechanical Turk

Acquire the Mechanical Turk command line tools and run something like this:

$ cd ~/src/aws-mturk-clt-1.3.0/bin/
$ ./loadHITs.sh -maxhits 5 -input ~/src/canvas-fingerprinting/mt_config/js_hit.input -question ~/src/canvas-fingerprinting/mt_config/js_hit.question -question ~/src/canvas-fingerprinting/mt_config/js_hit.question  -properties mturk.properties

Refer to the Mechanical Turk documentation for setup and configuration of the command line tools and for further instructions on this step.


I seem to remember adding a feature to MT mode whereby the mechanical turk worker will post their results back to me before sending them to Amazon, thus skipping the annoying HTML import method. This should be working. You'll need to enter your server's address in /views/mt.haml, though. There should probably be a switch for this.