Home > Uncategorized > Parsing U2F Registration Data in #Javascript

Parsing U2F Registration Data in #Javascript


Following on from yesterday’s post, today, I’m taking U2F one step further, by parsing the returned data in Javascript.

If you want to just skip to the code; here is the repo on GitHub: https://github.com/infiniteloopltd/U2FJS

A high level overview of what is happening here, is that the u2f.register function call returns an object, a property of which is registrationData, which is a Web-Safe Base64 string, that encodes the raw FIDO data, as a byte array.

First, a quick seque – a web-safe base64 string is just a base64 string with the forward-slashes (/) converted to underscores (_) and plusses (+) converted to dashes (-), and any trailing equals (=) removed. It’s important to note the difference, because the standard (atob and btoa functions will fail if you don’t account for this)

In Javascript, the first challenge is to convert a Web-Safe Base64 array into a Uint8Array array, which is much easier to handle, when you are doing byte-operations.

So here’s the code;

_Base64ToArrayBuffer : function (base64) {
base64 = base64.replace(/_/g, ‘/’).replace(/-/g, ‘+’); // web safe
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
return bytes;
_ArrayBufferToBase64 : function (arrayBuffer) {
var dView = new Uint8Array(arrayBuffer);
var arr = Array.prototype.slice.call(dView);
var arr1 = arr.map(function(item){
return String.fromCharCode(item);
var b64 = window.btoa(arr1.join(”));
return b64.replace(/\+/g, ‘-‘).replace(/\//g, ‘_’).replace(/=+$/, ”);

Now, we need to look at FIDO’s documentation on the raw message format to see what the data contains, here are the docs;


The parts of the registrationData that we are interested in are;

  • reserved byte [1 byte], which for legacy reasons has the value 0x05.
  • user public key [65 bytes]. This is the (uncompressed) x,y-representation of a curve point on the P-256 NIST elliptic curve.
  • key handle length byte [1 byte], which specifies the length of the key handle (see below). The value is unsigned (range 0-255).
  • key handle [length specified in previous field]. This a handle that allows the U2F token to identify the generated key pair. U2F tokens may wrap the generated private key and the application id it was generated for, and output that as the key handle.

There is very little validation done in the javascript, but we are trusting the U2F API to return un-tampered data.

So, we parse it as follows

var bRegData = U2FRegistration._Base64ToArrayBuffer(registrationData);
throw “Reserved byte is incorrect”;
U2FRegistration.userPublicKey = U2FRegistration._ArrayBufferToBase64(bRegData.slice(1,66));
U2FRegistration.keyHandleLength = bRegData[66];
U2FRegistration.keyHandle = U2FRegistration._ArrayBufferToBase64(bRegData.slice(67,U2FRegistration.keyHandleLength+67));

The Attestation certificate and signature are not captured from the data, since we are trusting the data to be valid.

Going back to our U2F registration code, we callout to U2FRegistration.parse after registration;

let registerRequest = {
challenge: ‘RegisterChallenge’,
version: ‘U2F_V2’
u2f.register(‘https://localhost&#8217;, [registerRequest], [],
(response) => {

The next step will be signing, in which we will use the KeyHandle above. But that’s for another day.


Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: