# Lab 5 recitation Author: Sanjit Bhat Date: 04/29/2024 ## Part 1: ACME ### Setup Note: for a full explanation, see the [lecture](https://css.csail.mit.edu/6.566/2024/lec/l16-certs.txt). Problem: * When you visit a site, there's a lock icon next to the URL. Q: what does the lock mean? A: intuitively, your browser knows it's talking to the "right" site. * Q: what does "right" mean? A: identifying something is a hard problem in general. E.g., the IRS requests your SSN and DOB on tax filings. Hopefully, only you know those things. If you leak them, that's a big problem. * We can try to make identity more secure through crypto. Solution: * Public-key crypto. * Have a trusted third-party that keeps some privkey secret. Third-parties called Certificate Authorities (CAs). Biggest one is Let's Encrypt (LE). * Consider a site S looking to establish its identity. * S's sysadmin proves to LE that it owns the domain `S.com`. S provides its identity, `S_pk`. * LE signs "certificate". Intuitively, `S_cert = Sign(LE_sk, "LE believes S.com's pubkey is {S_pk}")`. * User U connects to `S.com`. `S.com` says its pubkey is `S_pk` and provides `S_cert`. * There's a small number of trusted CA's, so U's browser (e.g., Chrome) has all the CA pubkeys in the install binary, including `LE_pk`. * Chrome does `Verify(LE_pk, cert)` and `assert(cert.pk == S_pk)`. * Chome creates a TLS connection with `S.com` using `S_pk`. ### Your task * S's sysadmin proves it owns `S.com` via the ACME protocol. * Implement ACME client, i.e., the script that S's sysadmin would run. ### ACME (from 7.1 of RFC 8555) +-------------------+--------------------------------+--------------+ | Action | Request | Response | +-------------------+--------------------------------+--------------+ | Get directory | GET directory | 200 | | | | | | Get nonce | HEAD newNonce | 200 | | | | | | Create account | POST newAccount | 201 -> | | | | account | | | | | | Submit order | POST newOrder | 201 -> order | | | | | | Fetch challenges | POST-as-GET order's | 200 | | | authorization urls | | | | | | | Respond to | POST authorization challenge | 200 | | challenges | urls | | | | | | | Poll for status | POST-as-GET order | 200 | | | | | | Finalize order | POST order's finalize url | 200 | | | | | | Poll for status | POST-as-GET order | 200 | | | | | | Download | POST-as-GET order's | 200 | | certificate | certificate url | | +-------------------+--------------------------------+--------------+ Key parts: * Create account. Client presents pubkey and domain. * Fetch challenges. Client gets list of challenge blobs and challenge domains. * Respond to challenges. Client makes challenges visible on their site. * Download certificate. After server validates, get the final cert. Advice: * If you're confused about what a particular thing is, try to read the relevant RFC section. In general, reading and interpreting specs is a useful skill to learn, and one of the takeaways of the lab. * Also, you have the CA script. It's fairly small (~300 LOC). Add print statements to debug it. ### Details * JSON Web Keys (JWK). Pubkey format. * JSON Web Signatures (JWS). Signature format. Note that almost every blob to sent to server must be signed. * x509. Certificate format. ## Part 2: WebAuthn Note: for a full explanation, see the [lecture](https://css.csail.mit.edu/6.566/2024/lec/l17-user-auth.txt). The [webauthn guide](https://webauthn.guide/) is also very useful. ### Setup Problem: * We're concerned about identifying users who access a site. ACME was about identifying web servers. * We have usable security concerns. We want to prevent phishing attacks where a malicious site poses as a legitimate one and requests your creds. * We want to protect against server compromise leaking the client's credential. * Can't expect humans to remember many high-entropy secrets, although finally, user auth needs to tie back into human auth. * Prevent the cred from de-anonymizing a user across multiple sites. The WebAuthn solution: * Unlike ACME, this doesn't rely on a trusted third-party. This uses a trust on first use (TOFU) model. * User U, U's client C, server S. * On registration: * `S->C`: new `chal`. * C: `pubkey = browser.createPubkey(chal, domain, pubkeyT, authenticatorT)`. `domain` is server domain. It must match the browser URL. `authenticatorT` is component that will store privkey. E.g., in order of increasing security: browser, secure enclave, HSM. * `C->S`: `(pubkeyId, pubkey)`. * S: do a bunch of checks on `pubkey` and store it. * On login: * `S->C`: new `chal`, old `pubkeyId`. * C: `sig = browser.getSig(chal, pubkeyId)`. * `C->S`: `sig`. * S: do a bunch of checks on `sig`, grant user some short-lived auth token for rest of site visit. How does this meet the above security goals? * Only U owns the privkey. Hard to steal, unless there's device compromise. * Browser ensures key only works for the right domain. Anti-phishing. * If server compromise, only leaks the pubkey, not the privkey. That's fine. * Client only needs to remember good secret for device auth. After that, their device stores the high-entropy privkey. * New pubkey for each site. Prevent cross-site linking. ### Your task * Modify the Zoobar server and client to support WebAuthn. * Big parts: * Add the additional server and client interaction to, e.g., get nonces. * Call the right browser API's, encode / decode the right stuff. * Check and store the right things on the server when getting the cred and sig. Big win: no more password box!