Edge's Two Password Cryptographies: A Beautiful PSI on the Wire, and Plaintext RAM by Design
Microsoft Edge ships a homomorphic-encryption PSI for breach checking and decrypts every saved password into process RAM at launch. Both designs are deliberate. They defend different threat models.
Permalink1. Two cryptographies, one product, one week
On January 21, 2021, Microsoft Research's Cryptography and Privacy group announced Edge's Password Monitor ships a homomorphic-encryption-based Private Set Intersection protocol built on Microsoft SEAL. The post is explicit that this is "possible due to pioneering cryptography research and technology incubation done here at Microsoft Research," that it is the result of a collaboration "between [the] Cryptography and Privacy Research Group, and Edge product team," and that the protocol descends from two specific papers: "Fast Private Set Intersection from Homomorphic Encryption" and "Labeled PSI from Fully Homomorphic Encryption with Malicious Security" [1]. It is, by a comfortable margin, the first production consumer deployment of homomorphic encryption in a browser.
On May 4, 2026, at 14:29:51 UTC, a researcher in Oslo named Tom Joran Sonstebyseter Ronning posted to X: "Microsoft Edge loads all your saved passwords into memory in cleartext -- even when you're not using them" [2]. He linked a GitHub repository called EdgeSavedPasswordsDumper: roughly 500 lines of C# that opens a handle to the parent msedge.exe process and reads every saved credential as plaintext, with no kernel exploit, no admin (against same-user processes), and no DPAPI bypass [3]. The README confirms the behaviour is present in "any Edge versions that's Chromium based (from version 79 and newer, including 147.0.3912.98 and any future version)" [3]. Two days later, on May 6, 2026, Microsoft told Forbes that the in-memory behaviour is "an expected feature of the application" and "by design" [4].
Both designs ship in the same binary. Both are owned by the same product team. Both can be defended on technical grounds. And both stories get told about the same word: "passwords."
This article argues they are about two different threat models, and the apparent contradiction in the headline disappears once you separate them.
A two-party cryptographic protocol in which Alice holds a set , Bob holds a set , and they jointly compute such that each party learns the intersection (or, in some variants, only one party does) and nothing else about the other party's set beyond what the intersection implies.
The PSI story is genuinely beautiful. It begins in 1986 with a paper hardly anyone reads, climbs through a 35-year cryptographic engineering effort to make oblivious transfer cheap enough to be free, lands in 2017 on a homomorphic-encryption breakthrough whose cost curve fits the breach-checking problem exactly, and ships on consumers' desktops by 2021 [1]. The endpoint-storage story is genuinely awkward. Edge unwraps every DPAPI-encrypted saved credential into process memory when the password feature first activates, keeps the plaintext resident for the lifetime of the session, and accepts that any same-user process can read it back out [3]. Microsoft's official position is that local code execution on the user's machine is "outside the threat model" of the browser password store -- a position that is internally consistent with a decade of MSRC policy and also true [4].
The thesis: "password security" is at least two threat models, and Microsoft has chosen to deploy genuinely state-of-the-art cryptography against one of them while explicitly conceding the other. Treating both as one unified story is how product narratives obscure where the actual compromise happens in 2026.
Diagram source
timeline
title PSI and browser credential storage, 1986 to 2026
1986 : Meadows PSI
: NRL matchmaking
1999 : Huberman-Franklin-Hogg
: DH meet-in-the-middle
2003 : IKNP03 OT extension
2004 : FNP04 polynomial PSI
2015 : KOS15 active security
2016 : KKRT16 OPRF-PSI
2017 : CLR17 HE-PSI
: Signal SGX contact discovery
2018 : CHLR18 Labeled PSI
: HIBP v2 k-anonymity
2019 : Google Password Checkup
: Silent OT
2021 : Edge Password Monitor ships
: Cong et al. CCS 2021
2024 : Chrome App-Bound Encryption
2026 : Ronning EdgeSavedPasswordsDumper
: Microsoft "by design" To see why the two designs are not a contradiction, we need to understand how PSI got to be deployable at all -- a story that begins forty years before Edge Password Monitor existed.
2. Why Private Set Intersection exists at all
Imagine two parties, neither of whom trusts the other. Alice has a set of identifiers; Bob has a set of identifiers. They want to learn which identifiers they share -- and only that. Each party wants to learn nothing about elements not in the intersection.
This is not an obvious problem to need a protocol for. If Alice and Bob trusted a third party, they would hand over their sets. If they trusted each other, they would compare directly. The problem only becomes interesting when neither assumption holds. The 2026 canonical version looks like this: Microsoft holds a curated set of roughly five billion breached credentials, and the user holds a few hundred passwords saved in their browser. The user wants to know which of their passwords appear in Microsoft's breach corpus -- and they want Microsoft to learn nothing about the passwords that do not. (Throughout this article the "five billion" figure is the author's 2026 forward projection of Microsoft's compromised-credential corpus; the contemporaneous Microsoft Research figure used in the 2021 Password Monitor announcement is four billion [1], and the §3 sidenote spells out the inference.)
That framing did not exist in 1986. The original motivation was much weirder.
The 1986 paper
Catherine Meadows, then at the U.S. Naval Research Laboratory, published "A More Efficient Cryptographic Matchmaking Protocol for Use in the Absence of a Continuously Available Third Party" at the 1986 IEEE Symposium on Security and Privacy [5][6]. The titular "matchmaking" problem was prosaic. Two parties want to learn whether they share an interest in some sensitive list -- classified-mailing-list membership, intelligence-source overlap, the everyday work of compartmented information systems -- without revealing anything else.
Meadows's protocol uses commutative encryption. Alice and Bob both raise the elements of their sets to private exponents over a Diffie-Hellman group. After two rounds, both parties hold the doubly-blinded versions of both sets. Equal underlying elements produce equal doubly-blinded values, because exponentiation in an Abelian group commutes. Unequal elements look like uniform-random group elements to both sides. The intersection comes out; the rest does not.
Meadows wrote this ten years before Diffie-Hellman key exchange shipped in SSL 3.0 (November 1996), the protocol family TLS would standardise in 1999 [7], and forty years before her protocol's intellectual descendants would ship in a consumer browser.
The 1999 revival
The same protocol shape was rediscovered and given its modern formulation by Bernardo Huberman, Matthew Franklin, and Tad Hogg at Xerox PARC in 1999. Their paper "Enhancing Privacy and Trust in Electronic Communities" was published at the First ACM Conference on Electronic Commerce [8]. The motivations were online-community problems that look quaint today: which of your friends are on this matchmaking site, do we share interests on a sensitive bulletin board, can two early-internet communities establish trust without leaking their member lists. The protocol they wrote down -- usually called "DH meet-in-the-middle" or just "the Huberman-Franklin-Hogg protocol" -- is the canonical PSI shape every security engineer still reaches for first.
The dblp BibTeX record gives the canonical DOI as 10.1145/336992.337012, which the ACM Digital Library 403s to most non-browser User-Agents. The dblp HTML mirror returns 200 and confirms the citation [9].What had to exist before
PSI predates breach checking by twenty years. The cryptographers who built PSI did not know they were building Edge Password Monitor. They were building a protocol primitive that happened, much later, to map cleanly onto a problem the world did not yet have.
The first such mapping landed in 2018 with HIBP's k-anonymity API and the cluster of academic and industry PSI deployments that followed [10]. The primitive predated the killer application by two and a half decades. This is the normal shape of cryptographic engineering: the primitive sits on the shelf until the world needs it.
The DH meet-in-the-middle protocol is elegant. It is also catastrophically wrong for the breach-checking use case. To see why, we have to count exponentiations.
3. Early approaches: DH meet-in-the-middle and FNP04
Let us walk the DH meet-in-the-middle protocol step by step. Alice holds a set . Bob holds a set . Both parties agree on a Diffie-Hellman group of prime order with generator , and on a cryptographic hash function that maps set elements into the group. Alice picks a private exponent ; Bob picks .
The protocol proceeds in two rounds:
- Alice computes , shuffles, and sends to Bob.
- Bob computes , shuffles, and sends to Alice.
- Alice exponentiates every value Bob sent her by , producing . She sends this set back to Bob in the order Bob originally sent his , so Bob can index by his own set.
- Bob exponentiates Alice's first-round values by , producing . (In the symmetric variant Bob also sends his doubly-blinded set back to Alice; either side can then perform the match.)
- Both parties now hold the same doubly-blinded set for both sides. Equal underlying elements collide; unequal ones do not. They intersect locally.
Diagram source
sequenceDiagram
participant A as Alice (set S_A)
participant B as Bob (set S_B)
Note over A,B: shared group G, hash H, private exponents a (Alice), b (Bob)
A->>B: shuffled set of H(x)^a for x in S_A
B->>A: shuffled set of H(y)^b for y in S_B
A->>A: compute H(y)^(ba) for each item from Bob
B->>B: compute H(x)^(ab) for each item from Alice
Note over A,B: equal underlying elements yield equal doubly-blinded values
A->>B: ordered set of H(y)^(ab) for matching
Note over A,B: intersection computed locally Why this is right. Under the Decisional Diffie-Hellman (DDH) assumption in , the doubly-blinded values for look uniformly random to the other side. Equal underlying elements collide; unequal underlying elements do not. The reader can verify this for themselves in the demonstration below, which is the canonical pedagogical version of the protocol.
// Toy PSI -- pedagogical only, NOT secure (small modulus, weak hash).
const p = 2n ** 61n - 1n; // Mersenne prime, small for demo
const g = 37n; // generator over Z_p* (toy)
const H = s => {
// toy hash: deterministic map string -> [1, p-1]
let h = 1469598103934665603n;
for (const c of s) h = ((h ^ BigInt(c.charCodeAt(0))) * 1099511628211n) % p;
return h === 0n ? 1n : h;
};
const expMod = (base, exp, mod) => {
let r = 1n, b = base % mod, e = exp;
while (e > 0n) {
if (e & 1n) r = (r * b) % mod;
b = (b * b) % mod;
e >>= 1n;
}
return r;
};
const S_A = ["alice-at-example.com", "bob-at-example.com", "carol-at-example.com"];
const S_B = ["dave-at-example.com", "bob-at-example.com", "carol-at-example.com"];
const a = 0xC0FFEEn, b = 0xBADCAFEn;
const A1 = S_A.map(x => expMod(H(x), a, p)); // Alice -> Bob
const B1 = S_B.map(y => expMod(H(y), b, p)); // Bob -> Alice
const A2 = A1.map(v => expMod(v, b, p)); // Bob blinds Alice's set
const B2 = B1.map(v => expMod(v, a, p)); // Alice blinds Bob's set
// Reveal intersection by matching doubly-blinded values
const setA2 = new Set(A2.map(String));
const intersection = S_B.filter((_, i) => setA2.has(String(B2[i])));
console.log("Intersection:", intersection); Press Run to execute.
The protocol does work. It gives semi-honest security under DDH and costs group exponentiations per side, plus the same again to blind the received set. In a balanced setting -- two sets of similar size, perhaps a few thousand elements each -- it is genuinely deployable.
The three things that go wrong at scale
For breach checking, the protocol breaks in three documented ways.
Set-cardinality leakage. The shuffled lists Alice and Bob send each other have lengths and . Bob learns precisely how many passwords Alice has saved; Alice learns precisely how big Bob's breach corpus is. The first leak is small but real; the second is fine when the server publishes its corpus size anyway (HIBP does), but the protocol does not hide it.
Online-cost asymmetry. The server pays exponentiations per client query. At the five-billion-element scale of Microsoft's compromised-credential corpus, no realistic group exponentiation cost makes this feasible per query: even at 100 microseconds per exponentiation (optimistic for ), five billion exponentiations is more than five days of single-core CPU. Sharding helps. Caching helps. Pre-computation helps. None makes the asymptotic curve workable as the corpus grows.
No labeled variant. The protocol returns set membership, not associated metadata. Edge Password Monitor wants to tell you "this credential appeared in breach X" -- so the protocol has to support associating a server-side label with each set element and returning the label for matched elements. DH meet-in-the-middle does not, without unpleasant extensions.
FNP04: the right idea, wrong substrate
The algebraic alternative arrived in 2004 with Freedman, Nissim, and Pinkas's "Efficient Private Matching and Set Intersection" at EUROCRYPT [11]. The idea is gorgeous. Alice encodes her set as the polynomial whose roots are her set:
Alice encrypts each coefficient of under an additively-homomorphic encryption scheme (Paillier, in the paper). She sends the encrypted coefficients to Bob. Bob homomorphically evaluates for every element of his set and returns the encrypted results. If , then , and after decryption Alice sees a zero in the corresponding position. If , then is a non-trivial polynomial evaluation that, randomized correctly, decrypts to a uniform value Alice cannot interpret.
This is the first asymmetric PSI -- the first protocol where one party can do most of the work while the other sends only a small encrypted query. It is also, in deployment terms, structurally infeasible at scale. Paillier ciphertexts live in and are bits each [12] (2048 bits for FNP04's default; 4096 bits for the that modern security demands). Paillier homomorphic evaluation needs full-size modular exponentiation per coefficient, and the server compute scales as . At Edge Password Monitor's target scale -- a client set of a few hundred passwords against a five-billion-element server corpus -- a single query would take minutes to hours of server compute and tens of megabytes of round-trip data per query.
The 5-billion-element estimate is INFERRED, not measured (see §2 for the article-wide projection disclosure). No published source benchmarks FNP04 at that scale; the inference combines the asymptotic with measured Paillier throughput on commodity hardware. The order-of-magnitude conclusion is sound; treat the precise number as a back-of-envelope. The polynomial-roots idea is not dead. Thirteen years later, Chen, Laine, and Rindal will revive exactly this construction inside CLR17 [13], with Paillier replaced by BFV-style somewhat-homomorphic encryption and a partition-and-evaluate trick that fixes the blow-up. The structure survives; the substrate gets swapped.| Protocol | Era | Server cost | Communication | Verdict at 5B-element scale |
|---|---|---|---|---|
| DH meet-in-the-middle [8] | 1999 | $O( | S_B | )$ DH exponentiations |
| FNP04 [11] | 2004 | $O( | S_A | \cdot |
| (preview) HE-PSI on BFV [13] | 2017 | $O( | S_B | \log |
FNP04's polynomial idea will turn out to be the right idea -- but only after we replace Paillier with somewhat-homomorphic encryption thirteen years later. Before we can get there, we need a different breakthrough: making the underlying oblivious-transfer primitive cheap enough that every PSI in the literature can ride on it.
4. The evolution: oblivious transfer extension
Here is the central fact that drove a decade of cryptographic engineering: every PSI protocol that scales eventually reduces to "many oblivious transfers." OT is the universal building block. Once you can do millions of OTs per second, you can do nearly any two-party secure computation, including PSI. The question is how cheap "many OTs" can become.
A two-party primitive. In 1-out-of-2 OT, the sender holds two messages , the receiver chooses a bit , and after the protocol runs the receiver learns while the sender learns nothing about . OT is universal -- it suffices for secure two-party computation of any function -- and it is also expensive: implemented directly from public-key primitives, each OT costs at least one Diffie-Hellman exponentiation, on the order of a millisecond per OT on commodity hardware.
A two-phase protocol that performs OTs at the cost of "base" OTs (typically , implemented with public-key crypto) plus symmetric primitive calls. Because is small and constant, the per-OT cost drops from public-key cost (~1 ms) to symmetric-crypto cost (~100 ns) -- roughly three orders of magnitude, and the asymptotic gap widens with .
Generation 1: IKNP03
In 2003, Yuval Ishai, Joe Kilian, Kobbi Nissim, and Erez Petrank published "Extending Oblivious Transfers Efficiently" at CRYPTO 2003 [14].
Ishai and Petrank are at Technion; Kilian and Nissim were at NEC Labs America at the time. The construction is short enough to summarize in one paragraph and important enough to be called the OT extension: start with "base" OTs done the expensive way (one public-key operation each), then use them to seed pseudorandom generators and a clever transposition trick that, with hash-function calls, produces effective OTs. The base cost stays fixed at public-key operations; the per-OT marginal cost collapses to a few hash invocations.
The numerical impact: before IKNP, secure-computation researchers cited oblivious-transfer cost in milliseconds; after IKNP, in hundreds of nanoseconds. Three orders of magnitude is the difference between "research artifact" and "this protocol can ship."
IKNP03 has no IACR ePrint preprint; ePrint 2003/052 is a different paper by different authors (Klima, Pokorny, Rosa). Cite Springer LNCS only [14].Generation 2: KOS15
IKNP03 is secure against a semi-honest adversary -- one who follows the protocol but tries to learn extra information from the transcript. Real-world deployments often need active security: protection against an adversary who deviates to extract information or bias the output.
In 2015, Marcel Keller, Emmanuela Orsini, and Peter Scholl published "Actively Secure OT Extension with Optimal Overhead" [15]. The construction adds a correlation-check phase on top of IKNP03 that catches active deviations with overwhelming probability. The paper's own abstract: "no more than 5% more time than the passively secure IKNP extension, in both LAN and WAN environments, and thus is essentially optimal with respect to the passive protocol." Modern implementations (libOTe, EMP-toolkit, MP-SPDZ) report on the order of 10-20% wall-clock overhead and 5-10% communication overhead over semi-honest IKNP03 in production -- the "optimal overhead" in the title is the claim that this margin vanishes as the OT count grows.
After KOS15, "active security is free" became the industry default. Every modern OT-extension library -- libOTe, EMP-toolkit, MP-SPDZ -- ships KOS15 (or a close variant) as the production-grade default. The earlier semi-honest-only choice is a research artifact.
Generation 3: Silent OT
A protocol primitive that, given a short shared seed, lets two parties locally expand the seed into long correlated random strings -- in the OT case, the random correlations needed to "consume" each OT call. Once the seed is exchanged, no further communication is needed to produce more OTs; the parties simply expand more locally. PCGs reduce the per-OT wire cost to zero in the post-seed phase.
The numerical impact this time is bandwidth. Pre-Silent-OT, OT-extension protocols sent on the order of bits per OT. Silent OT sends a polylogarithmic amount of data total for the entire extension. The precursor construction "Compressing Vector OLE" by Boyle, Couteau, Gilboa, and Ishai [17] laid the algebraic foundation.
For Edge Password Monitor's deployment shape (small client set, large server set), Silent OT does not land in the production protocol -- HE-PSI provides the asymmetric communication scaling -- but its existence in 2019 is part of why the industry treats OT extension as essentially solved engineering and feels free to ride a higher-layer protocol on top.
The OPRF-PSI plateau: KKRT16
Pure OT-extension is one substrate; the other is the Oblivious Pseudorandom Function.
A two-party protocol in which the sender holds a key , the receiver holds an input , and after the protocol the receiver learns while the sender learns nothing about . The receiver gets the PRF output without giving up the input; the sender keeps the key without giving up the output. OPRFs are the building block under most modern PSI: each party evaluates the OPRF on their set, then plaintext-compares the outputs.
In 2016, Vladimir Kolesnikov, Ranjit Kumaresan, Mike Rosulek, and Ni Trieu published "Efficient Batched Oblivious PRF with Applications to Private Set Intersection" at CCS 2016 [18]. The paper builds a batched OPRF directly on top of KOS-style OT extension. The reported benchmark: intersecting two -element sets on a LAN took about 3.8 seconds total. For several years, KKRT16 was the deployment-grade symmetric-PSI protocol.
KKRT16 is great if your two sets are roughly the same size. The Edge Password Monitor problem is fundamentally asymmetric -- the client holds a few hundred saved passwords, the server holds billions of breached credentials. For asymmetric PSI, the OT-extension lineage hits a wall the next generation has to climb.
Diagram source
flowchart LR
A["Kappa base OTs
(public-key)"] --> B["IKNP03 extension
(symmetric)"]
B --> C["KOS15 active security"]
C --> D["Silent OT
(PCG-based)"]
B --> E["KKRT16 OPRF-PSI"]
C --> F["CHLR18 HE-PSI
+ OPRF wrapping"]
D --> G["Modern OT-extension libraries:
libOTe, EMP-toolkit"]
E --> H["Symmetric balanced PSI"]
F --> I["Edge Password Monitor"] 5. The breakthrough: HE-based PSI
Asymmetric PSI requires that the server's heavy compute stays on the server, and that the client send only a tiny encrypted query whose size is independent of . That is exactly what fully homomorphic encryption -- or, more precisely, somewhat-homomorphic encryption -- can offer.
An encryption scheme is homomorphic if operations on ciphertexts decrypt to the corresponding operations on plaintexts. Somewhat-homomorphic encryption (SWHE) supports a bounded depth of operations (typically additions and multiplications) before noise growth requires re-encryption. Fully homomorphic encryption (FHE) supports arbitrary-depth circuits via bootstrapping. The BFV scheme (Brakerski-Fan-Vercauteren), implemented in Microsoft SEAL [19], is the SWHE variant Edge Password Monitor uses; FHE is the popular term but the actual deployed circuit depth fits comfortably within SWHE.
CLR17: the cost curve flips
In 2017, Hao Chen, Kim Laine, and Peter Rindal published "Fast Private Set Intersection from Homomorphic Encryption" at CCS 2017 [13]. The construction is a clean revival of FNP04's polynomial-roots idea, with three engineering moves that fix every reason FNP04 was infeasible.Move 1: SWHE instead of Paillier. BFV ciphertexts pack many plaintext slots and support SIMD-style homomorphic operations. A single ciphertext can encrypt and evaluate over thousands of plaintext values in parallel; the slot count is set at scheme-parameter time.
Move 2: Cuckoo hash partitioning. The receiver Cuckoo-hashes its set into bins. The sender hashes each element of to the same set of bins. Instead of one giant polynomial whose roots are all of , the sender builds one small polynomial per bin -- typically a few thousand bins, each holding a few hundred elements.
A hashing scheme that uses hash functions and inserts each element into one of candidate bins, displacing existing occupants if necessary (the displaced element finds another of its candidate bins). Cuckoo hashing achieves worst-case lookup; the achievable load factor depends on the number of hash functions and the bucket size -- roughly 49% with (the original Pagh-Rodler 2001 construction [20]), roughly 91% with , and higher with a stash of evicted elements or . CLR17 and CHLR18 use parameter choices in the high-load regime. In CLR17, Cuckoo hashing pairs the receiver's set with the sender's set so that two equal elements end up in the same bin with overwhelming probability.
Move 3: Partition-and-evaluate. The receiver encrypts its bins under BFV and sends them. The sender homomorphically evaluates its per-bin polynomial at the encrypted receiver's bin. Because of SIMD slot packing, each bin's polynomial is evaluated in parallel across all slots, and the sender's total work is FHE operations instead of FNP04's .
The headline benchmark from the paper, on the MSR publication page: "36 seconds of online-computation and 12.5 MB of round trip communication to intersect five thousand 32-bit strings with 16 million 32-bit strings" [21]. Communication scales linearly in the small set and logarithmically in the large set. The cost curve is finally right.
Diagram source
sequenceDiagram
participant C as Client (Edge)
participant S as Server (Microsoft)
Note over C,S: stage 1 -- OPRF preprocessing (binds queries to server's secret key)
C->>S: blinded credential beta * H(cred)
S->>C: alpha * (blinded H(cred)) using server key alpha
C->>C: unblind, obtain F_alpha(cred)
Note over C,S: stage 2 -- HE-PSI on sharded corpus
C->>S: BFV ciphertext encrypting F_alpha(cred), sharded by 2-byte prefix
S->>S: Cuckoo-hash shard, evaluate per-bin polynomial homomorphically
S->>C: encrypted match result + label ciphertext
C->>C: decrypt result, then if match surface breach metadata CHLR18: labeled, malicious, deployable
Labels. Each element in the server's set can carry an associated label (which breach, when, severity). When the receiver finds a match, they also recover the label.
Malicious security. The protocol is secure against an actively malicious sender, layered on top of the underlying semi-honest construction via an OPRF preprocessing step. The OPRF is the same primitive we met in §4; here it does double duty: it prevents the client from brute-forcing the server's corpus offline (the client cannot evaluate without server interaction) and provides the malicious-security guarantee.
Arbitrary-length items. The protocol handles long inputs (full URLs plus usernames, in the breach-checking case), not just short fixed-width keys.
The headline benchmark: "for an intersection of and 512 size sets of arbitrary length items our protocol has a total online running time of just 1 second (single thread), and a total communication cost of 4 MB" [23]. A larger benchmark of and 1024 takes 12 seconds multithreaded with less than 18 MB of communication.
Cong et al. 2021: the production-grade successor
The protocol that ships in Edge Password Monitor today is the descendant published by Kelong Cong, Radames Cruz Moreno, Mariana Botelho da Gama, Wei Dai, Ilia Iliashenko, Kim Laine, and Michael Rosenberg at CCS 2021: "Labeled PSI from Homomorphic Encryption with Reduced Computation and Communication" [24]. The paper is the basis for Microsoft's open-source APSI library [25], whose README states verbatim that it "provides a PSI functionality for asymmetric set sizes based on the protocol described in eprint.iacr.org/2021/1116" and that it "uses the BFV encryption scheme implemented in the Microsoft SEAL library."
The Cong et al. 2021 byline is seven authors: Kelong Cong, Radames Cruz Moreno, Mariana Botelho da Gama, Wei Dai, Ilia Iliashenko, Kim Laine, Michael Rosenberg. Some upstream reporting conflates a different author list onto the same URL; the citation_author meta-tags returned by ePrint 2021/1116 confirm this seven-author septuple [24].The OPRF wrapping and corpus sharding
Two practical layers on top of the bare HE-PSI protocol turn the academic construction into a production deployment, and the Microsoft Research Password Monitor blog is explicit about both [1].
First, the OPRF preprocessing. Without it, a malicious client could send candidate passwords one at a time and observe match results, brute-forcing the server's corpus. With it, every client query passes through where is a server secret. The MSR blog states: "the client communicates with the server to obtain a hash of the credential, where denotes a hash function that only the server knows... using an OPRF... the client is prevented from performing an efficient dictionary attack on the server" [1].
Second, corpus sharding. The MSR blog notes that the corpus is sharded by the first two bytes of a username-hash. The blog's verbatim example: "Suppose the database consists of 4 billion credentials, then after sharding each subset, it will contain about 60,000 credentials on average." At the article's 2026 5-billion projection the math is the same -- corpus divided by -- and per-shard work is closer to 76,000 credentials. Either way, the per-query homomorphic evaluation runs against tens of thousands of credentials instead of the full corpus. This is the same engineering trade as Apple's 15-bit bucketing -- a small information leak (the client reveals which shard their query lives in) in exchange for tractable per-query compute.
A Windows facility, introduced in Windows 2000, that encrypts arbitrary blobs under a user-derived key chain (ultimately rooted in the user's password, with hardware-bound variants under DPAPI-NG) and exposes a simple CryptProtectData / CryptUnprotectData API [26]. Browsers including Chromium store the symmetric key that wraps their saved-password database under DPAPI at rest. This protects the on-disk database when the user is not logged in, but it does not protect process memory after the same user has unwrapped the data into a running browser.
"This unique security feature is possible due to pioneering cryptography research and technology incubation done here at Microsoft Research." -- Microsoft Research, January 21, 2021 [1]
The administrator-visible group policy that controls this feature is PasswordMonitorAllowed, documented on Microsoft Learn [27].
Asymmetric PSI on somewhat-homomorphic encryption flips the cost curve so that communication scales with the small client set, not the enormous server set. That is why a homomorphic-encryption protocol can ship on a consumer browser in 2021 without melting the user's CPU. The cryptographic case for Edge Password Monitor is auditable down to the published papers and unequivocally well-engineered.
Microsoft has shipped the first production consumer homomorphic-encryption deployment in a browser, against the threat "server-side breach corpus leakage," on the same browser that, in §7, will turn out to hold every saved credential in plaintext RAM the entire time you have it open. To make sense of that contrast, we need to see what the rest of the industry did with the same problem.
6. State of the art: four deployed compromised-credential services
PSI on paper is one thing. PSI in production is another. The "pure PSI" ideal -- both parties learn the intersection and nothing else, no information leaks on either side -- is impractical at planetary scale. Every deployed compromised-credential service in 2026 makes a concession somewhere.
The four services compared here are HIBP Pwned Passwords v3, Google Password Checkup, Apple Password Monitoring (iCloud Keychain), and Microsoft Edge Password Monitor. A fifth, Signal contact discovery, is technically a contact-discovery service rather than a breach checker, but it sits on the same protocol map and is the canonical "we used a TEE instead of pure crypto" data point.
| Service | Protocol family | What's revealed on the wire | Server trust | Bandwidth at scale | Dictionary-attack hardening |
|---|---|---|---|---|---|
| HIBP Pwned Passwords v3 [28] | Pure SHA-1 5-hex-char k-anonymity | A 20-bit hash prefix per query | None (zero-trust API) | Trivial (a few KB per query) | None on the wire; SHA-1 hash makes corpus searchable |
| Google Password Checkup [29] | k-anonymity + blinded-hash OPRF | A small hash prefix per query | Honest-but-curious | Tens of KB per query | OPRF prevents corpus enumeration by the client |
| Apple Password Monitoring [30] | EC-based PSM on NIST P-256 + 15-bit bucket | A 15-bit prefix + double-blinded EC point | Honest-but-curious | A few hundred KB per query (padded) | OPRF + double-blinding + padding-to-fixed-count |
| Signal contact discovery (2017) [31] | SGX enclave + ORAM (no pure crypto) | Nothing visible to Signal staff | TEE attestation | Negligible (single SGX RPC) | Enclave isolation rather than crypto hardening |
| Microsoft Edge Password Monitor [1] | HE-PSI on Microsoft SEAL + OPRF + 2-byte shard | 2-byte username-hash prefix + BFV ciphertext | Honest-but-curious | Single MB-range round trip | OPRF binds queries to server key; HE prevents transcript leaks |
HIBP Pwned Passwords v3: the k-anonymity baseline
Troy Hunt's "Have I Been Pwned" launched in 2018 with the help of Junade Ali at Cloudflare; the design is published in two posts, Hunt's "I've Just Launched Pwned Passwords Version 2" and Ali's "Validating Leaked Passwords with k-Anonymity" [10][32]. The protocol is delightfully simple: the client hashes the candidate password under SHA-1, sends the first 5 hex characters (20 bits) of the hash to the API, and the API returns every suffix in that bucket. The client compares locally.
A privacy property: each query produces output that is consistent with at least other potential queries the client could have made. In the HIBP context, is the number of distinct password hashes that share the same 20-bit SHA-1 prefix -- typically a few hundred. The server learns the bucket but not which specific password the client cares about, and (because hashes are sparse over the prefix space) cannot easily distinguish "the user has password X" from "the user has password Y" if X and Y share the prefix.
The HIBP corpus serves "18B+ Monthly Requests" against roughly a billion hashes [33]. Operationally, this is a one-shot HTTP GET. There is no PSI on the wire beyond TLS. The whole protocol fits on the back of an envelope. The cost: each query leaks the 20-bit prefix, which is enough to identify the user's password if the attacker has independent information narrowing the candidate space.
async function sha1Hex(s) {
const buf = new TextEncoder().encode(s);
const hash = await crypto.subtle.digest("SHA-1", buf);
return [...new Uint8Array(hash)].map(b => b.toString(16).padStart(2, "0")).join("").toUpperCase();
}
async function showBucket(password) {
const h = await sha1Hex(password);
const prefix = h.slice(0, 5); // 5 hex chars -- 20 bits sent to server
const suffix = h.slice(5);
console.log("Password:", password);
console.log("SHA-1: ", h);
console.log("Prefix (leaves your device):", prefix);
console.log("Suffix (compared locally): ", suffix);
console.log("Approx bucket size: ~", Math.round(847_223_402 / (1<<20)), "entries");
}
showBucket("hunter2"); Press Run to execute.
The mental model the runnable above gives is the precise shape of the trade. Every HIBP query says "I am asking about a password whose SHA-1 starts with these 20 bits." There are roughly possible prefixes, so each query narrows the server's posterior over your password by exactly that much.
Google Password Checkup: k-anonymity with an OPRF on top
In August 2019, Kurt Thomas and colleagues at Google published "Protecting Accounts from Credential Stuffing with Password Breach Alerting" at USENIX Security [29]. The accompanying blog post on the Google Security Blog announces the deployment [34]. The numbers are familiar at this point: "a cloud service that mediates access to over 4 billion credentials found in breaches and a Chrome extension serving as an initial client. Based on anonymous telemetry from nearly 670,000 users and 21 million logins, we find that 1.5% of logins on the web involve breached credentials" [29].
The protocol upgrades HIBP's k-anonymity baseline with an OPRF preprocessing round: instead of hashing under SHA-1 locally and sending the prefix, the client first obtains via an OPRF interaction, where is a Google-held key. The OPRF output is then bucketed and matched against Google's corpus. The OPRF prevents the client from enumerating Google's corpus offline; the bucketing limits per-query server work.
Apple Password Monitoring: PSM with double-blinding
Apple's protocol is the most cryptographically elaborate of the four. The Apple Platform Security guide is unusually explicit [30][35]. From the guide, verbatim: "a form of cryptographic private set intersection is deployed that compares the users' passwords against a large set of leaked passwords"; the corpus is "approximately 1.5 billion passwords... into different buckets"; and the protocol uses elliptic-curve PSM on NIST P-256 with a double-blinded structure.
The math, slightly compressed. Let be the Shallue-van de Woestijne-Ulas hash-to-curve.
Google publishes an open-source PSM construction at google/private-membership [36]; Apple's protocol shares the EC double-blinding skeleton. Apple computes a per-corpus-element representation:
where is a secret random key known only to Apple. The client computes its query:
with chosen randomly per-query. The interaction lets the client recover and check it against a 15-bit bucket of values. The double-blinding is the point: stays Apple's secret (so the client cannot enumerate); stays per-query random (so Apple cannot link two queries from the same client).
Apple's PSM defends also against the server learning how many unique passwords a user has, by padding-to-fixed-count with random queries: "if a user has fewer than this number, random passwords are generated and added to the queries to make up the difference" [30]. None of the other four services deploys this defence. The padding cost is the price.Signal contact discovery: the TEE outlier
In September 2017, Moxie Marlinspike published "Technology Preview: Private Contact Discovery" on Signal's blog [31]. The post is candid about the cost calculation that drove Signal toward Intel SGX rather than pure cryptographic PSI:
"Signal clients will be able to efficiently and scalably determine whether the contacts in their address book are Signal users without revealing the contacts in their address book to the Signal service." -- Moxie Marlinspike, September 2017 [31]
Marlinspike is explicit about the cost calculation: "Doing better is difficult. There are a range of options that don't work... like using bloom filters, encrypted bloom filters, sharded bloom filters." Signal examines pure cryptographic PSI and decides, given its scale and latency requirements, that an SGX enclave running a constant-time ORAM-protected lookup is the better engineering trade [37].
Microsoft Edge Password Monitor
The Microsoft deployment is the only one shipping a full HE-PSI protocol on the wire against the full corpus. As established in §5, the protocol stack is:
- Two-byte username-hash shard selection (corpus partitioned, sender does work only against tens of thousands of elements per query -- the MSR blog's 2021 example uses 4 billion / 60,000; the article's 2026 5-billion projection yields 76,000).
- OPRF preprocessing (binds queries to a server secret; prevents client-side enumeration).
- BFV-encrypted query, evaluated against the Cuckoo-hashed per-bin polynomials, returned as a single ciphertext per shard.
- Client decrypts; if matched, decrypts the associated label (the breach metadata).
All four moving parts are described in the MSR blog, the Cong et al. 2021 paper, and the open-source APSI library [1][24][25]. Communication scales with the small client set; sender compute scales with the (sharded) server set. The Microsoft Edge enterprise documentation says the feature "helps Microsoft Edge users protect their online accounts by informing them if any of their passwords are found in an online leak" [27].
Four products, four concessions
| Service | Primary concession | What it defends against | What it does not |
|---|---|---|---|
| HIBP | 20-bit prefix leak per query | Server learning the password | A linkage attack on repeated queries |
| Google PCU | OPRF transcript + prefix | Client-side corpus enumeration | Server-side query inference if the prefix is rare |
| Apple PSM | 15-bit bucket + double-blinding overhead | Both client and server enumeration; query linkage | Side-channels on the EC implementation |
| Signal CDS | TEE attestation trust | Server-side mass-data exfiltration | SGX side-channel attacks |
| Edge PM | 2-byte shard leak + OPRF transcript | Anything short of breach corpus leakage from inside Microsoft | Endpoint compromise -- see §7 |
Four products. Four different concessions. Each is internally coherent. None of them solves a problem that Tom Joran Sonstebyseter Ronning's PoC will turn out to make trivial.
7. The other half: plaintext RAM "by design"
Now we turn the article inside out.
Everything we have built so far -- IKNP, KOS, KKRT, CLR17, CHLR18, Cong et al., Apple's PSM, Google's k-anonymity wrapping, the entire CCS-grade cryptographic stack inside Edge -- assumes the endpoint is trustworthy. The question Ronning asked on May 4, 2026 is what happens when it is not.
The disclosure
The X post arrived at 14:29:51 UTC on May 4, 2026 [2]: "Microsoft Edge loads all your saved passwords into memory in cleartext -- even when you're not using them." Five hours later the GitHub repository went public, with a complete C# proof-of-concept and a long README [3]. PCWorld picked up the story two days later under the byline of Laura Pippig, summarising Microsoft's response in English [42]. The Norwegian origin, ITavisen, carried the verbatim "by design" rendering and named Ronning's affiliation with the transmission-system operator Statnett [43]. Davey Winder at Forbes reached Microsoft and obtained the official spokesperson statement on May 6, 2026 [4].
Ronning works at Statnett and presented this finding at BigBiteOfTech (Palo Alto Networks Norway) on April 29, 2026 -- five days before the public X-post disclosure [43]. The X bio describes "#PenetrationTesting using only tools that are already on the system."What the PoC does
The C# program is short. OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, ...) against the parent msedge.exe. A walk over committed memory regions via VirtualQueryEx. ReadProcessMemory reads of every region. Pattern matching for stored credential structures. Output: every saved Edge password as plaintext.
The README is explicit on the constraints. "Can be run without Adminstrator rights, but will only be able to access Edge processes ran by the same user. If run with Administrator privileges, the program can access and read memory from other users' Edge processes on the same machine" [3]. No kernel exploit. No DPAPI bypass. The DPAPI unwrap happened earlier, when Edge launched (or when the password feature first activated); the cleartext has been sitting in msedge.exe's heap ever since.
The tested target is Edge 147.0.3912.98, but the README explicitly generalises: "Any Edge versions that's Chromium based (from version 79 and newer, including 147.0.3912.98 and any future version, as Microsoft won't change this feature)" [3].
What the architectural choice is
The behaviour Ronning identifies is not a memory-safety bug. It is a design choice: Edge unwraps every DPAPI-protected saved credential into process memory when the password manager activates, and keeps the plaintext resident for the lifetime of the session.
Diagram source
flowchart TD
A["Saved password file
(SQLite blob)"] -->|"DPAPI-wrapped at rest"| B["Disk: encrypted with
per-user DPAPI key"]
B -->|"msedge.exe launches"| C["DPAPI CryptUnprotectData()
unwraps key"]
C -->|"password manager activates"| D["Plaintext credentials
resident in msedge.exe heap"]
D -->|"OpenProcess + ReadProcessMemory
(same-user, no admin)"| E["EdgeSavedPasswordsDumper
reads cleartext"]
D -->|"autofill flow"| F["Plaintext copied into
renderer / web form"]
style D fill:#fee,stroke:#c33
style E fill:#fcf,stroke:#939 Chrome and Brave do not do this. Both browsers decrypt credentials only at the autofill RPC -- the password manager fetches the DPAPI-wrapped blob, decrypts in a narrow window, hands the plaintext to the relevant renderer, and zeroes the buffer [44]. PCWorld corroborates: "Other password managers, including those that are built into browsers, don't operate in this way -- Ronning says Edge is the only Chromium-based browser he's tested with this behavior" [42].
In July 2024, Google announced Chrome App-Bound Encryption -- a further hardening of exactly this same-user-LCE threat model. ABE binds the on-disk key unwrap to a verified Chrome process identity, so a malicious program impersonating Chrome cannot ask DPAPI to unwrap Chrome's data even if it runs as the same user [45]. Microsoft has the same DPAPI substrate; Edge has not adopted the equivalent control.
The .NET runtime tie-in to AMSI
The PoC's original implementation language is a noteworthy detail. Ronning's README states: ".NET Framework 4.8.1 (changed from 3.5 originally)" [3]. The original .NET 3.5 choice was deliberate. The Antimalware Scan Interface (AMSI) [46] scans .NET 4.8+ assemblies before execution; .NET 3.5 predates AMSI's Amsi* API surface entirely [47].
Microsoft's response, verbatim
"Safety and security are foundational to Microsoft Edge. Access to browser data as described in the reported scenario would require the device to already be compromised. Design choices in this area involve balancing performance, usability, and security, and we continue to review it against evolving threats. Browsers access password data in memory to help users sign in quickly and securely -- this is an expected feature of the application. We recommend users install the latest security updates and antivirus software to help protect against security threats." -- Microsoft spokesperson, via Forbes, May 6, 2026 [4]
The statement is technically defensible. The threat model is exactly what the spokesperson says: an attacker who can already execute code as the user on the user's machine. In MSRC's published servicing criteria [48], "exploitation requires local code execution" is a recurring boundary line -- the same line MSRC applied to Mimikatz against LSASS in the pre-Credential-Guard era, and that Microsoft eventually crossed by shipping Credential Guard. The "by design" framing is consistent with a decade of precedent.
Edge does not have a credential-storage vulnerability. Edge has a credential-storage architectural choice. The choice is to spend the entire browser session's worth of plaintext-in-RAM budget on autofill UX latency. The choice is defensible. It is also a precise statement of which threats the Edge product team is and is not defending against.
Microsoft's response is technically defensible. It is also a precise statement of which threat model the Edge product team is and is not defending against. To see why both halves of this article describe the same product, we need to look at the architectural alternatives.
8. Competing approaches: where should the secret store live?
Three architectural positions present themselves, as siblings rather than as a generational ladder:
- Browser-as-secret-store, decrypt-on-launch (Edge today). Plaintext-in-RAM window: the entire session. Autofill latency: a memcpy.
- Browser-as-secret-store, decrypt-on-autofill (Chrome, Brave). Plaintext-in-RAM window: the autofill RPC. Autofill latency: one DPAPI unwrap per fill (microseconds).
- OS-as-secret-broker (the design the Windows Credential Manager and DPAPI-NG already implement for native apps). Plaintext never crosses into the browser's process; a higher-privileged broker holds the plaintext at autofill time and the browser receives a handle, not the secret.
Diagram source
flowchart LR
subgraph "Decrypt-on-launch (Edge)"
A1[Disk: DPAPI blob] --> A2[Browser process
plaintext, full session]
A2 --> A3[Renderer: autofill memcpy]
end
subgraph "Decrypt-on-autofill (Chrome / Brave)"
B1[Disk: DPAPI blob] --> B2[Browser process
plaintext, narrow RPC]
B2 --> B3[Renderer: autofill]
end
subgraph "OS-as-secret-broker"
C1[Disk: DPAPI-NG blob] --> C2[OS broker process
plaintext only here]
C2 -.handle.-> C3[Browser receives handle]
C3 -.autofill via broker.-> C4[Renderer]
end Six-axis comparison
| Axis | Decrypt-on-launch (Edge) | Decrypt-on-autofill (Chrome, Brave) | OS-as-broker |
|---|---|---|---|
| Plaintext-in-RAM window | Full session | Autofill RPC (~ms) | Never, in the browser process |
| Autofill latency | Memcpy (nanoseconds) | DPAPI unwrap (~10s of microseconds) | IPC + broker policy check (~ms) |
| Same-user-LCE attack surface | High (ReadProcessMemory exposes all) | Low (must catch the RPC window) | Negligible (no plaintext in the browser) |
| Memory-scraping forensics | Trivial (any same-user dump works) | Hard (must dump during fill) | Impossible (no plaintext to dump) |
| Sync UX with cloud account | Standard | Standard | Standard (broker handles sync) |
| Engineering cost to ship | Already shipped | Already shipped (Chromium baseline) | High (broker IPC, signed code path, extension renegotiation) |
The OS-broker position is not hypothetical. The Windows Credential Manager already provides this property for Windows-app credentials. WebAuthn and passkeys provide it for sites that have adopted the standard. The DPAPI-NG protection descriptors include a WEBCREDENTIALS= variant [26][49]. Pluton-anchored vTPM key unwrap provides a hardware-rooted broker substrate [50]. Credential Guard's LSAISO trustlet is architecturally an isolated secret-broker for LSASS-derived secrets [51].
None of these primitives are wired into Edge's saved-passwords path. The engineering cost is non-trivial: the broker needs an IPC contract, the browser needs a signed-and-attested code path that talks to the broker, and the renderer extension API surface needs renegotiation. But the cost is finite, and the alternative is what Google has been shipping in Chrome since 2024 -- Chrome's App-Bound Encryption (see §7) is exactly a step toward the broker model, and Microsoft has the same DPAPI substrate but no equivalent control for Edge [45].
What "by design" means structurally
Microsoft can take the "by design" position because they are not wrong about cryptography. They are right about the bound. No protocol can autofill plaintext into a child renderer without some process in the chain holding plaintext at the moment of fill. The architectural question is which process and for how long.
Edge's answer: "the parent browser process, for the entire session." Chrome and Brave's answer: "the parent browser process, for the autofill RPC." The broker design's answer: "a separate, higher-privileged process, for the autofill RPC, and never the browser at all."
All three are valid points in the design space. The question is not "which is right" -- the answer depends on the user's environment -- but "what should the default be for a 2026 consumer browser." The PSI half of the article shows Microsoft can choose the most demanding default when they want to. The endpoint half shows what default they chose here.
To see why this is a structural property of the problem, not a Microsoft-specific gap, we need to look at the theoretical limits on both sides.
9. Theoretical limits
Two lower bounds, in parallel: one cryptographic (the PSI side), one architectural (the endpoint side).
PSI side: communication and computation lower bounds
The communication lower bound for PSI is folklore, used as the comparison baseline in Pinkas-Schneider-Zohner at USENIX Security 2014 [52]. Informally: any PSI protocol must transmit at least bits, where is the security parameter. The argument is information-theoretic: the receiver has to learn the intersection, which can have size up to , and each element identifier needs bits of representation to avoid collisions.
Silent OT [16] meets this lower bound up to polylogarithmic factors in the symmetric balanced setting. HE-PSI in the asymmetric setting gets to ciphertexts via CLR17's partition-and-evaluate construction [13], which is sublinear in -- the breakthrough that makes Edge Password Monitor practical.
The computation lower bound on the sender side is . The sender must, in the limit, touch each element of its set at least once per query. There is no way around this without trading correctness or privacy. Apple "cheats" by reducing the effective : their 15-bit bucket cuts the per-query work to roughly elements. Microsoft's two-byte shard cuts to roughly elements. The lower bound applies per shard, not per total corpus.
The OT-extension lower bound is base OTs per protocol session, with the bulk of the OT count amortised away by symmetric crypto. KOS15 meets this; Silent OT improves the wire constants further. By 2026, OT extension is essentially solved engineering.
Endpoint side: the "no plaintext in process" lower bound
The cryptographic side is comfortably tight. The endpoint side is much weirder.For a process to autofill a credential into a child form, some component in the trust chain must hold the plaintext at the moment of fill. There are exactly three possible holders:
- itself. The Edge design. Plaintext lives in the parent browser process throughout the session.
- A child renderer . The Chrome / Brave design. Plaintext crosses the parent-renderer boundary for the duration of the autofill RPC and gets zeroed.
- A separate higher-privileged broker . The OS-broker design. Plaintext lives in a sibling process that is harder to dump than the browser (in the limit, a PPL or a Credential-Guard-style trustlet).
No general cryptographic primitive lets a process use a plaintext credential without ever holding it. The plaintext is a value; the operations on it (paste-into-form, compute-HMAC-with-it, transmit-over-TLS-as-a-bearer-token) all require it in cleartext at some point. This is not a deficiency of any particular cryptosystem. It is the definition of "use."
The plaintext-RAM design Edge ships is not a cryptographic failure. It is a deliberate choice to spend the plaintext-in-RAM budget on UX latency. The escape hatch is architectural: a hardware-isolated broker process. Pluton-anchored vTPM key unwrap [50], Credential Guard's LSAISO pattern [51], DPAPI-NG with the right protection descriptor [49] -- the OS primitives all exist.
There is no cryptographic primitive that lets a process autofill plaintext without holding it. The only escape hatch is an architectural one: a higher-privileged broker. Microsoft already ships the broker primitives -- DPAPI-NG, Credential Guard, Pluton. They are not wired into Chromium.
The aha moment the rest of the article was built to deliver: the Ronning PoC is not a "bug" in any meaningful sense. The structural question is whether Microsoft should ship the architectural primitive -- which they already have, in DPAPI-NG and Credential Guard -- but have not wired into Chromium's password store. The "by design" response is technically true and politically convenient simultaneously. Both are correct readings.
Both lower bounds are tight or near-tight today. The PSI side is essentially solved engineering; the endpoint side is essentially solved policy and unsolved deployment. The open questions are about which side we invest in next.
10. Open problems
Four open problems, framed as research directions Microsoft, Apple, and Google have not jointly committed to.
Open problem 1: post-quantum PSI and OT extension
Every deployed breach-checking protocol today rests on assumptions Shor's algorithm breaks. The OPRFs in Apple PSM and Google Password Checkup rely on discrete log over elliptic curves; the HE-PSI in Edge Password Monitor relies on BFV-on-classical-parameters; Paillier (historic, FNP04) relies on integer factorisation. Harvest-now-decrypt-later exposure on durable transcripts is the near-term migration question: an adversary capturing PSI transcripts today and storing them until a cryptographically relevant quantum computer arrives could, in principle, reconstruct the queries.
Lattice-based OT extension exists at currently-secure parameters, at roughly the communication of IKNP per OT in early prototypes. Whether the breach-checking deployments at Microsoft, Apple, and Google migrate on the same timeline as the rest of TLS (the IETF post-quantum-handshake transition) is an open coordination problem.
Open problem 2: multi-party breach corpora
No production deployment of a -party breach-checking service exists. HIBP, Google, Apple, and Microsoft each hold corpora that overlap but contain unique breaches. Consolidating them privately -- so a query gets the union of all four corpora's match metadata without any one provider learning more than their own corpus contributed -- would meaningfully improve detection.
The academic literature on multi-party PSI is substantial and growing, but the engineering and the governance work has not been done. Each provider has a different commercial relationship with the breach dataset, a different legal posture, and a different operational interest in their corpus being canonical. The cryptographic primitive is the easy part.
Open problem 3: sub-linear sender-side amortisation
The sender-side computation lower bound is per query. For a service serving billions of queries against a static , can per-query cost be amortised across queries via a preprocessing step the sender pays once?
Cong et al. 2021 [24] reduces constants substantially and pushes the practical envelope. Sub-linear asymptotic sender-side cost is open. The information-theoretic barrier is real -- the sender must touch any element that could be in the receiver's query -- but the expected cost over many queries against a static corpus admits a more aggressive analysis under the right access patterns.
Open problem 4: hardware-broker browser secret stores
The endpoint architectural problem. Migrate Edge, Chrome, and Brave from "process-RAM plaintext" to "OS-broker (plaintext never crosses into the browser)" using DPAPI-NG with a broker-PPL protection descriptor or a Credential Guard-style trustlet.
WebAuthn and passkeys offer this property already -- the platform authenticator holds the private key, and the browser receives signed assertions without ever seeing the secret. But passkeys require per-site enrollment that traditional username-password sites have not adopted at scale; the long tail of legacy login forms will remain on saved-passwords-as-strings for years.
The Windows Credential Manager offers the broker property for Windows-app credentials -- but it is not wired into Chromium for browser credentials. The engineering work is real; the cryptographic work is essentially trivial. Whether and when Microsoft, Google, or Brave commit to it is the question.
| Open problem | What's been tried | Current best | Why it matters |
|---|---|---|---|
| Post-quantum PSI | Lattice-based OT, ring-LWE OPRFs | Prototype-grade; 10x classical at ~secure parameters | Harvest-now-decrypt-later on PSI transcripts |
| Multi-party breach corpora | Multi-party PSI literature (e.g., Kolesnikov et al. CCS 2017) | Academic constructions; no production deploy | Each provider's corpus has unique recall |
| Sub-linear sender cost | Cong et al. 2021 constants reduction | Linear per query | corpus, billions of queries |
| Hardware-broker secret stores | WebAuthn / passkeys; DPAPI-NG, Credential Guard | Standards exist; wiring into browsers is missing | The Ronning PoC threat model |
A simple Chrome App-Bound Encryption check on your machine
Open Chromium's process tree on Windows (Task Manager: Details, group by Path) and look for the Google Chrome.exe (or msedge.exe) process running with the --type= argument absent -- that's the parent. App-Bound Encryption binds the DPAPI unwrap to that exact parent process's signature, so a same-user attacker masquerading as Chrome cannot ask DPAPI to unwrap Chrome's data even with the right user identity. The architectural primitive is sitting in Chrome's source tree as of July 2024 [45]; the equivalent control for Edge's password store has not shipped.
11. Practical guide
What should you do this week?
Users
If your Edge browser is your password manager and you are on a single-user laptop you control end-to-end, the Ronning PoC's threat model is "an attacker who can run code as you on your own machine." If that happens, the attacker is already in a strong position regardless of how Edge holds passwords -- they can keylog the next login, screenshot anything you autofill, or install a malicious browser extension. The marginal risk of the plaintext-RAM design on a single-user laptop is real but bounded.
A dedicated password manager usually still keeps plaintext in its own process RAM during autofill -- this is the §9 lower bound asserting itself. The difference is the size of the plaintext-in-RAM window: dedicated password managers tend to require an explicit unlock and re-lock after a configurable idle period. Edge's window is the entire browser session.
Windows admins
The two relevant Edge enterprise policies are documented on Microsoft Learn:
PasswordManagerEnabled[53] -- turns Edge's saved-passwords feature on or off entirely. On a multi-user host with sensitive data, the right value is0.PasswordMonitorAllowed[27] -- controls whether Password Monitor's breach-checking PSI runs at all. The default is "user-controlled"; in a managed enterprise, you may want to mandatorily enable it (independent of whether the password manager itself is enabled, because Password Monitor can check passwords you type into login forms, not just ones you have saved).
For RDS, AVD, and Citrix environments specifically, the threat model is structurally worse than a single-user laptop. Multiple users share a single Windows host. Their Edge profiles are isolated by Windows ACLs but their processes are not isolated against an administrator. The PoC's "Administrator privileges can access other users' Edge processes" mode is exactly the privilege available to a session-host administrator who has been compromised, or to a malicious tenant who escalates locally.
Developers
If you ship a component that handles credentials, the design lesson from §9 is not "never hold plaintext" -- you cannot avoid it without an OS-level broker -- but "minimise the plaintext-in-RAM window."
The Chrome App-Bound Encryption pattern from July 2024 [45] is a template: bind your at-rest key unwrap to a verified process identity so an attacker who exfiltrates your wrapped data cannot trivially unwrap it from a different process. If you must hold plaintext in the parent process for the lifetime of the session (the Edge design), make the trade explicit in the threat model documentation and ensure operations consuming the plaintext are auditable.
If you can architecturally afford a broker, do it. The IPC cost is real (low-microsecond per call) but small compared to the operational reduction in incident severity. WebAuthn / passkeys are the long-term destination for credentials; the broker pattern is the short-term destination for everything else.
12. Frequently asked questions
Frequently asked questions about Edge's two password cryptographies
Doesn't DPAPI protect the saved passwords?
Yes, at rest on disk. DPAPI wraps the symmetric key that encrypts Edge's Login Data SQLite file under a key chain rooted in the user's password. When the user is logged out (or the machine is powered off), the on-disk blob is opaque to anyone who does not have the user's DPAPI credentials. The protection ends the moment Edge unwraps the DPAPI blob into process memory, which happens during browser launch or the first password-feature activation. Once unwrapped, the credentials sit in msedge.exe's heap until the process exits, and ReadProcessMemory from any same-user process reads them as plaintext. DPAPI is an at-rest control, not an in-memory one.
Couldn't Protected Process Light (PPL) or RunAsPPL fix this?
Partially. If Edge ran as a protected process at an appropriate signature level, only an antimalware-PPL-elevated process could open it for ReadProcessMemory, which would substantially raise the bar against a same-user attacker. Browser-process PPL has implications for every loaded DLL (each must be signed at or above the host's PPL level) and every extension API the renderer expects to call. Chrome and Brave have not adopted PPL for the browser process either. Microsoft has the option; they have not used it. PPL would address the same-user-LCE concern but not the administrator-across-sessions concern.
Doesn't Credential Guard cover browser credentials?
No. Credential Guard isolates LSASS-derived secrets (NTLM hashes, Kerberos tickets, cached credentials) into the LSAISO trustlet running under Virtualization-Based Security, which is unreachable from the normal-world kernel let alone normal-world user-mode processes. It does not cover browser-owned secrets. Saved Edge credentials live in msedge.exe's heap, not in LSASS, and Credential Guard does not extend protection to arbitrary user-mode application secret stores.
Is k-anonymity 'real' PSI?
No, in the strict cryptographic sense. K-anonymity leaks the bucket index by design -- the server learns a 20-bit (HIBP), 15-bit (Apple), or 16-bit (Edge shard) prefix of the hash being queried, which carries non-trivial information about which password the client is asking about. A proper PSI protocol leaks nothing beyond the intersection itself. The argument for k-anonymity is that the bucket is large enough -- on the order of hundreds to thousands of possible hashes per bucket -- that the residual information is not actionable for the threats most users face. It is a precise statement of "a small leak in exchange for vast practical efficiency"; the cost is documented and bounded, and that is why every deployed service uses some variant of it. But it is not zero-leak.
Why didn't Microsoft use SGX like Signal?
Threat-model differences and SGX's well-documented side-channel literature (see the §6 Aside for the four-attack chronology). For a breach-checking service whose threat model is "the corpus must not leak from inside Microsoft," HE-PSI offers a clean cryptographic argument that does not depend on any TEE's silicon-level security claims. The MSR Cryptography and Privacy group had been publishing the relevant HE-PSI papers since 2017 and shipping the SEAL library publicly since 2018, so the substrate was in-house. The cost is real (orders of magnitude more compute than an SGX enclave) but tractable at the sharded scale Edge Password Monitor operates at. The trade is reasonable, and it is documented in the MSR blog [1].
Why was the PoC originally in .NET 3.5?
AMSI evasion. The Antimalware Scan Interface scans .NET 4.8+ assemblies before execution; .NET 3.5 predates AMSI's API surface entirely. A C# program targeting .NET 3.5 will run on any modern Windows with the legacy framework installed (which is most of them, because .NET 3.5 is shipped as a Windows feature) and will not be subject to the same managed-runtime scanning that 4.8+ assemblies are. The current GitHub README says ".NET Framework 4.8.1 (changed from 3.5 originally)" [3] -- likely to ease running on a clean modern Windows -- but the original .NET 3.5 framing was the deliberate AMSI-evasion choice. The sibling AMSI post in this series explains the scanning architecture in detail.
Does Chrome or Brave have the same problem?
Per the researcher's claim and the PCWorld relay, no -- see §7 for the decrypt-on-autofill contrast and Chrome's App-Bound Encryption hardening [42][45]. The observable difference is direct: a ReadProcessMemory-based scrape of an idle Chrome process returns markedly less than the same scrape of an idle Edge process.
Is 'by design' a reasonable response?
Yes (with caveats). See §7's MSRC-servicing-criteria Aside for the full framing [48]: the short answer is that the position is internally consistent with a decade of MSRC policy and with the §9 architectural lower bound, but it concedes the same-user LCE threat model and shifts defence onto endpoint controls (antivirus, application-control policies, PPL on antimalware processes only) that may not exist on the user's machine. The architectural primitive that would close the gap (an OS broker) exists on Windows but is not wired into Chromium.
The PSI on the wire is real. The plaintext-RAM concession is also real. Both are statements about which threat model the Edge product team is defending against, and the apparent contradiction in the title disappears once you read them as such.
Study guide
Key terms
- Private Set Intersection (PSI)
- A two-party cryptographic protocol that computes the intersection of two sets without revealing anything else.
- Oblivious Transfer (OT)
- A primitive in which a sender holds two messages, a receiver picks one, and neither learns the other's choice or the unsent message.
- OT extension
- Two-phase protocol that turns kappa public-key OTs into m symmetric-cost OTs, collapsing per-OT cost by orders of magnitude.
- Oblivious Pseudorandom Function (OPRF)
- Two-party protocol where the receiver learns F_k(x) without revealing x to the sender or learning k.
- Pseudorandom Correlation Generator (PCG)
- Primitive that locally expands a short shared seed into long correlated random strings, used to make Silent OT communication-free post-seed.
- Homomorphic encryption (HE / SWHE / FHE)
- Encryption supporting operations on ciphertexts that decrypt to operations on plaintexts; SWHE is bounded depth, FHE is unbounded via bootstrapping.
- Cuckoo hashing
- Hashing with k candidate bins per element and displacement, achieving O(1) lookup at high load -- the partitioning trick under CLR17 and CHLR18.
- k-anonymity (password monitoring)
- A precise small information leak: each query is consistent with at least k possible passwords sharing the bucket prefix.
- Data Protection API (DPAPI)
- Windows facility that wraps blobs under user-derived keys; an at-rest control, not an in-process-memory control.
- App-Bound Encryption (Chrome, July 2024)
- Chrome control that binds DPAPI unwrap of saved data to the verified Chrome process identity, blocking same-user impersonation attacks.
Comprehension questions
Why does the DH meet-in-the-middle PSI protocol fail at breach-checking scale?
It costs O(|S_B|) group exponentiations per query, leaks set cardinality on both sides, and provides no labeled-PSI variant.
What three engineering moves let CLR17 revive FNP04's polynomial-roots PSI?
(1) BFV SWHE replaces Paillier for slot-packed homomorphic evaluation, (2) Cuckoo hash partitioning splits the giant polynomial into per-bin polynomials, (3) partition-and-evaluate bounds server work to O(|S_S| log |S_R|).
What does the OPRF preprocessing layer add to Edge Password Monitor's bare HE-PSI?
It prevents a malicious client from brute-forcing the server's corpus offline; the client cannot evaluate F_k(x) without server interaction.
What does the EdgeSavedPasswordsDumper PoC require to read Edge passwords as cleartext?
Same-user OpenProcess + ReadProcessMemory on the parent msedge.exe. No kernel exploit, no admin (against same-user processes), no DPAPI bypass.
Why is 'no cryptographic primitive closes the plaintext-RAM gap' the structural claim of section 9?
Using a plaintext value requires holding it; the only escape hatch is moving the holder to a higher-privileged broker process, which is an architectural choice, not a cryptographic one.
---WRITER METRICS---
Word count: 12625
Citations: 104 inline `@id`-style references across 53 unique sources (frontmatter expanded with PSZ14, four SGX disclosure pages, MSRC servicing criteria, three Microsoft Learn OS-broker primitives, Paillier 1999, Pagh-Rodler 2001, AMSI .NET 4.8, and Wikipedia TLS in Stage 11 iter-1 resolution)
Mermaid diagrams: 6
Definitions: 9
Sidenotes: 8
FAQ questions: 8
---END WRITER METRICS--- References
- (2021). Password Monitor: Safeguarding passwords in Microsoft Edge. https://www.microsoft.com/en-us/research/blog/password-monitor-safeguarding-passwords-in-microsoft-edge/ ↩
- (2026). X post disclosing EdgeSavedPasswordsDumper. https://x.com/L1v1ng0ffTh3L4N/status/2051308329880719730 ↩
- (2026). EdgeSavedPasswordsDumper. https://github.com/L1v1ng0ffTh3L4N/EdgeSavedPasswordsDumper ↩
- (2026). Microsoft Says Edge Password Security Vulnerability Is 'By Design'. https://www.forbes.com/sites/daveywinder/2026/05/06/microsoft-says-edge-password-security-vulnerability-is-by-design-is-it-time-to-switch-to-chrome/ ↩
- (1986). A More Efficient Cryptographic Matchmaking Protocol for Use in the Absence of a Continuously Available Third Party. https://dblp.org/rec/conf/sp/Meadows86.bib - IEEE Symposium on Security and Privacy, pp. 134-137 ↩
- IEEE Xplore record for Meadows 1986. https://ieeexplore.ieee.org/document/6234864 ↩
- Transport Layer Security (Wikipedia). https://en.wikipedia.org/wiki/Transport_Layer_Security ↩
- (1999). Enhancing Privacy and Trust in Electronic Communities. https://dblp.org/rec/conf/sigecom/HubermanFH99.bib - First ACM Conference on Electronic Commerce (EC-99), pp. 78-86 ↩
- DBLP record for Huberman-Franklin-Hogg 1999. https://dblp.org/rec/conf/sigecom/HubermanFH99.html ↩
- (2018). I've Just Launched Pwned Passwords Version 2. https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/ ↩
- (2004). Efficient Private Matching and Set Intersection. https://link.springer.com/chapter/10.1007/978-3-540-24676-3_1 - EUROCRYPT 2004 ↩
- (1999). Public-Key Cryptosystems Based on Composite Degree Residuosity Classes. https://link.springer.com/chapter/10.1007/3-540-48910-X_16 - EUROCRYPT 1999, LNCS 1592, pp. 223-238 ↩
- (2017). Fast Private Set Intersection from Homomorphic Encryption. https://eprint.iacr.org/2017/299 - CCS 2017 ↩
- (2003). Extending Oblivious Transfers Efficiently. https://link.springer.com/chapter/10.1007/978-3-540-45146-4_9 - CRYPTO 2003 ↩
- (2015). Actively Secure OT Extension with Optimal Overhead. https://eprint.iacr.org/2015/546 - CRYPTO 2015 ↩
- (2019). Efficient Pseudorandom Correlation Generators: Silent OT Extension and More. https://eprint.iacr.org/2019/448 - CRYPTO 2019 ↩
- (2019). Compressing Vector OLE. https://eprint.iacr.org/2019/273 - CCS 2018 PCG/VOLE precursor ↩
- (2016). Efficient Batched Oblivious PRF with Applications to Private Set Intersection. https://eprint.iacr.org/2016/799 - CCS 2016 ↩
- Microsoft SEAL. https://www.microsoft.com/en-us/research/project/microsoft-seal/ ↩
- (2001). Cuckoo Hashing. https://www.itu.dk/people/pagh/papers/cuckoo-jour.pdf - ESA 2001 (conference); J. Algorithms 51(2):122-144, 2004 (journal) ↩
- Fast Private Set Intersection from Homomorphic Encryption (Microsoft Research publication page). https://www.microsoft.com/en-us/research/publication/fast-private-set-intersection-homomorphic-encryption/ ↩
- (2018). Labeled PSI from Fully Homomorphic Encryption with Malicious Security. https://eprint.iacr.org/2018/787 - CCS 2018 ↩
- Labeled PSI from Fully Homomorphic Encryption with Malicious Security (Microsoft Research publication page). https://www.microsoft.com/en-us/research/publication/labeled-psi-from-fully-homomorphic-encryption-with-malicious-security/ ↩
- (2021). Labeled PSI from Homomorphic Encryption with Reduced Computation and Communication. https://eprint.iacr.org/2021/1116 - CCS 2021 ↩
- Microsoft APSI (Asymmetric PSI) library. https://github.com/microsoft/APSI ↩
- CNG DPAPI (DPAPI-NG) and Protection Descriptors. https://learn.microsoft.com/en-us/windows/win32/seccng/cng-dpapi ↩
- Microsoft Edge Security: Password Monitor. https://learn.microsoft.com/en-us/deployedge/microsoft-edge-security-password-monitor ↩
- Have I Been Pwned API v3. https://haveibeenpwned.com/API/v3 ↩
- (2019). Protecting accounts from credential stuffing with password breach alerting. https://www.usenix.org/conference/usenixsecurity19/presentation/thomas - USENIX Security 2019 ↩
- Apple Platform Security: Password Monitoring. https://support.apple.com/guide/security/password-monitoring-sec78e79fc3b/web ↩
- (2017). Technology Preview: Private Contact Discovery. https://signal.org/blog/private-contact-discovery/ ↩
- (2018). Validating Leaked Passwords with k-Anonymity. https://blog.cloudflare.com/validating-leaked-passwords-with-k-anonymity/ ↩
- Have I Been Pwned: Pwned Passwords. https://haveibeenpwned.com/Passwords ↩
- (2019). Protect your accounts from data breaches with Password Checkup. https://security.googleblog.com/2019/02/protect-your-accounts-from-data.html ↩
- Apple Platform Security Guide (PDF). https://help.apple.com/pdf/security/en_US/apple-platform-security-guide.pdf ↩
- Google private-membership (PSM) open-source library. https://github.com/google/private-membership ↩
- Signal ContactDiscoveryService (SGX reference implementation). https://github.com/signalapp/ContactDiscoveryService ↩
- (2018). Foreshadow: Extracting the Keys to the Intel SGX Kingdom with Transient Out-of-Order Execution. https://foreshadowattack.eu/ - 27th USENIX Security Symposium, August 2018 ↩
- (2018). SgxPectre Attacks: Stealing Intel Secrets from SGX Enclaves via Speculative Execution. https://arxiv.org/abs/1802.09085 - arXiv:1802.09085 (Feb 2018); IEEE EuroS&P 2019 ↩
- (2020). SGAxe: How SGX Fails in Practice. https://sgaxe.com ↩
- (2022). ÆPIC Leak: Architecturally Leaking Uninitialized Data from the Microarchitecture. https://aepicleak.com - 31st USENIX Security Symposium, 2022 ↩
- (2026). Edge plaintext passwords in memory (PCWorld). https://www.pcworld.com/article/3131805/ ↩
- (2026). Microsoft Edge passord i klartekst i minnet (ITavisen). https://itavisen.no/2026/05/04/microsoft-edge-passord-klartekst-minne/ ↩
- Chromium os_crypt source (decrypt-on-autofill code path). https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/sync/os_crypt_win.cc ↩
- (2024). Improving the security of Chrome cookies on Windows (App-Bound Encryption). https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html ↩
- Antimalware Scan Interface (AMSI) portal. https://learn.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal ↩
- .NET Framework: What's New (AMSI integration introduced in .NET Framework 4.8). https://learn.microsoft.com/en-us/dotnet/framework/whats-new/ ↩
- Microsoft Security Servicing Criteria for Windows. https://www.microsoft.com/msrc/windows-security-servicing-criteria ↩
- Protection descriptors (DPAPI-NG NCRYPT). https://learn.microsoft.com/en-us/windows/win32/seccng/protection-descriptors ↩
- Microsoft Pluton security processor. https://learn.microsoft.com/en-us/windows/security/hardware-security/pluton/microsoft-pluton-security-processor ↩
- Credential Guard overview (VBS, LSAISO). https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/ ↩
- (2014). Faster Private Set Intersection Based on OT Extension. https://www.usenix.org/conference/usenixsecurity14/technical-sessions/presentation/pinkas - USENIX Security 2014, pp. 797-812 ↩
- Microsoft Edge policy: PasswordManagerEnabled. https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/passwordmanagerenabled ↩