not-webusb

Crates.ionot-webusb
lib.rsnot-webusb
version0.1.2
created_at2025-07-20 11:34:04.569329+00
updated_at2025-07-28 12:02:05.068423+00
descriptionCommunicate between a webpage and a usb device without webusb
homepage
repositoryhttps://github.com/rukai/not-webusb-rs
max_upload_size
id1761002
size161,136
Lucas Kent (rukai)

documentation

README

not-webUSB

Crates.io Docs

An alternative to webUSB for simple usecases with better browser support and the ability to restrict which sites can access the device.

Usage follows a request/response model where the browser JS or wasm sends a request to which the device must send exactly 1 response.

The goal is to be a production ready library for use in real devices. However, while it works fine for simple use cases, it needs more scrutiny and testing before I would be comfortable using it in production.

not-webusb consists of:

  • A usb-device class implementation that runs on your microcontroller
  • Client code for talking to the microcontroller from a website.

Use cases

  • not-webusb is well suited for occasional one time operations, with small amounts of data. e.g. flashing key mappings for a keyboard
  • Sending large amounts of data is possible but very slow. e.g. firmware updates
  • Constant live communication with a device is possible, but poorly suited due to flashing alerts. e.g. reading sensor data

Browser support

Unlike webusb which supports only chrome and edge. not-webusb supports all major browsers, having been tested on:

  • Firefox (Linux + Windows + Android)
  • Chrome (Linux + Windows + Android)
  • Edge
  • Safari Desktop (sometimes gets stuck)

Downsides

Far slower than webusb since it has to go through a lot of overhead with the U2F protocol. For example, to round trip 5kB of data it takes the following on different browsers:

  • linux chrome ~9s
  • linux firefox ~13s

Also, most browsers flash the entire window with an alert every time a not-webusb transfer occurs.

Expand for GIF of the flashing window on chrome on linux

Demonstration of flashing box on chrome

However, on firefox, only a small non-fullscreen box appears instead.

How does it work though???

not-webusb is built on top of U2F (the legacy part of FIDO) the protocol for security keys. However instead of implementing a security key, not-webusb smuggles data through the application_parameter and signature fields of the Authenticate messages sent between the browser and the device. This is a fundamental part of the protocol and cannot be removed by browsers without rendering large numbers of currently working security keys unusable.

The idea comes from the I Cant Believe Its Not WebUSB demo, which uses the same fields to control an LED from the browser.

Examples

With a debugger+pico connected, and probe-rs installed, the examples can be run by one of:

and then following the instructions on the page.

Cargo Features

  • defmt - enable defmt logging

Running integration tests

Install system deps:

# TODO: confirm which are really needed
sudo apt install ninja-build mercurial python-is-python3 g++-14 libudev-dev

Flash the rot13 example firmware to a pico and then run cargo test.

Future work

  • Make protocol implementation more robust
    • transaction timeout
    • Remove all possible panic paths
    • Improve handling with an actual FIDO key plugged in at the same time.
  • Internal cleanup
    • Better separate U2F vs CTAP vs user data layers
  • more batteries
    • I would love for this project to have a recommended webusb implementation of the fido client protocol, allowing browsers with webusb support to avoid the "touch your security key" pop ups, while keeping fido as a fallback protocol. I have no immediate plans to implement this however.
    • rust wasm implementation of the browser side logic
Commit count: 0

cargo fmt