WebAuthn: resident key and non-resident key explained in pictures

I wanted to learn WebAuthn and was surprised to be unable to find any tutorial with good pictures/diagrams. So I created two with the help of LLM’s (mostly Gemini) and wrote this article. I am assuming that you know the basics of asymmetric encryption and what WebAuthn is designed for.
So you have a master secret key that is locked inside an authenticator (such as Yubikey or Nitrokey) that you never get to read directly. You can use the master key inside the authenticator to generate many private keys for different websites and you can ask the hardware to use each private key to compute its corresponding public key, to create a signature, and to encrypt, but you can never read nor export the master key or these private keys. There is no way to make a backup. You create a private key whenever you register with a web site (referred to as the relying party in technical documents), and you present whatever credential is necessary to authenticate when you want to log in to the relying party.
There are two types of keys that can be generated from the master key: resident and non-resident. They have different flows of registration and authentication. These are what this article will explain.
A resident key takes up some precious space inside the authenticator. It is also called a passkey or a discoverable credential.
When you register with the relying party (RP), the software sends your user ID and the relying party's ID to the authenticator. This information, along with the master key, are fed to the key derivation function (KDF) inside the authenticator to generate the credential data (including a private key for this combination of user ID and RP ID) which then occupies one precious slot inside the authenticator. Finally the authenticator outputs the corresponding public key and credential ID to be returned to and stored in the relying party’s database. I personally think of the public key and the credential ID as a single blob and don't care about what different functions they serve in the relatively simple case of a resident key.
When you want to authenticate (log in) to the RP, you present the public key and credential ID to it. The RP can then then challenge you by encrypting some message with the public key, and the authenticator can look up the corresponding private key from its precious storage to decrypt the message and therefore win the trust of the relying party.
In the diagram, all the information in the light red shaded area of the authenticator is hidden (kept secret) from the world, including you, the owner.
A non-resident key is stored in the replying party’s database. It does not occupy any space of the authenticator. It is also called a non-discoverable credential since the authenticator has no way of recovering it except from some information later retrieved from the relying party. Kind of incredible, right? Hence more complicated.
When you register with an RP, its RP ID is sent to the authenticator and is fed to the KDF along with the master key and some random number generated within the authenticator . The KDF then generates a private key and holds it only temporarily. It will be used to compute the corresponding public key and to decrypt the challenges from the RP moments later. The KDF will also generate some important secret information. It will be “encrypted” by the master key into a credential ID and sent to the RP. Finally The credential ID, the public key, and the user ID are stored in the RP’s database.
When you want to authenticate to the RP, you present your user ID for the RP to find your credential ID from the database. Your computer receives the credential ID and passes it along for the authenticator to decrypt back into the “important secret information”. This, along with the RP ID is enough for the KDF to compute the very same private key again to answer the upcoming challenge, which will be encrypted by the RP using the recorded public key. This process is depicted by he light red lines in the diagram.
I am not sure the “encrypt/decrypt” part is exactly the kind of encryption we typically understand, and hence the quotes. This answer gives more details and is the only precise description I can find without seriously looking into specification documents. The important thing, however, is that the authenticator should be able to recover, from the credential ID, the random number used during the generation of this private key so as to re-compute the private key, and yet no one except the authenticator should be able to derive the private key given the (non-secret, not protected) credential ID.
I hope this article and these two diagrams make it easier for you to read two article: “How Hype Will Turn Your Security Key Into Junk” and “Passkeys: A Shattered Dream” , for those were the articles that prompted me to learn WebAuthn.
A side note: for certain kinds of knowledge (such as this) it is a great idea to ask an LLM to draw a conceptual diagram using the graphviz “dot” language. I hope more people will provide such diagrams when writing explanation articles . But the ones Gemini draw are too fancy for me. I started from scratch and ask it to comment so as to make sure that I understand it correctly. Here are the dot files: resident key, non-resident key.
ps. This is my first (real) article at hashnode. Most often I write in zh_TW. I had a few English articles at medium, but I suppose I'll put my (very infrequent) English articles here at hashnode in the future. More about me.