Key transparency ================ Opportunistic encryption. Each party sends its public key over the network to the other. E.g. secure channel starts with A -> B: PK_A A <- B: PK_B ... When does this help security? When doesn't it? Trust on First Use (TOFU) Assume first connection was OK, and remember ("pin") other user's public key. SSH uses TOFU, as do many messaging systems. + Convenient -- no user action required. + Strong defense against a new attack, or passive eavesdropper. - Not useful against long-term active attacker. - What if Bob changes key -- gets new device, or loses old one? TOFU is pretty good if you talk to a fixed small set of people. And if they don't change keys often. The easier it is to accept a changed key, the less secure TOFU is. An attack would likely appear as "Bob is using a different key; is that OK?" Out-of-band exchange: Exchange public keys in person in advance, perhaps via QR code. Or verify, afterwards, that TOFU pinned key is correct, in person. Not so secure if exchange is by phone or e-mail! WhatsApp/Signal supports this. + Secure. + End-to-end, security depends only on users and their devices. - It's a pain, people often don't bother. - Need to re-do whenever anyone changes keys (loses a device, gets a new one). Can be made mandatory, but then most people won't use the system. Thus often falls back to TOFU, which is OK. Some larger points: Convenience is very important. In practice we can demand little patience or security expertise from users. If 100% secure means no-one uses, then actual security is 0%. Table I has security and useability columns. Few schemes score well in both sets of columns! Recovery (lost device/key) is particularly challenging. Alternative plan to recover key -- could be a target for attackers. Generate new key -- how to convince other users the new key is legitimate? Useability solutions are often systems-level. e.g. TOFU and key pinning. A combination of technical ideas (crypto) and system architecture. Can we have a central server tell Alice what Bob's public key is? To avoid Alice and Bob having to exchange public keys in person. To increase useability! Central key server example: Apple's iMessage. Alice's device ; Apple server ; Bob's device. Registration: User has ID and password (iCloud). Messaging app has a public/private key pair. User registers public key w/ Apple server. Only the device itself knows the private key. When Alice sends to Bob: Alice asks Apple server for Bob's public key. Alice encrypts msg with Bob's key, signs, sends to Apple server. When Bob is active, he retrieves, decrypts. Bob asks Apple for Alice's public key to check her signature. TLS secures communication with Apple servers. + Convenient, little user involvement + Apple doesn't know private keys, can't directly read or forge messages. + Handles lost/new devices well (re-register w/ password). - Password opens up various attacks. - Disaster if Apple is corrupt: could return Eve's public key, not Bob's. Not perfect, but the convenience is enormously important to people actually using secure chat! Key Transparency -- detect a corrupt key server or unauthorized key change. i.e. use a key service for useability, w/o losing end-to-end security. A recent proposal from Google. The basic idea: Require key server to maintain a public log of all key updates. Key owners periodically check that their key is correct in the log. Key requesters check that result matches latest update in the log. The log might look like Bob added PK_x. Alice added PK_y. Bob deleted PK_z. If a corrupt key server wants to return Eve's key when Alice asks about Bob: Either server must put Bob->PK_Eve in the log, and Bob will see it and complain. Or server doesn't change the log, and returns PK_Eve anyway, and Alice will see that Bob->PK_Eve is not in the log, and complain. Key Transparency reveals dishonesty, but it doesn't enforce it. Many interesting technical details: Efficient lookups and validity checks (linear scans of a log are too slow). Preserve privacy. Prevent server from "equivocating" -- forking the log: Maintaining two different logs, and showing one to Alice, and a different one to Bob. Different users compare notes to ensure they see the same log. Related to block chains. Keybase -- a different plan to reduce trust in a key server. Allow clients to check server's name/key claims. To defend against a corrupt key server. Server holds, for each name like "Alice": PK_Alice (only Alice's devices have private key) identity records linking Alice to her account names on other services e.g. Sign(SK_Alice, "I am alice177 on twitter") For each identity record, Alice must put signed statement visible in that other account. E.g. tweet it (encoded in ascii), post it on github, &c. How do clients use this? Bob asks Keybase server for info about Alice. Keybase sends PK_Alice and Alice's signed identity proofs. Bob's client fetches proof posts from twitter &c. Bob's client checks all proofs are signed with PK_Alice. Client presents other names to Bob, asks "is this the Alice you meant?" How does this defend against Keybase returning PK_Eve instead of PK_Alice? Keybase can't forge identity records linking PK_Eve to alice177 on twitter. So it must return nothing, or identity proofs about Eve. Bob or his client will (hopefully) notice. What attack might succeed? Attacker gets control of Alice's twitter &c accounts (e.g. guesses password). Keybase clients pin others' public keys, so Bob only has to make these checks the first time he talks to Alice. Keybase securely updates pins: If Alice legitimately changes her public key (or adds a new device), she signs the new public key with her old SK_Alice, and posts to Keybase server a signed "add key" record. Now Bob can ask Keybase for recent "add key" records for Alice, and believe them if they are signed by the PK_Alice that Bob has pinned. Is it convenient? Mostly invisible to users once after initial setup. Users have to pay attention to "is this the Alice you meant?" questions. Users have to revoke keys for lost devices. Users better not lose control of other "proof" accounts. Why temporary bindings, and not generate a fresh epoch right away? Auditing and monitoring costs scale with the number of epochs. CT demo: % go install github.com/google/certificate-transparency-go/client/ctclient@latest % go install github.com/google/certificate-transparency-go/ctutil/sctcheck@latest [ https://ct.cloudflare.com/logs ] [ https://www.gstatic.com/ct/log_list/v3/all_logs_list.json ] [ https://crt.sh/?q=es.csail.mit.edu ] ## one entry is the pre-certificate ## another entry is the actual certificate itself % ~/go/bin/ctclient get-sth --log_name nimbus2024 2024-04-22 14:52:05.164 -0400 EDT (timestamp 1713811925164): Got STH for V1 log (size=594640098) at https://ct.cloudflare.com/logs/nimbus2024, hash 923d05171505f4140034c57fbbfabe4d74c2cc1c5f787a94531a9fbc07931ed5 Signature: Hash=SHA256 Sign=ECDSA Value=3046022100af11c6402061726844740a53f9c4a22d717653ac6691fd2326263f855789629c022100af9f9c4efe7df06de238e7b63a2b021f132f91fb789b554558910a969017ac19 % ~/go/bin/ctclient get-sth --log_name argon2024 2024-04-22 16:05:39.077 -0400 EDT (timestamp 1713816339077): Got STH for V1 log (size=1423727425) at https://ct.googleapis.com/logs/us1/argon2024, hash 6cadeb71b3b08781b33e57f0444b8754ff358796d4a15106dd8577a8d88ec002 Signature: Hash=SHA256 Sign=ECDSA Value=30450221009ca02593d86796eec3f9bb31c615b86b4501521252e8b4b67aae6de1165d2045022012cadc7239056e24b1d2b9c42da05d40ac416673a4a5d3732c6fa2c823b2cec3 % ~/go/bin/ctclient get-sth --log_name argon2024 2024-04-22 16:06:23.155 -0400 EDT (timestamp 1713816383155): Got STH for V1 log (size=1423730644) at https://ct.googleapis.com/logs/us1/argon2024, hash e4c1268d77171b153b58aaa42c4d31380a3489c9a8c5ccb8fa55a83eb3f0c70e Signature: Hash=SHA256 Sign=ECDSA Value=3046022100e20cac3b68f5783841f84556f0cc9efeb01eb2f0be1c156487f83c5955e8ad7802210084bc8ed666291117d0ad47c34d436c0f37757b918007d5869a84328bdfd2c3e9 % openssl s_client -connect es.csail.mit.edu:443 /tmp/es.pem % cat /tmp/es.pem | openssl x509 -noout -text % date -d "Apr 12 01:56:50.893 2024 GMT" +%s 1712887010 ## add back 893 msec because date doesn't deal with milliseconds ## check that pre-certificate was really logged % ~/go/bin/ctclient bisect --log_name mammoth2024h2 --timestamp 1712887010893 ## or, in a single tool: % ~/go/bin/sctcheck /tmp/es.pem ## get the actual certificate from the log (a different one); log entry# from crt.sh % ~/go/bin/ctclient get-entries --log_name argon2024 --first=1354700135 % ~/go/bin/ctclient get-entries --log_name argon2024 --first=1354700135 --text=false > /tmp/es-log.pem % ~/go/bin/ctclient get-inclusion-proof --log_name argon2024 --cert_chain /tmp/es-log.pem Inclusion proof for index 1354700135 in tree of size 1423853975: [...] Verified that hash 8744c69a3197c8ae62a4c107f9bb27d1784b41bde91db93b556db38f408efacf + proof = root hash 0d02cf9c7ffd62b118fc40f4dd6e21d49addc93db98fbcb636ded13af1de368e % ~/go/bin/ctclient get-sth --log_name argon2024 2024-04-22 16:34:49.661 -0400 EDT (timestamp 1713818089661): Got STH for V1 log (size=1423860692) at https://ct.googleapis.com/logs/us1/argon2024, hash fa51ebe377fed83204647d2870333414ce31ba3798c380859aadba330e785037 Signature: Hash=SHA256 Sign=ECDSA Value=304502200dc8f0c962b54baeec89de1a7949d7312ce23c767ee4799447aba70d6f2204fa022100c92373675a7af734f1dffc5929f048e8fe6e9a4f25d698f78a378ad0c13211c9 % ~/go/bin/ctclient get-consistency-proof --log_name argon2024 --prev_hash 0d02cf9c7ffd62b118fc40f4dd6e21d49addc93db98fbcb636ded13af1de368e --prev_size 1423853975 --tree_hash fa51ebe377fed83204647d2870333414ce31ba3798c380859aadba330e785037 --size 1423860692 Consistency proof from size 1423853975 to size 1423860692: [...] Verified that hash 0d02cf9c7ffd62b118fc40f4dd6e21d49addc93db98fbcb636ded13af1de368e @1423853975 + proof = hash fa51ebe377fed83204647d2870333414ce31ba3798c380859aadba330e785037 @1423860692 === Certificate transparency. https://crt.sh/ CT logs are hard to keep consistent: https://www.agwa.name/blog/post/how_ct_logs_fail WhatsApp implements something similar: https://engineering.fb.com/2023/04/13/security/whatsapp-key-transparency/ Apple's iMessage has something similar too: https://support.apple.com/en-gb/HT213465