Blog posts
go back

Passkeys for secure web3 workflows

Why passkeys are key to web3 security

May 18, 2023
written by
John Renner
Founding Engineer
Fraser Brown
Co-Founder & CTO
Deian Stefan
Co-Founder & Chief Scientist
Ann Stefan
Co-Founder & COO
Blog posts
Several online services have recently announced their support for **Passkeys**, an alternative to passwords, for authenticating with web services. Websites such as <a href="" target="_blank">Google</a>, <a href="" target="_blank">Paypal</a>, <a href="" target="_blank">Ebay</a> and Best Buy have all adopted passkeys as part of their authentication story. But it's not just them; passkeys are the result of a massive industry collaboration known as the <a href="" target="_blank">FIDO alliance</a> which aims to make authentication safer and simpler for users. Here at Cubist, we are big fans of passkeys—and have been using passkeys to authenticate users in our <a href="" target="_blank">Key Manager</a> from the very start. In this post we're going to talk about what passkeys are, why you should want every service to authenticate you with passkeys, and finally what types of security advantages and trade-offs you get from using passkeys over passwords and traditional two-factor authentication approaches. Secure user authentication is critical on the web—and especially in web3, where using insecure authentication can result in massive and irreversible financial losses.<br> <br> ## What are passkeys<br> <br> Passkeys are a form of cryptographic credentials that can provide the same or better guarantees as multi-factor authentication (MFA), without all the friction that comes from using MFA today. With passkeys, authentication takes place on your device (e.g., phone or YubiKey) without your credentials ever leaving the secure hardware, which protects you from phishing and other attacks while still providing strong proof of identity to the remote service that is trying to authenticate you. This is in contrast to other methods of authentication which transmit sensitive data over the network, opening users up to credential theft and spoofing.<br> <br> Before we dive into passkeys further, let's first review how authentication commonly works today—this will make it easier to both understand how passkeys work and why they offer better security guarantees than traditional password-based authentication plus MFA.<br> <br> ## The point of authentication: gathering evidence<br> <br> Typically, the goal of authentication is to build a strong argument that the person logging in to an account is the same person who registered that account. It's up to the service (e.g., web server or API endpoint) to decide how strong an argument is required. For example, providing the same password at both registration and login indicates that the authenticating user is likely the same as the registering user—they _know_ the same secret. However, regular users both 1) choose bad passwords—not you of course, you use a password manager to generate your passwords—and, 2) reuse passwords—and attackers are good at sieving through data dumps from breaches. This is why secure services don't trust users to keep their passwords secret and typically require an additional factor such as an SMS code or an authenticator one-time-password (OTP).<br> <br> Each authentication strategy provides different evidence and comes with a unique trust relationship between a service and a user:<br> <br> ### Password Authentication<br> <br> The user provides a secret string at registration time; at login time, they produce the same secret string.<br> <br> **Guarantees:** The authenticating user _knows_ something that the registering user knew.<br> <br> **Requirements:** Both the user and the service must trust each other to keep the password confidential.<br> <br> While the mechanism of password authentication is simple, the obligations are often difficult for services and users. Data leaks happen; users are phished; and so we struggle to trust password authentication on its own. Like we said above, this is why many services will require a second factor .<br> <br> ### <a href="" target="_blank">Time-Based One-Time Password</a> (TOTP, e.g., via Google Authenticator):<br> <br> The service generates a large random seed value at registration time (often conveyed via QR code). Both the service and the user agree on a non-reversible algorithm that produces a unique code from the combination of the random seed and the current time. During authentication, the user executes the algorithm and sends the result to the service. The service then runs the algorithm independently and confirms that it got the same result.<br> <br> **Guarantees:** As with regular passwords, the authenticating user _knows_ something that the registering user knew. Unlike conventional passwords, phishing an OTP only works for a single session (whereas for passkeys, this attack vector goes away).<br> <br> **Requirements:** Both the user and the service must trust each other to keep the seed confidential, but the service can rely on the fact that the seed can't be easily phished. The user relies on the service to generate a sufficiently random seed.<br> <br> TOTP can be used standalone, but in practice it is used together with password-based authentication, as a secondary factor.<br> <br> ### SMS Two-factor<br> <br> The user provides a phone number at registration time. At login time, they prove they can access that phone by reproducing a short text the service has sent.<br> <br> **Guarantees:** The authenticating user _has_ access to the phone number provided at registration-time.<br> <br> **Requirements:** The service must trust that the user has retained unique access to the phone number.<br> <br> Unlike passwords, SMS authentication puts less burden on the service—though it does bring the SMS provider into the trusted computing base (and they sometimes get hacked too). The user obligations, however, are out of their hands: as a user you can do very little to defend against SIM Swapping, an attack where hackers hijack your phone number—and these attacks have become increasingly common.<br> <br> All of the strategies above—especially when combined—can provide compelling evidence that a user should be able to successfully authenticate. _Unfortunately_, they also place considerable obligations on both the user and the service. Not all authentication methods have this problem, however. SSH servers and git repositories often employ _public key authentication_ which requires very little of the service, and consequently less trust from the user.<br> <br> ### Public Key Authentication<br> <br> The user provides a public key at registration time. At login, the service sends them a random challenge value which they must sign with the associated private key.<br> <br> **Guarantees:** User _has_ access to a private key they had access to at registration time.<br> <br> **Requirements:** The user to keep the private key confidential. Unlike with passwords, however, the user does not have to worry about the service keeping anything secret.<br> <br> Public key authentication is a compelling option because it allows users to have less trust in the service, but like password authentication, it requires significant trust in the opposite direction. Keeping a private key private is a difficult task for most users, and services have no guarantees that the user is following good security practices (e.g., protecting their private key with a password or pin). This is where passkeys come in.<br> <br> <br> ## From private keys to passkeys<br> <br> Passkeys build on public key cryptography to reduce the trust required between services and users. Specifically, they provide guarantees to the service about how the private key is protected. This is accomplished with a two-part process:<br> <br> 1. **Attestation:** Proving the origin of the key at registration time.<br> 2. **Assertion:** Describing the access method of the key at authentication time.<br> <br> ### Attesting keys during registration<br> <br> When registering a passkey with a service, the user provides both a public key and a chain of signed certificates that proves how the public-private keypair came about. This is very similar to how TLS certificates prove a chain of trust for HTTPS.<br> <br> An example attestation chain might look like this:<br> <br> - Provided public key, signed by KeyPairA<br> - KeyPairA's public key, signed by Yubico<br> <br> <br> This indicates that KeyPairA is a hardware key on some YubiKey produced by Yubico. A service that receives this attestation chain can then trust that the private key is protected by the hardware characteristics of a given device.<br> <br> Passkeys don't require a specific attestation chain or any particular root, but they empower the service to make educated decisions about the level of security required. They're free to discard the chain completely, implicitly trusting the user to generate and protect the private key without any guarantees. In practice, though, you should check these attestation chains—and YubiKeys are pretty great.<br> <br> ### Asserting access during authentication<br> <br> Just like regular public key authentication, passkeys authenticate by signing a random challenge (typically 32-bytes) generated by the service. This signature proves they have access to the private key, but it doesn't prove how they accessed it. Was the user physically present? Did they enter a password? Did they use biometric authentication?<br> <br> Passkeys address these questions by signing not only the challenge but an additional set of flags. Specifically:<br> <br> - Whether or not the user was present (e.g., did they tap the YubiKey?)<br> - Whether or not the user verified their identity (through a password, PIN, or biometrics)<br> <br> This data is extensible so it can optionally include details on exactly how the user was verified, so that services can require biometrics, or a password, or both.<br> <br> All of these assertions are signed along with the challenge and sent back to the service, so we know they came from the holder of the private key. But how do we know they aren't a lie? A software key could easily generate an assertion claiming to be a hardware key that did biometric verification. This is where the value of attestation comes into play. If we know that the public key was generated on a YubiKey, then we know that this attestation data is generated on-device and that it can be trusted. Rather than having to trust the user, like we would in the basic public key authentication case, we can trust Yubico or any other attestation root we like, such as Apple (secure enclave) or Infineon (TPM).<br> <br> ## Bringing passkeys to the public<br> <br> Passkeys provide strong guarantees, but they seem to have all the downsides of hardware-based keys. Namely: what happens when you lose your hardware? If you're using a hardware module like a YubiKey, then you'll need to be sure to have a second key registered with the service (or some way to reset your account). For users of high-stakes services (e.g., especially in web3) this is okay. For general consumers this isn't feasible. They're realistically using their phones or laptops to handle their passkeys—and they may only have a single device. All the major platforms have developed (or are developing) backup solutions for passkeys. For example, <a href="" target="_blank">Apple syncs passkeys to iCloud</a>, and <a href="" target="_blank">Google syncs passkeys to the Google Password Manager</a>.<br> <br> Syncing credentials like this can be dangerous, and requires careful handling, but the trust, at least in Apple and Google's case, is essentially identical to how password managers work today. They sync an encrypted form of your credentials that is decrypted on device before use. While not quite as secure as a YubiKey (which cannot be copied), this flow is reasonably secure. Furthermore, it's usable enough that even non-technical users can benefit from it—and it's certainly better than the alternatives.<br> <br> ## An open standard<br> <br> <br> Passkeys are defined as an open standard called FIDO2 which is comprised of two specifications:<br> <br> - **<a href="" target="_blank">WebAuthn</a>:** A W3C standard which defines the JavaScript API and data formats for attestation<br> - **<a href="" target="_blank">CTAP2</a>:** A protocol for communicating with external authentication devices like YubiKeys<br> <br> While each platform is going to have their own way of storing and syncing passkeys, the standard can be freely implemented by anyone in hardware or software.<br> <br> ## Passkeys at Cubist<br> <br> We use passkeys at Cubist as the primary authentication method for our <a href="" target="_blank">key management platform</a>. Passkeys allow us to ensure our users always follow high standards for authentication—e.g., that they use highly-secure physical security keys (e.g., YubiKeys) and that using these keys requires locally-verified passwords. This is crucial to securing their private keys and the assets these keys protect, and preventing (potentially catastrophic) exploits from lost or stolen credentials. It's not quite the "the end of the password", but it is the beginning of an exciting new era of secure authentication.<br> <br>

Read more

Cubist & EigenLabs anti-slasher collaboration

Cubist is excited to announce a new partnership: we are working with EigenLabs to build anti-slashers that will help honest operators avoid getting slashed on EigenLayer.

September 19, 2023

Hardware-backed signing for MetaMask developers

Our Snap lets Snap- or dapp-developers use CubeSigner, our hardware-backed key management system, to safely sign transactions on behalf of their MetaMask users.

September 12, 2023

Intel SGX is broken (again)

Last week, security researcher Daniel Moghimi publicly announced the new Downfall attack that can steal private keys from Intel SGX hardware. In this post, we review the SGX architecture and discuss its underlying security problems. Then, we describe the process we used for evaluating which secure hardware to use in our key manager.

August 15, 2023