Reliable, Secure and Universal Backup for U2F Token

I really love the security level U2F provides, but together with security, we have to think carefully about the backup and recovery plan. It would totally suck to get locked out of my accounts if something happens with my U2F token. At the same time, it doesn't make sense to have a backup which compromises U2F security.

The advice I've seen in many places is that the best practice is having a second U2F token for backup, which should be manually added to every service and which should be kept in some “safe” place. And another common practice is to have some non-U2F method as a backup (OTP, or recovery codes, etc). Well, both of those leave a lot to be desired, honestly.

Let's talk about the first option, the “best” one: having a backup token.

Separate U2F token for backup

Having a second token means that whenever I register on a new service, I have to add both of my tokens to my account. It poses a few problems:

  • The backup token needs to be easily accessible. Even though I'm not going to carry it on my keyring, I should be able to access it quickly, so I can hardly do any better than keeping it somewhere at home.
  • When I'm traveling and need to register on a new service, I can't access my backup token immediately. So, I'll have to remember to add it to the new account when I get home, and until that, I have no backup for that service. Worst case, I can even forget.
  • Whenever I'm at home, both of my tokens (primary and backup) are basically in the same place. That is a bad, bad way to backup things. If something happens with the apartment, both tokens can be affected by the same event (get destroyed or stolen).
  • The idea to keep a backup token at home is pretty obvious, and even though we try to make it hard for other people to break into our homes, it might be doable if one really wants to.
  • Non-universal method: if some service doesn't allow adding more than one U2F token to a single account, then we're out of luck. At the time of writing this, an example of such service is Twitter.

Clearly this “best practice” is not so secure and also quite burdensome. So let's look at another common option (spoiler: which sucks even more).

Non-U2F method as a backup

OTP:

  • Even though having a backup OTP is better than using it as the primary 2FA (because as long as I keep using the U2F token, I'm not vulnerable to phishing), it still opens one more attack vector;
  • Phones can break or get lost or stolen, and in the case of such event, I'd have to revoke backup creds from all services and recreate them;
  • Probably the biggest issue for me: I always carry my u2f token and my phone with me, so again, it's a bad way to backup things. It's not too unlikely that I could lose both my phone and u2f token at the same time and thus get myself locked out of my accounts. We could use Authy which synchronizes the database with the server, but the Authy account can be recovered using SMS, which is anything but secure (however the backup is encrypted by a password which only I know, so overall I'm okay about those backups);
  • Non-universal method. Even though many services support Google Authenticator (with the alternatives like Authy), some only have an option to use custom app.

Recovery codes:

  • It's desirable to keep recovery codes for all services in a single, safe place. Again, this place is likely to be my home with (almost) the same problems as already discussed with the backup U2F token.
  • Again, non-universal method: whether the service supports recovery codes depends on a service.

So bottom line, all of the above methods are non-universal, burdensome and not so secure.

Optimal backup strategy

Now that I ranted enough on why everything is so bad, let me tell what I want. I do actually want to have two U2F tokens: primary and backup, but they should be set up in a special way:

  • When I register the primary token on some service, the backup automatically becomes valid for this service as well;
  • Just when I use the backup token on some service for the first time, the primary one is invalidated for that service.

Before we discuss the technical possibility of it, let me elaborate why I actually want that and how I'd use it.

Why it is awesome

If we refer to my points above on why a distinct U2F backup token is a bad idea, we can see that all shortcomings of such approach are solved:

  • The backup token does not need to be easily accessible anymore. Extreme use cases are: I could secretly brick it up into the wall in the villa's basement, or bury somewhere in the forest. I'm not kidding, I would actually go that far. A fair warning is that obviously one has to remember very well where the token is stored. :)
  • Whether I'm at home or I'm travelling, and I need to register on some new service, I do the same thing about maintaining the backup token. That is, I do nothing. I just use my primary token as if it was my the only token, and I have the peace in mind knowing that I'm covered by the backup automatically.
  • It's not at all obvious for other people where is my backup token. Few people know it exists in the first place (okay let me say it straight up: it does exist), but even though you now know it exists, I bet it's not feasible to even consider looking for it.
  • It's safe. Even if something bad happens with my primary token, it's highly unlikely that my backup token could be affected by the same event.
  • It's universal. Having the two tokens set up as I described above, I could use the primary one on any number of services supporting U2F, and it would work independently of whether the service supports multiple tokens, or which backup options does it have, etc.

And if I'm unlucky enough to actually lose my primary token somehow, here's what I should do:

  • Unbrick / dig out the backup token;
  • Log into all accounts with the backup token, thus invalidating the primary one;
  • Since the lost primary token is invalidated, I should be mostly safe at this point, but still, the backup should only be used to enroll a new token. So, time to get a new pair of tokens, add them (i.e. the new primary one) to all accounts and revoke the old token.

I consider this strategy overall to be a really good tradeoff for being secure and still have a reliable, burden-free backup. It's both more reliable and more secure than all other backup strategies.

Implementation

Brief overview of U2F

Before we can talk about actually making it a reality, we need to understand briefly how U2F works. So, here's how it's implemented by the majority of manufacturers (there are some details which are not specified in FIDO U2F, and thus are implementation details)

A U2F token device has a device_secret programmed into it, together with a 32-bit counter which starts from 1 and can only be incremented. When we register that device on some new service, here's what happens:

  • Browser sends an AppID (basically, a domain you're on) to the U2F device;
  • Device generates a random number (nonce), mixes this with the AppID, runs all that through HMAC-SHA256 using device_secret as a key, and the output becomes the private key for that particular service: service_private_key;
  • From service_private_key, a public counterpart is generated: service_public_key;
  • Device takes AppID again, mixes it with the service_private_key, and again runs through HMAC-SHA256 using device_secret. The resulting data (MAC), together with nonce generated earlier, becomes a key_handle.
  • Device sends key_handle and service_public_key to the browser, and browser transfers it to the service which keeps that data for future authentications.

And authentication goes as follows:

  • Service generates a challenge (a piece of random data) and sends it to the browser together with key_handle (which consists of nonce and MAC). Browser sends all of that to the device, together with AppID (i.e. the domain);
  • Device generates service_private_key the same way it did on registration, but this time it uses the received nonce instead of the randomly generated one;
  • Device generates MAC in the same way it did on registration, and by comparing it with the MAC received from browser it verifies that the received nonce is not tampered and thus the generated service_private_key is valid;
  • Device increments its internal counter;
  • Device signs the challenge, AppID and counter with service_private_key, and sends the resulting signature along with the counter to the browser, which forwards this data further to the service;
  • Service verifies the signature using the service_public_key it has from the registration. It also checks that the received counter is larger than it was the last time (if any). That check is designed to prevent device clones. So if signature matches and counter > last_counter, the authentication is successful, and service saves counter as last_counter.

Curious reader can refer to FIDO Alliance Proposed Standard 11 April 2017 and Yubico's developer documentation for more details.

Let me highlight the parts which are very relevant to our today's discussion.

Relevant parts

First, the token doesn't store service_private_keys for each service: instead, it derives keys from other data it has using HMAC-SHA256. This is very important for us: obviously if each device was keeping its own set of per-service private keys, it would be technically not possible to use the backup token on a service without actually registering that same physical token on that service.

(By the way, this is not actually a U2F requirement: U2F doesn't specify how to store keys, and at least in the past there were some implementations which were keeping private keys on the device, e.g. see this github issue. And the rationale for not storing private keys was to avoid limiting the maximum number of services registered with a given token: since device doesn't store any per-service data, the number of services is unlimited)

And second, the token has a counter to prevent device clones.

At first sight, it might seem that this counter thing prevents us from implementing the desired strategy (at least it seemed so to me when I was trying to come up with some solution), but in fact, it only helps us! Bear with me.

The main idea

The idea is as follows: at the time of manufacturing, program two tokens so that they share the same device_secret, but the backup token needs to have a small tweak: instead of returning counter from 1 (as normal tokens do), it should add some large constant to each returned value: I'd say, approx. half of the 32-bit range, e.g. 2 000 000 000, looks reasonable: I'm unlikely to exceed it during the whole life.

That's basically it, simple and effective.

Having two tokens programmed this way, I hide the backup token somewhere far away and never use it, and just keep using the primary one, so the counter will start from 1 and will be incremented by 1 at each authentication. If something terrible happens and the primary token is gone, I go all the way down to get the backup token from where I hidden it, and I can immediately use it on all the services I used the primary one with, because it has the same secret, and its initial counter is set to a very large number, which I'm unlikely to exceed during the lifetime anyway. Some service's admin might get surprised if they happen to look at authentication counter logs when they see a number suddenly jumping from some small value to 2 milliards, but that shouldn't be a concern. :)

Also let me clarify that I'm not suggesting making the tokens cloneable. As you see, they are not entirely clones anyway (because the backup token has different counter); they only share device_secret which needs to be just programmed to them at the same time, and after that it's not possible to read that data from the token or otherwise make a clone.

Caveat with the counter

Attentive reader could notice that there is some security flaw in the idea above: what if attacker gains access to the primary token, and then somehow forces it to count up to 2 000 000 000? Then they'll be able to use the token even after the backup token was activated.

Luckily, this issue has a simple solution. The counter should be implemented as some hardware counter (presumably on some cryptoprocessor), and that hardware counter should have the range less than 32-bit. E.g. on ATECC508A, monotonic counters can count only up to 2097151. So, by setting the boost counter value in the backup token to anything larger than 2097151 ensures that the primary token could never possibly use the counter value which larger than the backup's counter. To clarify: let's refer to the value from ATECC508A's counter as hw_counter. Then:

  • In the primary token, we use: hw_counter;
  • In the backup token, we use: hw_counter + 2000000000.

Note that we do not modify the actual hw_counter in ATECC508A; it will still count from 0 to 2097151. Instead, every time we need to get a counter value, we read hw_counter from ATECC508A, then add boost constant, and return further (for using in u2f calculations).

This way, the counter range of the primary token is [0, 2097151], while the counter range of the backup is [2000000000, 2002097151]. The fact that those ranges don't intersect ensures that once backup token is used on some service, the primary one is invalidated for good on that service.

Actual implementation

We cannot use YubiKeys for that. Even though YubiKeys do support programming of OTP keys easily (and they even have two slots for them), the U2F key material is totally set in stone. They say that the device_secret is generated on-chip at the time of manufacturing. Well, that's cool and secure and all, but as I mentioned in the beginning, along with security we have to think about a good recovery plan, otherwise one has to actually weaken that security with some back-way if they want at least some recovery plan. Okay, so no YubiKeys for me.

Ideally we should be able to program U2F key material and the counter boost value; having that, creating backups as explained would be easy. Also, it's actually a good thing to be able to control our keys: even though Yubico claims that they do not know the U2F keys in the devices they sell, we have no way to prove that. At the moment, there are no U2F manufacturers who would allow us to program U2F keys and counter Actually, there is! See the section on Trezor below.

Luckily, there is an open source implementation of U2F: U2F Zero. Hats off to Conor Patrick for that! I totally appreciate it, thank you Conor.

There are detailed instructions on reprogramming the devices on their wiki: Building a U2F Token, read that page carefully.

I'm not a hardware guy and I'm not excited about soldering parts together, so I just ordered a few pre-made devices, and reprogrammed them. I personally used a programmer by Silicon Labs for that, but there are alternatives, check the link above and the programmer datasheet. GND is pins 2, 3 or 9; C2D is pin 4, C2CK is pin 7.

At the device configuring stage, we need to specify the same keys when programming both primary and backup tokens. At the moment of writing it, the tools in the u2f-zero repo don't support that (they can only generate pseudo-random keys), so I forked it and added a small commit which implements a few flags. I'll make a pull request and hopefully it will be merged in some shape, but for now, use my fork if you need backups as discussed: https://github.com/dimonomid/u2f-zero .

So, to program two tokens, the sequence is very similar to what's described in the wiki page linked above; the only differences are:

  • Before doing anything, generate your keys and store them e.g. into environment vars. Due to implementation details of u2f-zero, we need two 32-byte keys: wkey and rkey. On Linux, it could be done as follows:
$ MY_WKEY=$(dd if=/dev/urandom bs=1 count=32 | od -t x1 -An | tr -d '\n ')
$ MY_RKEY=$(dd if=/dev/urandom bs=1 count=32 | od -t x1 -An | tr -d '\n ')
  • When invoking ./setup_device.sh, we need to provide those keys as follows:
$ ./setup_device.sh -w ${MY_WKEY} -r ${MY_RKEY} gencert/ca/key.pem gencert/ca/cert.der
  • When programming a backup token, we need to additionally modify the source code to return boosted counter: in the file firmware/src/u2f_atecc.c, there is a function:
uint32_t u2f_count()
{
	struct atecc_response res;
	atecc_send_recv(ATECC_CMD_COUNTER,
			ATECC_COUNTER_INC, ATECC_COUNTER0,NULL,0,
			appdata.tmp, sizeof(appdata.tmp), &res);
	return le32toh(*(uint32_t*)res.buf);
}

For backup token, the last line should be modified as follows (obviously the exact boost value is up to you, I used 2000000000 here) :

	return le32toh(*(uint32_t*)res.buf) + 2000000000;

Everything else is the same as explained in the u2f-zero wiki. To outline the overall process real quick:

  • Generate random wkey and rkey, store in environment vars MY_WKEY and MY_RKEY
  • Insert primary token, erase it and flash SETUP.hex
  • From the tools dir, run ./setup_device.sh -w ${MY_WKEY} -r ${MY_RKEY} gencert/ca/key.pem gencert/ca/cert.der
  • Rebuild firmware
  • Erase the device again and flash the hex you just built: firmware/release/u2f-firmware.hex
  • Unplug primary token
  • Insert backup token, erase it and flash SETUP.hex
  • From the tools dir, run ./setup_device.sh -w ${MY_WKEY} -r ${MY_RKEY} gencert/ca/key.pem gencert/ca/cert.der
  • Modify the firmware to return boosted counter
  • Rebuild firmware
  • Erase the device again and flash the hex you just built: firmware/release/u2f-firmware.hex
  • Wipe your MY_WKEY and MY_RKEY environment vars

That's it! Go to https://demo.yubico.com/u2f , register your primary token, then authenticate with it, and click on the “Techical data” button: on the bottom there will be a counter with some small value. Then try to authenticate again but with your backup token, it'll let you in and you'll see the boosted counter.

I verified that if I add the primary token on Google account, then use it for authentication, then use backup token, and after that if I try to use the primary one again, it won't work (because of the counter). So, as desired, the first usage of the backup invalidates the primary token. Github does the same, and supposedly does any other sane service which supports U2F. Awwwwww. <3

Trezor

This is a new section I added a year after writing the original article.

Luckily, Trezor now supports U2F as well, so one can program their own key using the BIP39 recovery seed, and that key will be used for U2F.

At the time of device reset, one can specify custom counter as well, like this:

$ trezorctl reset-device -t 256 --u2f-counter 2000000

(more details on trezorctl is available in their wiki)

Therefore, one could have two Trezor devices set up with the same recovery seed, but different counters, and achieve the desired backup goal. Or, if having a readily-available backup device isn't a concern, just backing up the recovery seed is enough.

A word of caution

Even though I keep saying that the backup strategy is awesome (isn't it?!), I'm not so sure about the particular implementation of it, i.e. by means of u2f-zero or Trezor. u2f-zero is the only way I could implement it at the time of writing, so that's what I did, but if we imagine that a hacker gets physical access to the u2f-zero device, I'm not sure whether hacking it (i.e. getting secret key from it) would be as hard as hacking a YubiKey. U2f-zero guys claim that “the security level is about the same as a modern car key”, but I'd need to do a more thorough review of the implementation to judge whether it's true.

The same is true for Trezor as well, unfortunately: Kraken Security Labs were able to successfully extract seeds from all Trezor models.

Nevertheless, to tell the truth, I'm not too worried about it. If an attacker just steals the token without an intention to return it back, then it doesn't matter how hard it is to hack the token, because the attacker can then just use it to log into my accounts and then do whatever they want, like add another token, revoke this one, etc. However, for that I have to be already compromised otherwise as well, because the u2f token is only a second factor.

So, the only scenario in which u2f-zero or Trezor can be less secure than e.g. yubikey is when the attacker tries to get access to my u2f device for some short period of time, learn the secret key from it, and then return the device back to me, all without me noticing anything. For that to be done, one would have to read the contents of the MCU flash (or RAM in the right moment), which isn't impossible of course but isn't trivial either, especially in the short period of time they have until I could notice that I got my key stolen or replaced by another one. Just to be safe, I keep verifying almost every day that the key in my pocket is legit.

Considering all that, I still believe that having a backup as described by means of u2f-zero or Trezor is a lot more secure and reliable than having backup by any other means. At least for me.

Conclusion

The discussed backup strategy beats all alternatives on every dimension: it's universal, it's more secure and more reliable than any other backup method.

I'm really surprised that manufacturers don't use it. It would be nice to have an option to buy a ready pair of tokens which are set up in this way, but alas. A guy from YubiKey support, James A., even said to me that the backup the way I want is “not possible with the way U2F is designed”. Well, not that impossible, luckily.

In case you're interested in purchasing a few pre-made u2f-zeros, here are links:

Donate
Discuss on Hacker News, Reddit, Lobsters, or right here:

Discussion

William, 2018/08/15 09:41

Thanks a lot for sharing that! I didn't use u2f for my personal accounts exactly because the backup is a pain, but it looks like your approach solves all my concerns. Really awesome, thank you.

Dmitry Frank, 2018/08/15 10:29

Cool, thanks for the feedback!

Mike, 2018/08/15 11:18

Hey Dmitry, I must say that I really like your blog for such interesting and uncommon content. I enjoy every post, and that one in particular.

On today's subject, I feel like by having a backup like that you're almost abusing U2F, but you do it so brilliantly. I really don't think that U2F designers were considering that use case at all, but it fits into the picture so flawlessly like it was designed with that in mind! Man that's awesome, thanks for the writeup.

Dmitry Frank, 2018/10/27 16:05

Thanks for the feedback Mike!

ND, 2018/08/15 12:42

How well does U2F-Zero resist power-differential and other side-channel attacks?

Dmitry Frank, 2018/08/15 13:14

This is what u2f-zero readme has to say about it:

The security level is about the same as a modern car key. Any secret information cannot be read or duplicated. A true random number generator is used to create unpredictable keys.

However, side channel leakage is an unsolved problem in industry and academia. So for well equipped adversaries that can make targetted attacks and get physical access, secret information leakage is possible. Any other hardware token that claims it's “impenetrable” or otherwise totally secure is still vulnerable to physical side channels and it's important to acknowledge. However, most people don't worry about targeted attacks from well equipped adversaries.

For more information about U2F Zero's secure implementation and the problem of side channels, check out the wiki.
ND, 2018/08/15 12:44

Another question - how do we derive a 2048/4096 bit public/private key from the output of a 256 bit HMAC? Are we using some method of key expansion? And if so, surely we have limited the entropy of our public/private keys significantly?

Dmitry Frank, 2018/08/15 13:12

Asking those questions on the u2f-zero project might be a better idea, since Conor (author of u2f-zero) could probably provide better answers.

He mentions that the algorithm is very similar to that of YubiKeys, and he was using that explanation as a reference.

Also there is a more detailed overview of security architecture in the Nitrokey docs (Nitrokey is an alternative hardware implementation of u2f-zero) : Nitrokey FIDO U2F Security Architecture.

randomguy, 2018/08/15 14:56

This is one of the reasons why I do not use U2F. It is a p*ta to create backups. You should maybe send a link of this article to Yubico and see what they say. Yet another reason I don't use it yet is privacy. It is theoretically possible to link multiple identities i.e. it would be possible for Github to see if two accounts belong to one person. Maybe you also can find a solution for that ^^

Dmitry Frank, 2018/08/16 10:41
Yet another reason I don't use it yet is privacy. It is theoretically possible to link multiple identities i.e. it would be possible for Github to see if two accounts belong to one person

This is wrong. With the way U2F is designed, it's not possible to figure whether the two registrations are done by the same u2f device. There is no identifying information that the service can derive from its interactions with a U2F token. Sorry, that was misleading.

randomguy, 2018/08/16 14:40

I got my information from here: https://medium.com/@nparlante/the-unofficial-fido-u2f-faq-9201fa5cb4da

“Q: Can Web Sites Use U2F To Track Me?”

“There is one oddball case where a single web site can, with difficulty, figure out if two accounts share a token — see next question.”

“Exception: there is one obscure way that a site can determine that two accounts use the same token, although it requires the site to do something deliberately weird. Suppose user A and user B both secure their accounts at example.com with the same U2F token. This works fine. Each registration by a token is identified by a giant random number, and there is no indication to the site what specific token or tokens produced these numbers. Therefore, the site cannot tell if users A and B are using the same token. BUT if when user A tries to log in, the site deliberately sends user B’s log in information, the token will approve the request, and in this way the site could conclude that A and B share a token. This requires the site to deliberately go outside the normal log in sequence, so it does not seem like scenario to worry about much. Note also that this is not some bad guy trying to break into a site, it is the site itself learning information about its users.”

Fazal Majid, 2018/08/15 16:06

Thanks for the write up, it’s a great idea. I’m currently using U2F as an alternative but not exclusive 2FA method for the same reasons as yours, but also because U2F is not supported by Safari or iOS.

What happens if you are traveling abroad and don’t have ready access to your token? Wouldn’t you be locked out until you travel home?

Dmitry Frank, 2018/08/15 18:35

Thanks for the feedback.

What happens if you are traveling abroad and don’t have ready access to your token? Wouldn’t you be locked out until you travel home?

You mean if you are traveling and lose your primary key? Yeah, in this case you'd have to come back to where the backup is hidden. But having a regular U2F backup token, which is kept at home, is not better anyway.

Eugene Crosser, 2018/08/16 09:28

First, I'd like to point out that the idea is really neat! Simple and effective.

And second, I believe that ability to inject externally generated secret material into the token is an important feature from security standpoint, and if yubico does not allow that, it's a design flaw, not an advantage. Design of the token definitely must not allow extraction of secret material, but ability to inject your own is important, because it removes the need to trust the the token vendor. If you are limited to the vendor-supplied secret data, you cannot be sure that they did not keep a copy to themselves (because of a government request or for some other reason). When you generate your own secret data, vendor's ability to betray you is significantly diminished.

Perhaps it's worth to suggest to fidoalliance to include user's ability to inject secret data together with the initial counter value into the token as an optional part of the standard.

Dmitry Frank, 2018/08/16 10:25

Hi Eugene, thanks for the feedback.

Yeah I totally agree that injecting key material (together with the counter boost value) would be very valuable. Actually yubikeys allow to program keys for OTP, and frankly I expected the same for U2F, but alas. I talked to Conor and Nicolas (the guys behind u2f-zero), they are considering adding this functionality in their devices, including a new FIDO2 device (which is in the prototyping stage right now).

John Souvestre, 2018/08/18 00:09

Very nice! One question: Is there any way to test the backup key to see if it is still working?

Dmitry Frank, 2018/08/18 00:23

Sure; the safest way is to just try it on https://demo.yubico.com/u2f (register primary token there, and then login with the backup token), but also it doesn't hurt much to try on some of your real accounts: e.g. log into Google with the backup token, verify that it works, then try to use the primary one, verify that it doesn't work, then just remove that security key from your account, and add again.

John Souvestre, 2018/08/18 00:25

Very good! When do you start production? :) Thanks, John

Dmitry Frank, 2018/08/20 08:11

If you're willing to buy a matched pair of u2f-zeros, contact Conor (conorco at conorco.com), he mentioned to me that he's happy to produce matched pairs for those who are interested.

Malcolm Handley, 2018/08/19 22:55

Thank you so much for doing this. I had the same goal for the same reasons and was reading the docs and discovering that it seemed impossible. You have solved everything.

Dmitry Frank, 2018/08/20 08:12

Cool, happy it helped!

PT, 2018/08/22 21:49

I wonder if something similar can be done with TOPT. I have several accounts on sites that don't yet support U2F, and I also have an iPhone which doesn't support U2F (or NFC to talk to a U2F device).

I use a convoluted process with a TOPT auth app on an iPhone and a backup TOPT app on an old iPod Touch. But this process has all the same downsides you mentioned about needed quick access to the backup in order to register new accounts. It's actually even worse because I must scan the TOPT QR code on both devices when the account is first set up as TOPT never presents the QR code at a later time.

I realize TOPT isn't nearly as secure as U2F, but for the time being it is practically necessary until as sites support it.

Dmitry Frank, 2018/08/22 23:25

I personally use Authy, which has a backup of my codes at their servers. I hate it because Authy account could be recovered using SMS, which is, as I mentioned in the article, anything but secure. But still it's better than living without a backup.

Actually I have a solution for that in mind, and the solution targets even bigger problem: use U2F even for sites which only support TOTP. I hate that too few services support U2F at the moment. The idea is simple: introduce a “wrapper” service, which will basically be a TOTP client, and to get a code for a particular service, one has to use U2F token.

To make it work, one has to have an account on that “wrapper” service, and install browser extension.

So the procedure to login is as follows: when a service asks like “now enter your Google Authenticator” code, the user clicks an icon of the browser extension, then the extension says like “touch a button on your u2f token”, user touches, then the extension checks the current domain, checks that the user indeed has an account on that domain, shows corresponding TOTP code, user copies-pastes it into the service, and that's it. It also addresses the phishing problem (because the browser extension checks the domain name before giving a TOTP code).

I have no idea when I get time to implement that. Hopefully I'll be able to make it open-source, so that one could self-host it.

Óscar Ardèvol, 2018/09/09 13:01

Hey there!

I personally use Authy, which has a backup of my codes at their servers. I hate it because Authy account could be recovered using SMS, which is, as I mentioned in the article, anything but secure. But still it's better than living without a backup.

The backup of the codes at Authy is password protected. So you don’t only need the token sent through SMS message, but also the password used to encrypt the backup. It seems secure in theory, innit?

Dmitry Frank, 2018/09/13 06:17

Hi Oscar, yeah you're right, thanks. I blanked on that. If the backup password is good, should be okay. They also claim that the password never leaves the user's device, so that Authy only has data encrypted with the key they don't know, which is nice of course.

David Vielhuber, 2019/10/31 22:19

Hello,

this is quite cool and I wonder why nobody is considering the authors concerns about backup strategies.

@Dmitry: Did you find a way to get this whole idea working with the successor of u2f zero, solokey?

If not: What do you thing of solutions like https://trezor.io/, which also supports backup and u2f out of the box? Do you know any other solutions like this?

Dmitry Frank, 2019/11/01 05:58

Hello David,

this is quite cool and I wonder why nobody is considering the authors concerns about backup strategies.

Yeah I don't know, probably nobody cares enough about solid backups and are satisfied with the common-practice backup methods (TOTP, recovery codes)

Did you find a way to get this whole idea working with the successor of u2f zero, solokey?

Not yet; I just have my u2f-zeros, they work for me so I stick to them for now

What do you thing of solutions like https://trezor.io/, which also supports backup and u2f out of the box?

To my knowledge, they don't support counter boosting (at least not yet) (they do, see my next comment), so e.g. on this page: https://wiki.trezor.io/User_manual:Two-factor_Authentication_with_U2F they mention:

Note: It is not possible to use multiple devices with the same recovery seed for U2F if the service has a counter mechanism in place.

I believe that most services supporting U2F would respect the counter (I checked google, github, attlassian; might check the rest of the services but didn't bother yet), and therefore, a backup device wouldn't help as the service would reject the backup due to lower counter. It might be worth talking to trezor guys, asking whether they'd be willing to implement counter boosting for u2f; that'd be cool. However, it might still make the setup somewhat less secure than having two u2f-zeros as I described in the article: having two u2f-zeros, if I lose my primary token, then I can log into all my accounts using the backup token, thus invalidating the primary one (so even if someone gets access to my primary token, it'd be useless). In case of boost-able trezor counter though, the counter can just be adjusted.

But that last point could be addressed with just implementing it in such a way so that the counter boost value can only be specified on the time of setting trezor up, so only someone knowing the seed can also set initial counter value, and it should be set in stone after the setup is done.

Definitely worth talking to trezor guys I think.

Dmitry Frank, 2019/11/03 11:35

Actually it seems like I was wrong, there is a way to customize the U2F counter, looking at the wiki page for trezorctl: https://wiki.trezor.io/Using_trezorctl_commands_with_Trezor !

I'm going to check it out.

David Vielhuber, 2019/11/03 14:55

Wow, this sounds cool.

But I think there is no way to have duplicate keys, or am I wrong?

Dmitry Frank, 2019/11/03 15:37

Yes there is a way to have multiple Trezor devices with the same master key (derived from the same seed), if that's what you mean. To make two Trezor devices work as primary and backup U2F tokens, they shouldn't be entirely duplicates though: the backup one should have a boosted counter, but from what I'm reading so far, it should be possible.

I'll post an update once I get my hands dirty with Trezor.

David Vielhuber, 2019/11/03 15:39

It seems that if you use the same seed, you get the same keys.

Just for my understanding: If you don't boost the internal counter, doesn't this mean, you cannot use the second device for U2F because the counter there is behind?

Dmitry Frank, 2019/11/03 17:46
If you don't boost the internal counter, doesn't this mean, you cannot use the second device for U2F because the counter there is behind?

Yes, that's right for the majority of the services (probably not for all of them because technically a service could ignore counter, although I'm personally not aware of such a service)

David Vielhuber, 2019/11/05 21:23

Just for information: Currently (only) Trezor T supports FIDO2 (see the answer to my recent question here: https://github.com/trezor/trezor-firmware/issues/245#issuecomment-549718344). So we have to investigate with Trezor T (which is unfortunately not cheap).

Dmitry Frank, 2019/11/06 11:56

Yeah right. By the way, I'm personally not at all a fan of FIDO2; for me, unguessable passwords with password manager + U2F token with a good backup is a better tradeoff.

So I'll probably be fine with Trezor One.

David Vielhuber, 2019/11/06 12:00

Can you elaborate?

For me a complete passwordless world would be way better.

The only thing is that all backends need to adapt and nearly every site needs something like an account and roles center, where you can add multiple users (with every user has one FIDO2 key) have permission to an account. This works well on big sites like Google Analytics, etc. But for small sites, we nearly need to login into shared accounts every day from different working spaces at and this would be impossible to do with FIDO2.

Martin Burnicki, 2019/11/06 10:15

Thanks very much for these useful ideas and information!

Dmitry Frank, 2019/11/06 11:56

Glad it helped!

Jeff Brixhamite, 2019/11/28 11:59

For me I have concerns about any security device that uses a USB port as it is possible for a user to have their token replaced with something that appears to be the same thing, but in reality can either (a) infect computers with a virus or keylogger or (b) totally destroy any computer they are plugged in to (devices such as this actually exist and do their damage using a stored charge).

Julien, 2020/05/25 16:50

Thank you Dmitry for this amazing deep dive into U2F backup.

Looking closer to more recent updates on both Trezor and Ledger devices, I read that recovering with the seed (mnemonic) also restore the U2F device_secret (master key) and the counter state.

Restoring a seed on another Trezor (see Recovery) restores all the U2F keys too, since they are derived from one master key. Due to the design of U2F, some services might implement a counter that records the number of sign-ins. However, if you have firmware version 1.4.2 or higher, the U2F counter is restored automatically.
If you lose access to your device, you can restore your recovery phrase on any Ledger hardware wallet and reinstall the Fido U2F app to get access to your account.

So, today, could the ideal U2F backup strategy be:

  1. Buy 2 devices (either 2 Trezor or 2 Ledger)
  2. Reset one of them with a new seed (evading an evil manufacturer keeping track of device_secret)
  3. Keep in a safe/distant physical place the 12/18/24 words mnemonic (using a cryptosteel-like device)
  4. Install U2F app and register the deivce on a bunch of services
  5. When you loose your device, go fetch your mnemonic and import it into the spare device.

The only disadvantage I see compared with your custom counter is that the old/primary device is still valid. So we'd need to register/signin with the backup device on all services, and replace it with a new one. It may take us some time, but using a PIN on the device reduce the chance of having a thief using the device, at least for a few hours/days, and that's assuming they also have access to the 1st auth factor credentials.

Did I get something wrong or do you see any other disadvantage to this solution? It of course remains to be tested, especially for Ledger as they don't mention the counter issue on their support page.

Dmitry Frank, 2020/05/26 07:27

Hi Julien, thanks for the feedback.

I read that recovering with the seed (mnemonic) also restore the U2F device_secret (master key) and the counter state.

To clarify, device_secret is indeed derived from the seed, but counter is a separate thing, it can't be derived from the seed. The counter is “restored” by just setting it to the Unix timestamp at the time of restoring. Weirdly enough they don't mention this detail in their docs (they just say that the counter is restored “automatically”), but here's a Reddit comment where they explain it. So in fact, when you restore trezor, the resulting counter in the device will be a lot larger than in the old device, which is a good thing, because logging into some service with the backup device will invalidate the primary device (if the service uses counter)

4. Install U2F app and register the device on a bunch of services

Probably minor, but I'm not sure what do you mean by the U2F app; to my knowledge there's nothing to install. I'm able to use Trezor right after resetting it with a new or existing seed.

The only disadvantage I see compared with your custom counter is that the old/primary device is still valid. So we'd need to register/signin with the backup device on all services, and replace it with a new one.

As I mentioned above, counter on a backup device will end up being significantly higher than on the primary one, so just logging into a service will invalidate the primary one, at least for some time (“for some time” because, unlike the u2f-zero with custom counter approach, an attacker might be able to initiate a lot of authentications using the primary token, thus incrementing counter, and might reach the counter you have in the backup. I didn't check how hard it is to do on Trezor. On U2f-zero with large counter boost it's not possible because the counter can only count up to 2097151, so by using a counter boost value larger than this number, we make it impossible to just increment the counter by performing lots of authenticatins).

But overall, yes I agree that the strategy you outlined (with backing up a seed on cryptosteel and having a spare device handy) is probably a better tradeoff, comparing to having two u2f-zeros.

Julien, 2020/05/26 14:33

Yes, I wasn't sure how they managed to recover the counter given it's not derived from the mnemonic. Thanks for sharing the Reddit comment, that helps a lot. This solution then also come with the advantage of making the original device obsolete thanks to the counter being boosted.

For the step 4 installing the U2F app, I referred to how Ledger requires you to install an U2F app before to use it Link. I assumed it was similar on Trezor, but looks like it comes preinstalled with the firmware.

The only attack vector I see is someone taking your device for long enough to be able to clone it (15min apparently, maybe 25min including the PIN brute forcing), then increasing the counter and finding what services it can authenticate (can also be automated). If a service authentication is successful this also make your backup U2F device useless as your counter is now behind the attacker's.

The only things mitigating this attack vector would be:

  1. to have your 1st factor authentication credentials separate from this device and strong enough to withstand brute forcing (ideally good password manager practices),
  2. using services with good security policy (such as blocking repeated authentication attempt, notifying you of these attempt)
  3. keeping your U2F device actually with you at all time and in a safe place otherwise (obvious but critical).
Dmitry Frank, 2020/05/27 12:38

Overall I agree, just a few things to clarify:

This solution then also come with the advantage of making the original device obsolete thanks to the counter being boosted.

Keep in mind that we can as well specify the arbitrary initial counter value when resetting Trezor device, as I mentioned in the article, like this: –u2f-counter 2000000.

If a service authentication is successful this also make your backup U2F device useless as your counter is now behind the attacker's.

I think if authentication is successful, then the counter doesn't matter much, because the attacker can just remove the token whatsoever, add his own token, etc. All bets are off.

Robert, 2020/08/06 16:15

One issue I see with this approach is that you can't test your backup token. It might get broken but you don't replace it because you don't know that it is broken. You only realize that when it is too late.

Dmitry Frank, 2020/08/06 16:32

Why not? I do periodically test (some of) my backup tokens: authenticate with the backup to, say, github, then try to authenticate with the primary one (it fails), then authenticate with the backup again, revoke the token, and add back the primary one.

Robert, 2020/08/06 23:40

I agree that works. Now that I think of it, I think what bothers me is that you have to physically access the backup token. Not knowing what the actual keys are, not being able to back them up like everything else, is scary to me. That of course has nothing to do with your method but is inherent to this kind of hardware security and actually a desired property.

I'm skeptical because I have lost important data from my phone due to hardware security: I had a complete backup of my phone, containing everything that was on my phone. When I had to make use of it, it turned out that an app had used the Trusted Platform Module of the device to encrypt its data, making the backup useless. The app never warned me that it did that and I never wanted it to do that.

I would prefer to have hardware security not everywhere but for example only for a central database that then manages all other private keys. (A software based security token.) It is a little bit less secure, yes, but having widespread hardware security everywhere, possibly with TPMs that you are not aware of, is too big of a risk for me. Especially I don't want software to make use of hardware security without telling me but I'm off topic here, sorry for that.

Jamie, 2020/08/25 20:55

DiceKeys.com is advertising the ability to create duplicate SoloKeys.com. I wonder what they do about the counter.

Enter your comment (please, English only). Wiki syntax is allowed:
   ____  ____    _  __   ____  _____
  /  _/ / __ \  | |/_/  /  _/ / ___/
 _/ /  / /_/ / _>  <   _/ /  / (_ / 
/___/  \___\_\/_/|_|  /___/  \___/
 
articles/backup_u2f_token.txt · Last modified: 2023/06/15 18:11 by dfrank
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0