# Passkeys : the good, the bad, the ugly

- Speakers: [Nicolas Bacca](https://streameth.org/speakers/nicolas-bacca)
- Channel: [Devcon 7 SEA](https://streameth.org/devcon_7_sea)
- Date: 2024-11-17
- Duration: 25:29
- Watch: https://streameth.org/watch/673982fe1b0f83434d5ab3b3

## Description

Passkeys are the new hype for easy onboarding, but it's a quite old protocol that has been hijacked for crypto purposes. We'll dig through the standard history, the potentially misleading security expectations, and see how to reverse engineer an implementation to validate its soundness

## About the speakers

### Nicolas Bacca

Nicolas is a co-founder of Ledger (https://www.ledger.com) - interested in making hardware security open, understandable and affordable to all, currently exploring the frontier between TEEs and ZKPs


## Transcript

Okay, so Makupai everybody. Today we'll be talking about passkeys, we'll be talking about security and memes as well. So you'll see it will be entertaining, I hope. i'll be going fast because i have a lot of slides so don't sleep so first you might be wondering what you are doing in this room why are we talking about identity and access management protocol phylo means fast identity online so why are we here it looks very complex server blocks client blocks a lot of stuff we don't do with Ethereum. But if we are DGENs, like we all are, we don't really care about all the parts on the server. We care about the fact that with passkeys, we can generate keys on the web browser. And this is very interesting for us because we like keys, of course. So next slide. Yes. So if I want to go through a Presentation as a FIDO protocol in one slide, I would say that FIDO is an authentication protocol You have a registration phase where you will create a key You will bind it to a web origin and then you have an authentication phase where you will get a challenge You will sign it and so you can verify that you are in the right place We have recent gas optimizations that allow us to run the FIDO protocol on-chain, which is why it's interesting, and there are a lot of abstractions going in FIDO, so a lot of different implementations of this protocol going on. Why is this interesting? Again, we got a God tier UX on mobile with account abstraction with passkeys. If you have not tried it already, I will suggest trying the Coinbase Smart Wallet, which is very impressive. But you get something that is very close to Web2 experience. You just use your biometrics, and you have a wallet. This wallet is self-custodial, so you can pretty much do whatever you want. And, well, it's super easy to create an account on mobile with Passkeys. On desktop, it's a bit different, but it's standard as well. So it's good because you have a common interface. You have a QR, you can redirect to your mobile. If you have an Android phone, you can just avoid scanning the QR every time. You can scan it once, and then it will be recognized automatically, but it's proprietary. So it's not a great interface, but at least it's standard on all the implementations, so you have a way to connect your desktop to your mobile, and it's not too confusing, let's say. Regarding a web developer, the experience is pretty standardized, pretty simple as well, because this was acquired by WebO10, by the W3C, sorry, under the name WebO10. So you pass common parameters when you register, like the user information, the key types, the challenge. So two APIs, super simple, have been going through this very, very quickly because we are not yet at the interesting part. The interesting part is going to start now because you are all wondering where the key is stored. We say we have keys, but well, where is it stored? This is the real question. And unfortunately to answer this we have to go through a very very large bit of history so I will be just doing this. The FIDO story starts in 2013 with two protocols the universal second factor and universal authentication factor. Universal second factor is the best known. And both protocols are mostly stateless. Stateless meaning that all credentials are not saved in the device. Credentials are generated in the device, saved on the server. So the device can be used to generate an infinite number of credentials. It was reported launched initially by google and ubico 2014 this is a real commercial launch with two devices uh ubikey and one device on which i worked on if you look at it you might recognize the early ledger design very similar 2018 502 is launched 502 introduces something new it's basically a fusion between U2F and UAF and introduces a concept of resident or discoverable credential. Those credentials are stored into the device so this completely changes the state of the protocol because now it goes stateful. 2019, WebO10 is launched by W3C, so it's basically FIDO but acquired by W3C, and at the same time, on Android, you have the Strongbox API which appears, and it is the equivalent of the secure enclave on iOS devices, so a very secure place to store keys, and Android got FIDO to certify. I think you are getting a trend there. We get iOS support in 2020, and we see that FIDO starts to be supported in devices which are very secure. So it all looks very good at the moment because we have dedicated devices with secure hardware to support FIDO. We have it in phones with strong security. And in 2022, things start changing because we get a shared announcement from Google, Apple, and Microsoft saying, this protocol looks nice, we are going to support it a lot more. And usually when you get this kind of announcement, it's the beginning of assimilation. And this assimilation has a name, Passkeys. So, well, first thing we can say, in 2023, it starts with the introduction of syncable credentials. So credentials that can be synced to different devices, either with a proprietary scheme or a password manager. So here's the illustration. It's a big temple because we are in Bangkok. Temples are called Wat. So this is Wat Pho. I didn't visit it yet, temples are called Wat. So this is Wat 4. I didn't visit it yet, but yeah, Wat. And in 2024, the FIDO alliance finally performs a general rebranding around passkeys. So now a passkey is just describing a FIDO credential. And we'll start a specification to make the synchronization a bit less proprietary. So we might ask ourselves, what is a syncable credential? Because if we search for this in the documentation, we won't find any reference to it. That's because the proper name for it is multi-device credential. So that's one thing. And if we want to define it, we can say it's a discoverable or resident credential in the context of a smartphone. But the only way to know if a credential is really syncable is to look at the answers that you get when you register it. You will get a flag which is called backup eligibility. If it's set to one, then the credential can be synced. So it's something on top of the spec, not super easy to get. The real problem starts now because we have several security misconceptions in FIDO. The first one is that, well, FIDO protects against phishing, not malware. So we can't really expect that FIDO is going to be good to protect against malware, but at the same time, it is implemented on secure devices. So we have strong... we think that the key is going to be strongly protected because this is the way that FIDO was defined. Then we can ask what is the consequence of introducing thinkable credentials to this. And to get even worse, when you look at the implementation on FIDO by crypto people, we abuse it routinely because FIDO is only designed for authentication. When you use it to sign transaction, we can't really verify what you are signing. And if we lose a key, the impact is going much more important for crypto than it is for authentication because you can always revoke an account and you can't revoke a transaction on the blockchain. Then FIDO is designed to be bound by the web origin. If we want to build a common web wallet, we are going to break this property by design. So we have to hack around it, but it's a hack around the specification. And just to say that we have been abusing this protocol for a long time, I'm not especially proud of it, but just mentioning it, I used U2F to communicate between Ledger and Metamask, sorry, and my Ether wallet in 2016 because there was no way to communicate between a browser and a USB device. So it was used as a tunnel at that time. Short break, maybe why secure hardware is important. Secure hardware is important because it will protect the key against malware. Any hardware does that but secure hardware is supposed to do it better. Then it will protect the key against physical attacks. Physical attacks are the last line of defense. When an attacker has access to a device you always think that your key is lost. Secure hardware is supposed to protect you against this. But even more importantly, secure hardware will protect you against passive attacks. Passive attacks meaning trying to obtain the key by listening to what the ship is doing, by listening to electromagnetic radiation, power differences, that kind of thing. And the only way to really protect against this is by using dedicated hardware because even if you use the best open source library like LeapSecP 266K1 here, it needs to be customized to your chip to avoid leaking information. So if you are not working with secure hardware you're going to have problems. That's basically, you are just one speculative leak away from losing the key, for example. So what is FIDO security model for non-seekable credentials? They cannot be extracted by malware. This is very important. The authentication is always done at the enclave level. The enclave is basically in charge. It's holding the key. It's holding the key, it's doing the authentication. If you want to do something with the enclave, you have to authenticate. This cannot be bypassed. So the malware cannot, a very strong malware that managed to modify the kernel of the device can fool you into signing something, but it would have to do it every time and it can't do anything else. Now let's think about some hypotheses for the synchronization. The first one will be the good hypothesis. In that case, we imagine that there is a hardware security module sitting at Google and Apple, and this hardware security module is doing a synchronization protocol between two enclaves. In that case, the security model doesn't change, the credential is never exposed, everything is good. At least it doesn't change. Now the bad synchronization hypothesis. In that case, the key is still owned by the enclave, but you have a way to put it into the application processor to start the synchronization mechanism. In that case, a malware could be able to extract the key, but after prompting the enclave to start the synchronization mechanism. In that case, a malware could be able to extract the key, but after prompting the enclave to start the synchronization protocol. And finally, the ugly synchronization hypothesis where the enclave might not even be used anymore. The key is in the application processor. Everything is in the clear. And then a malware could be able to extract the key, and the malware doesn't need to be as sophisticated as in the previous cases. And unfortunately, the only way to know what the implementation is, is to reverse it. So we are going to do this. First, on iOS. So iOS, to do this, we need to act as a malware. iOS is a bit difficult to jailbreak as you know so I made a reference to a recent jailbreak to show you how complex this is but since we can synchronize we can jailbreak an older iOS device and see what happens. So for that we are going to use the checkmate bug which is quite powerful and allows us to jailbreak a lot of older iPhones. I use PayRain for that, but you might want to use another exploit. It's a bit hard to run, but you will manage to run it if you want. Then we can dump the keychain. We have some information about the keychain at Apple, but here the first thing that we notice is that there is no security property that says that the credential needs to be authenticated every time. It's basically authenticated when the device is unlocked and then it's not going to be locked again. So we see a first problem here. Then digging into it, dumping the kitchen itself, we get more information. We got a first attempt that was done on an older version of iOS, a description of what the kitchen looks like. We basically, we have items in the kitchen which are defined by a metadata and the secret itself. The metadata and secret are wrapped by a key which is handled by the platform. So you need to have the device in order to decrypt this. And you have an additional indirection level for metadata. So you have an extra key which will be decrypt this and you have an additional indirection level for metadata so you have an extra key which will be decrypted by the platform as well but the scheme is always metadata in secret protected by a key basically so there is a small difference between two item version and basically knowing this you can fix what is on the internet today and you can make it dump the recent items because protocol buffers is very easy to describe, I mean it's self describing so you can modify this. When you look at the decrypted item you'll see that the value, the length of the value is 65 bytes plus 32 starting with 04. If you have played with key, you think that, okay, this might just be the public key and the private key concatenated. You can verify it by dumping the key, verifying that the public key associated to the private key is the right one, and it is the right one. So this means we have a way to decrypt. A malware has a way to decrypt the key. It can steal it, and it's fully handled by the by the application processor on ios on android we can do the same thing uh it's much easier to jailbreak an android phone because you can just unlock the bootloader and solve magics and your magis mat magisk and you're done and to look at the application we'll use a framework called frida which will let us introspect the application and inject code to understand what the application we'll use a framework called Frida which will let us introspect the application and inject code to understand what the program is doing. First question, it's very clear on iOS where the kitchen is, on Android not that much. So we want to know where we are and for that we are going to look at the logs. We see that we see a lot of logs referring GMS for Google Mobile Services. Looks like a good place to start, so we will instrument it. To instrument it, we'll just use the signature API in Java, and we will ask for the class that is being used, because that way we can dig further, and we can try to know exactly what is happening. So we do that with GMS. We see finally the name of the class. And we can find some information about that class on the internet. We see that it's a wrapper to another class. So we still don't know if the credential is handled by the secure enclave on the device. But at least we can dig further. So we start instrumenting again. And this time, we will dump the key. So we will assume that if we have the right class, we can cast it, and we can ask it to dump the key. And it works. So we can dump the key, we can verify it's the right private key, it matches the public key, which means that on Android and iOS, we have verified that the key is enabled by the application processor. As a bonus on Android, so it's yet another big what here, we get the key before the user authentication, which means that there is a catch mechanism that is loading the key, and user authentication is just there basically to make you think that it's secure, but it's not really secure. Finally, looking at an external password manager, here we have absolutely no expectation, so it's good. I did the example with Bitwarden. You can see when you dump it that the credential is listed as a public key. Bad news, it's not a public key. Of course, it's a private key, so we can just dump it, look at it, look at the private key, verify that it matches the public key. Exactly the same thing. So if you expected some security by saving your passkey to a password manager, you have none, which is completely the expected result. So to summarize, this is where we are today on smartphones. We have to choose between secure credentials or back-upable credentials, which might not be a good thing because you want both. So the passkeys are handled by the application processor. They are easy to extract by a malware when the device is unlocked, and there are physical attacks applicable, which is probably the worst part because something might be able to dump those keys at a later stage. So user-present enforcement is not really linked to usage of the key. And non-thinkable pass keys, things don't change there. They are still very secure. So we can wonder, how did we get there? One way to say that is that, well, we have conflicting rules between the vendors. So Google says that you can inject a key into the enclave, and Apple says that this is absolutely forbidden. You cannot inject a key into the enclave. So this might be the reason why the enclave were not modified and not used in that case. And all agree that the key cannot be exported from the enclave, so that's another good reason why it's not implemented that way. So FIDO says, FIDO introduced some enterprise, some difference between enterprise and customer pass keys. So this can be another sign that things are not going very, very well. If we wonder what will happen in the future, it's not going to change much because here we have a draft regarding the synchronization protocol, which does not describe how the key is used. If we want to add a trust encore to the key, so if we want to link a device-bound passkey to the key, there were a few extensions to do that, and they were finally dropped. And in the end, well, if we want a better UX for passkeys, this is also going to be dropped. So we had three possible improvement protocols that were dropped. So we can't think that this is not going to change much. If you are disappointed by Platform Authenticator, you can always rely on external passkey implementations. So I listed a few open source ones. The good news is that you can use your favorite hardware wallet if you want. The application is open source and you get a backupable passkey. So it can be another option. What happens on-chain? Well, I have one minute, so maybe I will go over there very fast. Cartridge initiated the move on StarkNet. So passkeys are now very popular because we have been running several optimizations in order to be able to verify passkeys on-chain very efficiently. So, PaaS keys are now very popular because we have been running several optimizations in order to be able to verify PaaS keys and chain very efficiently. I have a few kernels, I have listed a few kernels that you can use to check to use with PaaS keys. So, 0dev, Safecore or Coinbase Smart Wallet. Here's the main difference. I will just look at how they are using PaaS key. You make no difference with a common credential on 0dev. On Safecore, PaaSKey are supported but discouraged. If you look at the specifications, Safecore will tell you it's better to associate the PaaSKey with a regular credential. And if you want to run it on Coinbase Smart Wallet, they support PaaS pass keys, they also support regular signatures, and they will prompt you and tell you, yeah, you might want to use a recovery key. So the answer to the maybe burning question, should we drop pass keys? In my opinion, no, because they still offer the best way to onboard people. But we have to think about the threat model and we have to code accordingly. And one thing we can do since we have smart contracts, we can associate less privilege to pass keys that are not, that are syncable. Because since we know that syncable pass keys are way less secure than pass keys that are handled by the device, we can use them with quotas, we can use them, for example, for less amount of assets. And then we have something that is acceptable. But the most important thing is to know the threat and act accordingly. We are finished. So I will just let you with one last meme for the road. This is the difference between 2014 and 2024. We get rid of password by storing key in password managers. Might not be the best idea. I will let you decide. You can reach me on Twitter and there will be code on GitHub to describe all this so that you can run it on your own device and you can know if at some point implementation gets better and, well, the less ugly solution for the synchronization is being picked. Thank you. All right thank you so much Nicholas that was very entertaining as well to see some memes on the slides I really enjoy that. We do have a couple of questions for you I hope you don't mind answering. So the first question is is Bitwarden not safe generally or just for managing passkeys? So Bitwarden is safe for a password manager but you don't expect the same security to handle password and to handle keys. So that's why I think it's important to store keys in hardware because if you consider that a key is a password you lose a lot of security. So Bitwarden is reasonably safe for a password manager but of course you can extract anything you want from it because this is the way they work. Alright. There's one that's not a question, but thank you for making that big whack pun. It was brilliant. Thank you. Thank you. Next is, do you think intentional security lowering of the standard could be a dual... I don't like... I see the reference, so thanks for making it. No, I think it is... Sorry. I got the direction wrong, sorry. So, no, no, I don't think it is. I don't think it was... I don't think it was pushed by the government. I think it was really a choice to make the UX easier and to make it, make it easier, again, to not lose private keys. So definitely ease of use was the driver for that, in my opinion. Alright. And next question is, what do you think of spending limits for mission management? What should I use as well? I think spending limits and permission management are definitely a good way to deal with that. And what should I use as a wallet? So I will just speak about wallet frameworks. So not necessarily wallets, but for wallet frameworks, any framework that will support this is good. So there are a lot of them. I named three of them, and I think the three of them are good to manage passkeys and to manage additional permissions on top of them. All right, so there's four people who voted this. Well, that was depressing. What to do? What to do? Not panic. So that's the most important part. Keep using passkeys. Just think about using them well, using them with knowing this and use them knowing that they are pretty easy to extract by malware if they are synchronized. So just, yeah, it's not the end of the world. We just have to be more careful. All right. The next one is hardware UB keys would be relatively secure. Yeah, they are absolutely secure, but using your smartphone to store a key that will not be syncable is also very secure. But then you can't back up it, so it's always a choice. All right. And next question is, what are options for a non-syncable passkey? Exactly the same. You have to pass it as being non-discoverable when you create the key, but you can use a smartphone, and in that case, you are on an old style, I would say, file credential. All right. And let me just check. Okay. So next top voted question is, do you think pass keys are easy enough? Oh, it keeps moving. Do you think pass keys are easy enough to use for normal users? Even as an advanced user, I have sometimes lost access to pass key and had to jump through hoops to recover Yes, I think they will be I think they are in regular cases it might be a bit rough on the edges at the moment because the protocol is still very new Passkey synchronization is only one years old so I think it will get better and ultimately all the big firms want to push it. So it will definitely get better. All right. We have a few more seconds to answer this last question. If you turn off syncing passkeys on iOS, are they safe again? They are still on your device. So the problem here is that if you created the passkey as syncable and you turn off passkey synchronization, you get a passkey that is stored in the application processor and which is not synchronizable. So basically, you get the worst of both worlds. Sorry. Actually, we have a few more seconds. Maybe you want to answer also what's the future of secure chip? How do you feel JavaCard in general? I hope there will be secure chips that are more secure, more, sorry, more open in the future, and FlashBots is doing a lot of research in that, so it's good. JavaCard is outdated. That's one of the reasons why I decided to start Ledger, because I wanted to have native code running on a smart card, so that's my general take. JavaCard is good,
