 OK, we'll start the next session on implementations. The first presentation will be given by Mike Humberg, decaf eliminating cofactors through quotients and isogenes. Hi. So the actual title in the proceedings is through point compression. But I thought maybe quotients and isogenes maybe captures it a little bit better what exactly we're doing here. So the phrase, let GB a prime order group is surely familiar to members of the audience here. This is a common requirement of the group in crypto papers. And oftentimes the intention of this is that G is the group of points on some elliptic curve. And of course, if you're actually using this in a crypto system protocol, whatever, then you will need some way to encode points on the curve to binary and probably also to read them back in from binary so that you can communicate them to another party. So if you want to actually build such a system or build a library that could be used for implementing systems that you see in crypto papers, then one problem that you will find with prime order elliptic curves is that they have incomplete arithmetic. So the usual way to build a prime order elliptic curve is to use a short Weierstrass form and then either projective or Jacobian coordinates on that. And you find that the formulas are incomplete because they involve something like, well, you draw a line between these two points. But then if the two points are the same, then when you try to calculate the slope of the line, you get 0 over 0. And then even in the whole formula, this comes out in the output point, you get 0 over 0. And so for that reason, you have to fall back to a different formula for certain cases. Additionally, there are some minor issues like the fact that the identity point on the curve is usually not in the plane, but rather at infinity, which makes it more difficult to write down, requiring another special case. And all of these, in addition to adding to the code and possibly to the runtime of the code, they also are a problem because they lead to side channel attacks and they make, in some cases, the defenses against side channel attacks more difficult to implement. And oftentimes when you have a particular algorithm in mind, say Diffie-Hellman, then you can arrange your arithmetic to just avoid adding a point to itself and avoid the identity point. But in the general case, and certainly if you're trying to build a library to do all of this, you can't do that because you don't know what the underlying algorithm is going to do. In 2007, Edwards came up with a shape of elliptic curve that has simple, fast, complete arithmetic formulas and no points at infinity. They're all in the plane. So that would be certainly nicer to use. But unfortunately, Edwards curves necessarily have a cofactor divisible by 4. So they can't have prime order. Instead, they have order, say, h times q, where h is the cofactor at some small number and q is prime. Or at least for any curve that you would want to use in a real system, q is prime. So this can cause problems if you sort of take a protocol that assumed g was prime order and then adapted it to the case where g is not prime order. And most of these are sort of related to the idea that, well, if I give you a point whose order is like 2 or 4 and then you multiply it by your secret, then you're going to end up with a point whose order is still 2 or 4. And there are only a few such points, so I can probably guess what it is. And furthermore, I'll learn a few bits of your secret from doing that because I'll learn your secret mod h. So usually, these problems are pretty easy to mitigate. And they usually amount to something like, well, you multiply the point that you get as input by h ahead of time. And then if it's 0, then you abort because the other guy is trying to fool you. And otherwise, you continue on. Or maybe instead of making your scaler effectively 0 mod h, you make it 1 mod h, or so on. The biggest problem with this is that once you already have a protocol described using a prime order group, then you're going to have to redo the analysis of it in order to make it work for a composite order group. And while that might be easy for the guy who designed the protocol, it's going to be a pain for basically anyone else, and especially for somebody who's not a cryptographic expert who's maybe implementing it. Also, I sort of needed a dead horse to beat for the why cofactors are slightly annoying, if not outright bad. So one example is the ed25519 signature scheme where signatures are specified to obey a certain equation, mod h times q, but the specification explicitly allows verifiers to check it only mod q to speed up batch verification, I believe. And the result of this is that the behavior is implementation defined, which doesn't mean the signature is insecure, but it does mean that it's harder to test and could be problematic for use in some situation, like a blockchain, where you sort of care whether people get the same answer or not. So the other approach to this besides changing the protocol is to get rid of the cofactor. And the predominant technique in previous work is to use a subgroup, the q torsion subgroup of the group g written g bracket q. And so the way this works when you would implement is that internally your implementation still uses elements of g as its working elements. But then when it takes an input in binary or whatever, then it needs to test whether this input is, in fact, in g bracket q or not. And the most obvious way to do this would be to multiply it by q and see if you get the identity, but that's pretty slow. So an alternative that's faster but somewhat more complicated is to figure out some kind of algebraic property that points would have to have. And you can construct these using isogenes. And basically, if h is 4, you're going to have to do probably a square root and then check a quadratic symbol or something like that in order to verify that the point is indeed in the subgroup. So this is still kind of slow, and it's kind of complicated, and we'd rather not do it. And then any other operation that you're doing, add, subtract, multiply your points, they're just the same thing as on g. Possibly there's an asterisk, because maybe there's some small speed up in a couple cases that you can get from using the fact that it's in the subgroup, usually not. So the simple proposal from this talk is that instead of using a subgroup, you should use the quotient group g over gh. So what this is is it's the group of equivalence classes of points where the equivalence relation is that two points are considered equal if their difference is in this h-torsion subgroup. So how would this work in an implementation? Well, actually, so the same way. So you're just going to store and add and subtract in whatever points in the group as the representatives of their coset, so just one point representing the whole coset. And to add them, you just add them and so on. You're only going to have to change the equality check of course, because there's a different rule for what it means for two points to be equal. They're now equal if their difference is in the h-torsion group. And then when you want to write a point down to send it to the other party, probably you want to write it down canonically so that each member of the group g over gh has a unique encoding. And to do that, you have to pick, or at least the straightforward thing to do is to pick one of the elements of the coset, one of the possible representatives of this point to be the distinguished or canonical one that you're going to write out when you send it to the other party. And then you just encode as that element. And then when you decode a point, then you have to check that it was indeed the distinguished element. So and then of course, there are no changes to the other operations. So this sounds a little more complicated than the subgroup but now I've just added a bunch of new things that you have to do. But at least in some cases, this is actually really easy. So if you consider the straightforward case of just an untwisted Edwards curve with cofactor 4, the torsion operation is, you can even see it in the picture, it's just that the curve has 90 degree rotational symmetry in addition to mirror symmetry for the negation operation. And that's the four torsion group is that you rotate a point by 90 degrees and then those other points are on the curve. They're the curve plus an element of the four torsion subgroup. So the simplest way to say, well, which point is special, which point are we going to write out, is will you write out the one that's in the upper right quadrant? So you rotate the point around until x and y are both positive. And of course, you're not using the real numbers for this, so positive maybe means even the low bit of the representative is clear or something. And then that's the distinguished point. That's the one you write out. So when you have a point and want to encode it, you rotate it until x and y are positive and then you send it. And then the other guy checks not only that it's on the curve, but that x and y are positive. And maybe there's some additional distinguisher around which one of these points is distinguished, but say y is positive strictly and x might be zero or something. And they check that and then that's it. And then this also leads to a single coordinate or even single coordinate minus one bit point compression format. So instead of sending x and y, you just send y, say, and y is positive. And then the person, when you decode, you solve for x. And there are two possible x's and exactly one of them is non-negative. So that's the x that's the point that was being sent. And so you've got now a slightly more efficient point compression format than was previously in use. So this technique I call in the paper decaf because it divides the cofactor by four and reminded me of a way to divide coffee by four. So the last operation that I haven't told you how to do yet is to check equality. Remember that two points are equal if their difference is in this four torsion group, which means, going back to this diagram, that it's one of these points on the axis. So if you subtract two points, then you get this formula. It's complete. And you'll notice that these are points in some projective representation that you have internally. So you'll notice that they're equal in the quotient group if either the x of the difference or the y of the difference is 0. So in other words, if x1, y2 is x2, y1, in which case the two points lie on a line through the origin. Or if y1, y2 is minus a x1, x2, in which case they're 90 degrees off from each other. So this formula is not more complicated. And it doesn't take any longer than what you were going to do otherwise. Because otherwise you were going to check is x1, y2 equal to x2, y1. And also is x1, z2 equal to x2, z1. So this formula for checking equality is about as much effort and about as much complexity as you were going to do before. It's just slightly different. And so that's it. So that's how you can implement an Edwards curve much more easily and more quickly and using less code as a prime mortar group with a quotient group rather than as a subgroup. So you have to do this extra operation when you encode the point. But you get to avoid this slow and complicated subgroup membership check when you decode and replace it with a much simpler check. And then the equality check is about the same as in G, although as I sort of hinted to before, you could speed it up slightly by using the fact that points are in the subgroup. Doesn't really matter. You don't check point equality that often. And everything else is the same as in G. So that covers the case of untwisted Edwards curves with cofactor 4. So then you can move on to other questions like what about twisted Edwards curves? So twisted Edwards curves, particularly with a coefficient minus 1, are slightly simpler and slightly faster than untwisted ones to implement. But unfortunately, if minus 1 isn't a square, which it isn't when p is 3 mod 4, then the formulas that were complete on the untwisted Edwards curve are no longer complete for this curve. So that means that when you add certain pairs of points, you'll get 0 over 0, which is the wrong answer. This happens when, because these curves have a pointed infinity. And they only happen for additions involving the pointed infinity in some way. So in other words, if you use a subgroup of this curve where there are no points at infinity, a subgroup that doesn't include those points, then the addition laws that you were going to use are complete. So this sort of like leaves this planning for subgroups, even though they have this nasty and slow membership check. So a solution that I proposed earlier to this sort of problem is to use an isogeny. So an Edwards curve that's untwisted is for isogenists to another Edwards curve that's twisted. So minus a. So a here is probably 1 and minus 1 over here and with only a slightly different d value. So what you can do is when you're doing sort of cheap operations and fast ones, you do it on the Edwards curve. You specify your system on the Edwards curve. You encode and decode points on the Edwards curve. But then when you need to do a long running, scale or multiply or something, then you map to the twisted Edwards curve with the isogeny, do the operation, and then come back. The disadvantage of this is that when you do this, you pick up a factor of 4, which is slightly annoying. And it's especially annoying if you try to make like a generic library to do these things, because now you have to implement math on two different curves and also you have to deal with this factor of 4 in the round trip. And maybe you'd rather not do that. But because the image of the isogeny is one of these subgroups that doesn't contain points at infinity, all the operations on the twisted Edwards curve are complete. So this is still a safe strategy to do, but maybe it's not optimal. So the improved solution that I developed for this is actually, I think, interesting in its own right, which is that these two curves, the Edwards and twisted Edwards curve, which are four isogenists to each other, are, as one might expect, two isogenists to some intermediate curve. So in this case, this intermediate curve I'm writing is a Jacobi quorum. It's not necessarily an Edwards curve, because its torsion group looks like 2 by 2 instead of 4 by 1. So also, this Jacobi quorum is two isogenists with a very simple isogeny to a Montgomery curve. So you know that Montgomery curves and twisted Edwards curves are isomorphic to each other. But in this case, these two curves are not isomorphic to each other, but they are four isogenists to each other. And they both have small coordinates. So this one has a small capital A. This term is called coordinate. And this one has a small d coordinate, which is not the case for the isomorphism. So the strategy here is that you will specify your system in terms of the quotient group of the Jacobi quorum curve. So when you write down a point, you write down the point on the Jacobi quorum. And then to do the math, when you decode the point, you'll map it to either the twisted or the untwisted Edwards curve or even the Montgomery curve. Whatever one is the most convenient for you, but let's say the twisted Edwards curve. And then because you landed in a subgroup, the image of the isogeny, your addition laws will be complete, so you don't have to worry about dividing 0 by 0 or points at infinity or anything like that. And then when you want to encode back to the original curve, well, you could use the dual isogeny, but it's actually probably better to use the inverse of the isogeny. So you'll invert the isogeny. You'll get back to the Jacobi quorum curve. And that sounds complicated and expensive, but I'll show you on the next slide that it's really not. And that way you don't have a factor of 2 anywhere. And also a neat factor of this is that you can sort of choose which curve model you want to do all the work on. So maybe it's slightly simpler if you use an Edwards and slightly faster if you use a twisted Edwards or Montgomery or something like that. So the way the formulas work, just to give you sort of a taste of how this works, is that if you have a point s, t on the Jacobi quorum curve, then you can map it to using this sort of degree formula to the twisted Edwards curve or the Edwards curve. You set a to plus or minus one, depending which curve you want to land on. And then there's a dual formula that's just as simple. But to invert it, you need to take a square root. But the thing is that it turns out you can, there's a simple way to evaluate this formula that basically just uses one square root and folds the division into the square root, so it doesn't take any longer than just the square root operation. And you can see that this is still a relatively simple formula. And that gives you the s and t over s. So the distinguished point on the Jacobi quorum is where s and t over s are both positive. So you'll choose the sign of the square root to make this term positive. And then that gives you this term. And then it turns out you just take the absolute value of it, which is to say you negate it if it's not considered positive. And then you're done. So all of that sounds kind of complicated. It's actually not too bad to implement. But I don't know if it's the kind of thing that people are likely to actually use in practice because it certainly sounds complicated. And it uses the word isogeny. So a simpler application of this technique is half-calf. So a question I've actually been asked is I have a Curve 25519-based public key infrastructure deployed. I've got my app out there. All the users have Curve 25519 public keys, and we're using them for key exchange. But now I want to support signatures. And I can't support signatures easily because, at least to do signatures in a natural way, I want to know the sign of everybody's public key. But there's not a well-defined sign bit because if you have a point UV on the Montgomery Curve, the Curve 25519 public key only has U. So one way to get around this problem is to say that the ratio of V over U is always even, or infinity, is always even. And if you have a U that you want to serialize and V over U is not even, then you can choose and you care about the sign bit so you're not doing just Diffie-Hellman, then you can write out one over U instead. So that corresponds to adding the two torsion element to your point. And for that point, V over U will be even, or positive, however you're going to define positive, but let's say even. And the funny thing is that this is actually something that Curve 25519 already does, but only for the pointed infinity. So the rules for Curve 25519 are that if you want to write out the pointed infinity, instead you write 0. Partly because this is a natural thing to do, and partly because 0, 0 is the two torsion point. So if you multiply it by anything, you're going to get either, again, the two torsion point or the pointed infinity. And either way, you're going to write out 0 because we're sort of collapsing those two cases. So it's quotienting out by the two torsion point, but only for the pointed infinity. So the idea of half-calf is to extend that to always quotient out by two torsion. And then that gives you sort of a sign bit that you can play with. So in future work, which I've tackled a little bit of already, I have a tentative design, but it could be improved, is to deal with the Curve Ed 25519, which is the most popular Edwards curve out there these days. And it has a cofactor of 8. So I've told you what to do with a cofactor of 4. But so you're going to need, in your distinguishing function, if it's going to be simple and not just, oh, it's the least lexicographic encoding or something like that, you need another bit to distinguish points. So one possible way to do it, which I've tested and works, but maybe isn't the simplest thing ever, is to have some property on the Jacobi curve before you apply the isogeny and then some property that you test afterwards. This turns out to be much less complicated than it sounds, but still more complicated than I would like maybe. So still working on that. There's an implementation of this for Ed 448 Goldilocks and experimentally Curve 25519 on SourceForge, if you want to play with it. And that's all.