<div dir="ltr"><div>First off, its great to see interest in PAKE-like protocols. In my opinion they are one of the gems of modern cryptography, but not widely known about and not widely used.</div><div><br></div><div>The SPAKE2 idea with M=N, is basically the scheme described by Kobari and Imai here <a href="http://eprint.iacr.org/2003/038">http://eprint.iacr.org/2003/038</a>, and they have a security proof for it. So I think this is fine. The basic original idea also independently occurred to me (and probably others) some time before that - see <em><a href="http://www.computing.dcu.ie/wpapers/2000/CA1300.ps">www.computing.dcu.ie/wpapers/2000/CA1300.ps</a> </em></div><div><br></div><div>It is vital that the discrete logarithm relationship between the generators is not known, as if it is it represents exactly the same kind of back-door that was used by the NSA with the late and unlamented Dual Elliptic Curve Deterministic Random Bit Generator. The solution is to create the generators using a hash function in some transparent way. (In my original paper I suggested using as generators 2 and 3 with a safe prime, the challenge for an attacker being to find x such that 2=3^x mod p. You can't get more transparent than that!)</div><div><br></div><div>The cofactor issue can be simply solved by raising any received value to the power of the cofactor, and checking that it is not the neutral element of the group (read multiplying by the cofactor in the elliptic curve case). In the EC case the cofactor is so small that this is not a problem. In Zp the cofactor can be huge, so this is not practical. The solution here is to choose a lim-lee prime (for example such that (p-1)/2q is prime), in which case a sub-group confinement attack becomes pointless and the group order check is no longer necessary (other than to wipe out the cofactor 2 which can be done as for the EC group).</div><div><br></div><div>FYI my Python implementation of elliptic curves takes 17ms on a modem PC for a general point multiplication. In Zp with a 2048-bit prime, you really want to be using Karatsuba, which would give a substantial speed-up.</div><div><br></div><div><br></div><div>Mike </div><div><em><br></em></div><div><em><br></em></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Feb 7, 2015 at 3:27 AM, Brian Warner <span dir="ltr"><<a href="mailto:warner@lothar.com" target="_blank">warner@lothar.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
I've been working on a (python) PAKE library, and as usually happens<br>
with these things, there are a number of questions that don't really<br>
surface until the bits meet the road. I talked to Trevor about it last<br>
week, and we came up with a short list of things that we'd really like<br>
to figure out or resolve.<br>
<br>
I'm implementing SPAKE2, first with an integer group (prime-order<br>
subgroup of a larger Zp* group), then I want to move to one of the 25519<br>
groups. Portability matters more to me than speed, hence the<br>
pure-python, but it'd be nice to not be painfully slow. I've got a<br>
2048-bit integer group running in 16ms on a fast computer, 110ms on a<br>
slower one, and it'd be nice to bring that down a little bit.<br>
<br>
For reference, SPAKE2 (in additive notation, with scalars in lowercase<br>
and group elements in caps) is:<br>
<br>
 public elements: M and N (one per role), generator G<br>
 private scalar: pw<br>
<br>
 Alice:<br>
   x = random_scalar()<br>
   X = G*x<br>
   MSG_X = X + M*pw , send MSG_X<br>
 Bob:<br>
   y = random_scalar()<br>
   Y = G*y<br>
   MSG_Y = Y + N*pw, send MSG_Y<br>
   Z = (MSG_X - M*pw) * y<br>
   key = H("Alice", "Bob", MSG_X, MSG_Y, Z)<br>
 Alice:<br>
   Z = (MSG_Y - N*pw) * x<br>
   key = H("Alice", "Bob", MSG_X, MSG_Y, Z)<br>
<br>
<br>
1: Dealing with the cofactor<br>
<br>
I'm planning to grab the group-operation algorithms from the Ed25519<br>
reference implementation, because SPAKE2 needs both point-addition and<br>
scalar-multiplication (so Curve25519's DH-specific X-only code won't<br>
help me). I think I need both X and Y coordinates, but I haven't studied<br>
the algorithm enough to know if maybe I can get away with just the X<br>
coord (maybe trying both sign bits and accepting one of two different<br>
passwords?).<br>
<br>
Both Curve25519 and Ed25519 reference implementations clamp the secret<br>
scalars (clearing the low three bits, setting the high bit). My partial<br>
understanding is that this clears the cofactor and makes it safe to not<br>
do as much checking on the received public point (the DH public<br>
parameter for Curve25519/DH, or the public verifying key for<br>
Ed25519/Schnorr). If you don't check that the received point is part of<br>
the right group (and that it has the correct large order), then you<br>
might end up revealing the low-order bits of the private key, and so<br>
fixing them to zero means you're not revealing anything.<br>
<br>
So I think I either must spend the time to verify the incoming point for<br>
subgroup membership, or find a way to clear the cofactor in SPAKE2. Any<br>
idea how to do this correctly? We figured that, from Bob's point of<br>
view, the concern is that MSG_X is not really a point on the right<br>
subgroup, but MSG_X*cofactor would be. So maybe do something like:<br>
<br>
  Z = (MSG_X*cofactor - N*pw*cofactor) * y<br>
<br>
Are we on the right track?<br>
<br>
2: Augmentation<br>
<br>
Boneh/Shoup's "cryptobook" defines an additional algorithm, "PAKE2+",<br>
which includes an augmentation step. I think this is beyond what Abdalla<br>
and Pointcheval described in their 2005 RSA paper. Do people generally<br>
agree that PAKE2+ is a good approach? I don't know how much review it's<br>
had.<br>
<br>
(also, are "Balanced" and "Augmented" the modern terms for these two<br>
modes? or has this changed?)<br>
<br>
3: Simultaneous Init (M==N)<br>
<br>
I don't know what the best term is for this, but most of the PAKE<br>
algorithms I've seen assign roles to the two parties, and bake those<br>
into the messages. I'm sure this makes the proofs easier to build, and<br>
might block some sort of reflection attack (what happens if the attacker<br>
echoes Alice's message back to her.. could that help them learn the key<br>
or the password?).<br>
<br>
But it's a nuisance for certain peer-to-peer use cases, like the<br>
Petmail/Panda introduction protocol, where there's no easy way to give a<br>
consistent name to each side. In the scheme I'm building for Petmail,<br>
the two humans can pick a string and type it into their agents at<br>
roughly the same time; I then want PAKE to amplify that into strong key<br>
exchange. There's no client-vs-server, or first-vs-second distinction.<br>
I'd have to explain to users that, in addition to remembering a random<br>
string, they also have to pick sides, and that'd be a drag.<br>
<br>
So what happens if you take SPAKE2 and set M==N? Does it break horribly?<br>
<br>
I had another idea, which I *think* is reasonable:<br>
<br>
 Alice runs two instances in parallel, with the same password, one as A<br>
 and one as B. She glues the A and B messages together and sends both to<br>
 Bob.<br>
<br>
 Bob does the same, but swaps Alice's A/B messages before feeding them<br>
 into his A/B instances. Alice swaps Bob's A/B messages upon receipt.<br>
<br>
 Alice then XORs the keys that come out of her two instances. Bob does<br>
 the same.<br>
<br>
This takes twice as much CPU and bandwidth, but:<br>
<br>
 * combining the two keys before revealing any derivative means an<br>
   active attacker still only gets one guess, not two<br>
 * using XOR doesn't require deciding upon a canonical order for<br>
   anything (like sorting them lexicographically, concatenating, then<br>
   feeding into HKDF)<br>
 * I think it preserves the validity of SPAKE2's security proof<br>
 * it's pretty easy to implement<br>
<br>
<br>
4: Choosing M and N (aka U/V in PAKE2)<br>
<br>
SPAKE2 requires two "arbitrary public elements" to blind the passwords,<br>
but what wasn't obvious to me when I first started was that it's<br>
important that nobody knows the discrete log of either one (otherwise an<br>
active attacker gets a dictionary attack, I think). Since the easiest<br>
way to pick a random element is to start with a random scalar, it's a<br>
subtle failure mode for implementors.<br>
<br>
Picking an arbitrary member of a an elliptic curve subgroup usually<br>
means picking a random X coordinate, finding the 0 or 2 points that<br>
match (50/50 chance), choose one, then see if it's in the subgroup.<br>
Small cofactors make this probable(?) enough that random hunt-and-peck<br>
will yield a result quickly, and you can make it more rigid/"sleeveless"<br>
by starting your random search at SHA256("") or something.<br>
<br>
Doing this for a q=~160-bit prime-order subgroup of a p=~4kbit Zp* group<br>
doesn't work, because the cofactor (r=(p-1)/q) is gigantic: you'll never<br>
randomly discover a subgroup member this way. I learned/believe that the<br>
right approach is to pick a uniform integer h in Zp, then compute h^r,<br>
which will be a uniform member of the subgroup. My more-rigid algorithm<br>
is to hash a seed into enough bits to Zp, turn it into an integer, then<br>
take it modulo p (introducing some bias), before raising to the cofactor<br>
r.<br>
<br>
Is this right?<br>
<br>
This is one of the things we'd need to nail down so implementors can<br>
feel confident about it.<br>
<br>
5: Hashing the password<br>
<br>
The use cases that want Augmented PAKE really want something stronger<br>
than a single scalar multiplication. PAKE appears to be at odds with<br>
protecting server-side data against dictionary attacks, which is a pity<br>
because it does a great job of protecting against network-side attacks.<br>
Can we get both?<br>
<br>
Trevor floated a crazy idea that involved only masking one side of the<br>
exchange, and then being very careful about who reveals a derived key<br>
first. We thought this might be useful for something, but tough to keep<br>
it safe.<br>
<br>
<br>
thoughts?<br>
 -Brian<br>
_______________________________________________<br>
Curves mailing list<br>
<a href="mailto:Curves@moderncrypto.org">Curves@moderncrypto.org</a><br>
<a href="https://moderncrypto.org/mailman/listinfo/curves" target="_blank">https://moderncrypto.org/mailman/listinfo/curves</a><br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature"><div dir="ltr"><div>Michael Scott</div><div>Chief Cryptographer</div><div>CertiVox Ltd</div><div>Tel (353) 86 3888746</div><div><br></div></div></div>
</div>