 Next, today I want to share with you what is hands down my absolute favorite algorithm in all computational number theory. This is Scopes's algorithm for counting points on elliptic curves, and maybe just before we start digging in the algorithm, let me just set the stage and explain why I think, why it's my favorite. So back in the late 70s, early 80s, when people were just starting to really think hard about seriously using elliptic curves for cryptographic applications, it was observed and you'll get a chance to observe this yourself in one of the problem sessions that if you are not careful about how you choose your elliptic curve, the discrete log problem can be quite easy to solve. There's an attack known as the polar kelvin algorithm, which you'll get a chance to implement, which in the problem session, you'll break the discrete log problem on an elliptic curve over the field with 2 to the 255 minus 19 elements, which is exactly the same field over which your phones all work every time you connect to the internet, every time you sign into Facebook or Gmail or whatever online services you use, the first step in almost any HTTPS exchange you make, anytime you buy anything on Amazon, basically anytime you do anything secure on the internet, the first step is to exchange a secret key and the protocol that is now the default protocol for that key exchange is what's known as ephemeral Diffie Helm and it's used and it uses a standardized elliptic curve, which happens to be an elliptic curve defined over that field. So what's the difference between the elliptic curve you're going to break this afternoon and the one that you rely on for the security of all your transactions on the internet? Well, the one that you rely on is the group of rational points has prime order, the one that you're going to break this afternoon doesn't, but I'll note that the one you're going to break this afternoon is not some special magic curve that I cooked up. I didn't use the CM method to construct it. I just generated a few thousand random elliptic curves and I picked the one that I thought would be easiest to break and you'll find that it is quite breakable. Now you could get around that problem by making the key size slightly bigger, maybe if you went to 512 bits, you'd be a much less chance of that happening, but one of the main benefits of elliptic curve cryptography is the small key size. So you really want to squeeze the key size down as far as you can safely get away with. And in order to be sure of that, you really need to know what the order of the group you're working in is. I mean the discrete log problem works perfectly well in any cyclic group, but in order for it to be hard to break, we want that cyclic group to have prime order or very close to prime order. Now one of the challenges that we were facing in the very early days of elliptic cryptography is the algorithms we had for counting points were all basically the same speed as the algorithm somebody might use to break the discrete log problem. So almost by definition we couldn't count points on an elliptic curve whose cardinality was big enough for it to be safely used, which meant we had no way to really be sure that we were using a safe elliptic curve. And so we were in a situation where the best known algorithm for a computational problem that people seriously want to solve, this isn't some abstract hypothetical or something somebody posted in a problem session, you know, in a specialist workshop, this is a problem that a lot of people were actively working on trying to solve. The best known algorithm we had by any means, you can use randomization, whatever heuristics you want, the best known algorithms were all fully exponential, prulably exponential lower bound on the running time. With the advent of Scopes algorithm, we went from a problem that was essentially intractable in a very severe sense and one that we practically wanted to solve to one that we had a polynomial time algorithm for solving. And it's very rare to make that leap, to go from a problem where the best known solutions are exponential time and a problem that a lot of people are interested in and make that jump to a polynomial time algorithm. To make it even better, there's two things that make it even better. One is it turns out it's actually a deterministic algorithm, which is a huge bonus. I mean, at the time I think people would have been perfectly happy with a probabilistic algorithm even when they depended on heuristics as long as the heuristics didn't get in the way of proving that your group order was correct. But it's a deterministic polynomial time algorithm and it's also completely practical. I mean, there are a lot of results in complexity theory where somebody might prove the existence of a polynomial time algorithm for a certain problem but don't analyze its complexity carefully or maybe there is some computable exponent on the polynomial that makes a polynomial time but you expect that it's not likely to ever be a practical algorithm. But scope's algorithm is completely practical as we'll see today in the lecture. That wasn't fully realized, appreciated, I think, when it was first introduced, although they might correct me if I'm wrong here, but my impression from reading the literature is that people were a little skeptical at first and I think there were two reasons for this. One is people didn't really know how to multiply polynomials quickly and they didn't really appreciate the power of the fast Fourier transform. I'll say more about that when we get into the details and why that's important but the reason they perhaps didn't realize it was important is because if you're working over 256-bit finite field, 256 bits is way too small for the FFT to help you multiply integers. There are other algorithms that are going to be practically faster. But if you happen to be multiplying polynomials of degree 256 squared over a field with 256 elements, you can turn those polynomials into integers that have millions of bits and you can multiply polynomials by multiplying those integers using what's known as chronic or substitution. And this is how all the computer algebra systems you have been using all week multiply polynomials over finite fields. If they're at all large, they're going to use chronic or substitution to do it. And that means that even if you're only working over a 256-bit finite field, if you're running Scopes algorithm, you really do want to be able to multiply a million-bit integers quite quickly and today we have all of the software systems we work with today can do that extremely efficiently. And the FFT, the benefits of the fast Fourier transform, already start kicking in around 5,000 or 10,000 bits. So by the time you're in the million-bit range, you're getting a lot of mileage out of it, and that makes a big difference. I think the other reason, perhaps, people didn't fully appreciate how practical Scopes algorithm was is because shortly afterward, Noam Elkes noted that there was a way to at least heuristically speed up the algorithm by a significant factor. We'll talk about that a little bit in the lecture and you'll get a chance to implement Elke's improvement to Scopes algorithm in the problem session. So I think to some extent people tended to credit it was the Elke's improvement that really made the algorithm practical. But the reality is if people had worked hard and carefully implemented Scopes algorithm as it was originally written, they still, even on the computers in those days, if they were a little patient, they could have easily computed the cardinality of an elliptic curve over a 256-bit finite field. And at that time they were really only targeting like 160-bit finite fields. And the algorithm I'm going to show you today can easily do that. Okay, so with that pre-mail ample out of the way, let's get into the algorithm. Yeah, maybe just to say a third thing, reason why I really like this algorithm is that I think conceptually it's very simple. It's based on one very elegant idea and it's very mathematically satisfying. If you're trying to implement in a low-level programming language, it's quite complicated to implement. And so I think it's maybe got a bad reputation for that reason, but if you're implementing it in a high-level computer algebra system, as we will today, the algorithm's quite easy to implement. It's like a page of code and you get to see that page of code. So what's our strategy? We want to compute the trace of Arbenius and Scope's idea is to compute the trace of Arbenius mod L for lots of small primes L. And these in particular will be primes L that don't divide the characteristic of whatever field we're working in. And so the skeleton of the algorithm, the outer wrapper of the algorithm, the entire algorithm you can see here. You start not knowing anything about the trace of Arbenius, but what do you know? Well, you know it's zero mod one. And you're going to try and acquire additional information about the trace of Arbenius modulo more and more primes until you have enough information to know the trace of Arbenius mod sum integer that's bigger than the width of the Haas interval for square root of q, at which point you will know the trace of Arbenius on the nose. And so for increasing primes L that don't divide q, you're going to compute the trace of Arbenius mod L and then you're going to use the Chinese remainder theorem to sort of increase the modulus, the modulus M that you know the trace of Arbenius to. And you just keep going until you have enough primes to make M bigger than four square root of q. And notice the primes L that you're going to be working with are not going to be that big. They're going to be on the order of the logarithm of q. So if we were talking about a q is say something like say two to the 255 minus 19, the L's would be going up to actually something quite a bit less than 255. That's the range of L we should be thinking about. Okay, so that seems like a very nice, simple algorithm. Of course, all of the work is in step two A. How are we going to compute the trace of Arbenius mod L? Okay, but any, before I jump into that, any questions on the basic idea of the algorithm? I think it's pretty straightforward. Okay. All right, so we're going to assume that q is odd for convenience, so we don't have to worry about characteristic two. Although you can implement Schiff's algorithm even characteristic, but it's just convenient to be able to work with an equation that form y squared equals f of x. And let's even assume it's not characteristic three and the implementation I'll do that so that we can have our f of x will look like x cubed plus a x plus b. So if we write our polynomial in our short virus stress equation as y squared equals f of x, well, the points of order two on our elliptic curve, the rational points of order two, have x coordinates that are rational roots of f. And so to figure out whether the trace of Arbenius mod two is very easy, the question is just, is f irreducible over our finite field? If the answer is yes, then the trace of Arbenius is one mod two, and if the answer is, it's not irreducible, then there is a two torsion point in this, so the trace of Arbenius is going to be even. Because q plus one is even, because q is odd. And we can, as we saw in, I think, yesterday and even the day before, we know how to count roots of polynomials very quickly just by taking GCDs. So this takes very little time. It's quadratic in n where, quasi quadratic in n, where n is log q. So now that we're actually talking about polynomial time algorithms, I'm going to do what complexity theorists would normally do, which is define n to be the size of the input and express all of your complexity bounds in terms of this little n, the size of the input. So when you speak about a polynomial time algorithm, you mean polynomial in the length of the input, the bit size of the input. All the bounds we've seen in the previous days were all expressed in terms of q, just because they're all exponential time algorithms and I would have had to write a lot of x on the screen if I were going to express them in terms of n equals log q. Okay, so great, we've done the first step. We've computed the trace of Arbenius mod two. All we gotta do is figure out how to handle the odd, put the odd L. So we've done it with half of them. That was a joke, you're supposed to laugh. So now we, so far in this course, I've been careful to just define, unilaterally define the trace of Arbenius as q plus one minus the number of Fq rational points on the curve just because that's a very simple down to earth definition that everybody can understand and get their heads around even if they've never really seen elliptic curves before. But scope's algorithm requires us to actually understand where the trace of Arbenius comes from. It's the trace of an endomorphism of the elliptic curve, right? Our elliptic curve is an abelian group. It has endomorphisms. It's also not just an abelian group, it's an abelian variety. So the endomorphisms we're interested in are actually morphisms in that category from our abelian variety to itself. And one of the things one learns about the Arbenius endomorphism of an elliptic curve