Supersingular Isogeny Key Exchange for Not-Quite Beginners
I recently read a great introductory paper on Supersingular Isogeny Diffie-Hellman (SIDH) by Craig Costello and wanted to summarize just the math of it (with some simplifications) for myself. Hopefully this summary is clear enough to also be useful to people who aren't myself.
§ Background
We deal with supersingular (we won't define this word) elliptic curves defined over finite fields of the form Fp2.
For SIDH, we deal only with curves such that E(Fp2)≅Zp+1×Zp+1. The kernel of the left multiplication map P→[a]P is of the form Za×Za. We say that a map ϕ:E→E′ is an ℓ-isogeny iff |kerϕ|=ℓ. Notice that ℓ-isogenies only exist for ℓ∣p+1. Every ℓ-isogeny ϕ:E→E′ also has an associated ℓ-isogeny, called the dual isogeny ψ:E′→E, such that ϕ∘ψ is the left-multiplication map [ℓ]. Vélu's formulas tell us that every subgroup G≤E corresponds to a unique isogeny out of E (to some curve E′) with kernel G. They also tell us how to construct an isogeny given its desired kernel.
Claim: On a supersingular curve E of the form above, for any prime ℓ∣p+1, there are exactly ℓ+1 nontrivial ℓ-isogenies out of E.
Proof: Using Vélu's formulas, it suffices to show that E has exactly ℓ+1 many subgroups of prime order ℓ. Firstly, since these are of order ℓ, they all must be subgroups of E[ℓ]≅Zℓ×Zℓ. Let P and Q denote the free generators of E[ℓ]. Consider the family of cyclic subgroups generated by P+[k]Q for 0≤k<ℓ. We claim that these are not only distinct, but disjoint. Suppose for distinct k, k′ that
α(P+[k]Q)=β(P+[k′]Q)
for some integers α, β. Rearranging,
[α]P−[β]P=[βk]Q−[αk′]Q
Since P and Q are linearly independent, both sides of this equation must be the identity. Therefore,
α≡β (mod ℓ)
Putting this together with the fact that the RHS is the identity,
βk≡αk′≡βk′ (mod ℓ),
we conclude k≡k′ (mod ℓ). This gives us a family of ℓ many disjoint subgroups. The final subgroup to include is the one generated by Q. It is clear that this is also disjoint from the previously mentioned subgroups. Finally, there cannot be any more order ℓ subgroups, since we have listed all the possible cyclic subgroups of Zℓ×Zℓ, and all groups of prime order are cyclic.
A supersingular ℓ-isogeny graph is a graph whose nodes are j-invariants (i.e., elements of Fp2 which are in bijective correspondence with isomorphism classes of elliptic curves) and whose edges represent ℓ-isogenies between them. Note this is an undirected graph because every ℓ-isogeny has a dual ℓ-isogeny going in the other direction. Also, by the above claim, every node has degree ℓ+1. It turns out that this is an expander graph, which means random walks on it mix quickly. In other words, the diameter of an expander graph on N elements is roughly log(N). SIDH exploits this property to make its security claims.
§ SIDH
The purpose of SIDH is to compute a shared secret by exchanging public keys. Same idea as Diffie Hellman.
§ Public Parameters
- A prime p=2eA3eB−1. This way, p+1 is divisible by powers of 2 and 3. eA and eB are chosen so that 2eA≈3eB.
- A starting curve E defined over Fp2
- Two points PA,QA∈E such that ⟨PA,QA⟩≅Z2eA×Z2eA.
- Two points PB,QB∈E such that ⟨PB,QB⟩≅Z3eB×Z3eB.
§ Protocol
Here's the gist of the protocol: Alice takes a walk on a 2-isogeny graph and marks her stopping point. Bob takes a walk on a 3-isogeny graph and marks his stopping point. The constraint that 2eA≈3eB means that the number of possible stopping points that Alice can get to is roughly equal to the number of possible stopping points Bob can get to. They then share their stopping points with each other. Then both of them do the same walks as before, but starting at each other's stopping point. The final endpoints of Alice's and Bob's walks are isomorphic (as elliptic curves, since points on the isogeny graph are curves), which means they have the same j-invariant.
Concretely, here's the protocol sequence. Alice initiates:
Alice:
- Picks a random secret scalar 0≤kA<2eA and defines a secret generator SA=PA+[kA]QA. Note that SA has order 2eA because PA and QA are linearly independent. By the proof above, all the possible subgroups ⟨SA⟩ are disjoint.
- Constructs a 2eA-isogeny ϕA:E→E/⟨SA⟩. This is done iteratively by repeatedly constructing 2-isogenies with elements of ⟨SA⟩ in the kernel. The way you do this is by getting a point RA=[2eA−1]SA of order 2. Using Vélu's formulas, you can construct a ϕ0:E→E/⟨RA⟩. Now let S′A=ϕ0(SA). Then S′A has order 2eA−1. Let R′A=[2eA−2]S′A, ... Once you've constructed ϕ0, ..., ϕeA, let ϕA be the composition of all of these.
- Sends Bob (ϕA(E),ϕA(PB),ϕA(QB)), where ϕA(E) is the description of the output curve. We call this tuple Alice's "public key".
Bob:
- Picks a secret 0<kB≤3eB, lets SB=PB+[kB]QB, and constructs a 3eB-isogeny ϕB:E→E/⟨SB⟩ in the same way as above.
- Sends Alice (ϕB(E),ϕB(PA),ϕB(QA)). We call this tuple Bob's "public key".
Alice:
- Uses the same method to construct ψA:ϕB(E)→ϕB(E)/⟨TA⟩ where TA=ϕB(SA)=ϕB(PA)+[kA]ϕB(QA)
- Computes the j-invariant of ψA(ϕB(E))
Bob:
- Same idea as above: Construct ψB:ϕA(E)→ϕA(E)/⟨TB⟩ where TB=ϕA(SB)=ϕA(PB)+[kB]ϕA(QB)
- Computes the j-invariant of ψB(ϕA(E))
End of Protocol
Note that, since j-variants of isomorphic curves are equal, and (E/⟨SA⟩)/⟨TB⟩≅E/⟨SA,SB⟩≅(E/⟨SB⟩)/⟨TA⟩,
the computed j-invariants are the same. Thus, it makes sense to have the j-invariant be the shared secret.
§ An Attack on Static Public Keys
This attack is due to Galbraith, Petit, Shani, and Ti. If Alice keeps reusing the same kA, Bob can determine its value by by initiating ⌈log2(kA)⌉ many SIDH exchanges. Here's the exploit:
Bob can figure out the bottom bit of kA by publishing ϕB(QA)+L2 instead of ϕB(QA), where L2 is a point of order 2. If kA is odd, i.e., if L2 is not killed by kA, then the protocol does not produce agreement, because TA+L2 is not the image of SA in Bob's curve ϕB(E). If kA is even, then L2 is killed by kA and the protocol completes successfully. Thus, the bottom bit is leaked.
Say Bob finds it was even. Now Bob wants to know if kA≡0 (mod 4) or 2 (mod 4). Then he sends ϕB(QA)+L4 where L4 is a point of order 4, and uses the same logic. If Bob had found kA was odd, then he would send ϕB(PA)−L4 instead of ϕB(PA), and ϕB(QA)+L4 instead of ϕB(QA). So if kA is 1 (mod 4), then
ϕB(PA)−L4+kA(ϕB(QA)+L4)=ϕB(PA)−L4+[kA]ϕB(QA)+L4=ϕB(PA)+[kA]ϕB(QA)
and the protocol succeeds. Otherwise,
ϕB(PA)−L4+kA(ϕB(QA)+L4)=ϕB(PA)−L4+[kA]ϕB(QA)+[3]L4=ϕB(PA)+[kA]ϕB(QA)+[2]L4
and the protocol fails. Bob can continue like this to recover each successive bit of kA.
§ Patching it up
How do you prevent the above attack from working? Ideally, Alice would like to be able to tell when she receives a malicious public key, i.e., one of the form ϕB(QA)+L for some low-order point L. If she could do this, then she would be able to terminate the protocol early and not reveal anything about the shared secret.
Unfortunately, given just a public key share, there's no way to tell if a given it was modified in this way or not.
But what if Alice was given more than a public key share? What if Bob somehow gave Alice his private ephemeral key as well? Then Alice would be able to compute Bob's public key share from his private key and check that it matches the one she received from Bob. If they match, then the public key was honest and the protocol completes successfully. If they don't match, then Alice can conclude that Bob cheated and she can abort the protocol early. This is precisely what the SIKE key encapsulation mechanism does. Here's the new protocol (a little simplified):
Alice
- Picks her secrets randomly, as before
- Publishes her public key pkA, computed as before (i.e., a description of a curve, and two points on that curve)
Bob
- Picks a random bitstring m
- Computes his secret scalar kB=G(m‖, where G is a pseudorandom number generator. He also computes the corresponding public key pk_B.
- Computes the j-invariant of the SIDH exchange (as described above) between k_B and pk_A
- Derives a symmetric key \kappa = \textrm{KDF}(j), where \textrm{KDF} is some key-derivation function.
- Computes c = \textrm{Enc}_\kappa(m), where \textrm{Enc} is the encryption function for some symmetric encryption scheme.
- Sends Alice the tuple (pk_B, c)
- Computes the shared secret (to be used if the protocol complete successfully) K = \textrm{KDF}(m \| k_B \| c).
Alice
- Uses pk_B and her secret k_A to derive the j-invariant, denoted j'
- Computes \kappa' = \textrm{KDF}(j')
- Decrypts m' = \textrm{Dec}_{\kappa'}(c) (recall Alice received c from Bob)
- Computes the secret scalar k_B' = G(m' \| pk_A) and its corresponding public key pk_B'
- Checks that pk_B' = pk_B. If these are not equal, the protocol aborts.
- Derives the shared secret K = \textrm{KDF}(m' \| k_B' \| c)
§ Analysis
Let's give an informal sketch of how this prevents information leakage.
Say Bob wants Alice to leak the lowest bit of her secret scalar k_A. The only leakage mechanism he has access to is learning whether the protocol succeeded or failed (since this can be used to convey a bit of information). He needs the protocol to do one thing when k_A is even, and the other thing if it's odd.
If Bob computes and conveys everything honestly (i.e., as described in this new protocol), then it should be clear that the protocol succeeds with 100% probability. Thus, this leaks nothing. If Bob lies about c, then m' = \textrm{Dec}_{\kappa'}(c) is certainly going to differ from m,1 which results in a different k'_B and thus a different pk_B'. So that strategy causes the protocol to always fail with overwhelming probability, and thus leak nothing.
So what if Bob lies about pk_B and tries the "add a low-order point" trick from the previous section? As before, this gives Bob control over the value j' that Alice derives. If k_A is even, it will be the same as Bob's j, and if it's odd it will be different. So far so good. Continuing on the "good" branch, if j' = j, then Alice's steps 2, 3, and 4 all continue to derive the same values as Bob's. In step 5, Alice can see that the pk_B she received doesn't match the public key corresponding to k_B', so Alice aborts. On the "bad" branch, if j' \neq j, then all the values derived in steps 2, 3, and 4 are wrong, and Alice is certain to abort. Thus, this strategy also causes the protocol to always fail with overwhelming probability, thus leaking nothing!
I hope that explanation was understandable. The way the authors of SIKE prove security is actually far more elegant than this: it turns out that the "patch" I described above is a result of a much more general theorem.2 Also, the patch I presented isn't totally accurate, so if you want more detail I encourage you to check out the spec (algorithms 1 and 2, and the proofs of security in section 4.3).
This relies on some assumption about the symmetric key primitive and on \textrm{KDF}, so that even if you modified j' as well, you couldn't get c to decrypt to a chosen plaintext
The FO transformation is precisely made to turn an IND-CPA PKE into an IND-CCA PKE with very little overhead. Here's a paper describing what it is and how it works. Here is the extremely influential paper that the authors of SIKE cite.
SIKE is currently in round 2 of the NIST post-quantum cryptography competition