Back in 2021, I decided to pivot from infrastructure-oriented software engineering to cryptography, having only ever really interacted with cryptography through hashing and encryption implementations in major programming languages. I had come across this weird thing called Zero Knowledge cryptography when I was looking for privacy tools on Ethereum, and was linked to Tornado.cash by a friend. Usually, when something seems like magic, the further into understanding it you get, the less magic it seems. But, learning about Tornado.cash, the opposite was true; the more I came to understand about how it worked, the more it seemed that something truly arcane was happening. At the same time, I'm never satisfied with hand-waving the complex nature of something interesting. There's no true expertise in a field if the purported experts cannot explain how and why their thing works from first principles, in accessible terminology. For the most part in software engineering, everything is well-understood, and mechanistic explanations of software are abound - engineering software is distinct from "programming" in that the components within your product, and the relationships between them, must be well-articulated and coherently mechanistic. It has been my impression as I entered the field of cryptography that there is a lot of work yet to be done in making this the case for cryptographic components. A lot of focus is put on soundness and security - as must be the case - but far less energy has gone into making cryptography intelligible. With that in mind, I've been working on an idea called "primitive cryptography". It should be possible to build cryptographic applications which can be described from first principles, using components which are clearly mechanistic in nature, the relationship between each component being well-articulated and well-encapsulated. In coming to my own understanding of cryptography, I've had a number of big "aha" moments, where mechanistic explanations clicked into place. In this thread, I'm going to cover some of the first principles mechanistic explanations, and work toward a description of zero knowledge cryptographic circuits that should be accessible to the average dyscalculiac developer. ------ Let's begin with the most basic description of elliptic curve cryptography that we can come up with. In the mathematical universe, an elliptic curve is defined by a beautiful equation, something like y² = x³ + ax + b. The specific curve that you'll probably run into if building on Ethereum would be the alt-bn128 curve, which uses a = 0, b = 3, and so is generally expressed as y² = x³ + 3. Every point that exists "on the curve", is one whose x and y coordinates satisfy the curve equation, with the exception of a special point called the "point at infinity" or the "identity element", which is sort of like 0. Additionally, elliptic curves are generally defined as being "over a prime field". You can think of this as being that there are a certain number of points that can exist on the curve - called the order - and that order is prime, because a prime number can only be evenly divided by 1 or itself. This means that there is no point which can be "factored" down to a different point on the same curve. When you perform an operation on a curve, you do that operation modulo the prime field, which is a way of saying that you loop back around to the beginning. --- Okay, so we've got a curve which has a finite prime field. There are a certain number of points on that curve ("the order"), and when we run out of points we loop back around from the point at infinity - which is sort of like 0. The question that I had for a while is, where do we start? How do you go from a number like 10, and end up with a point? This is where another special point called the generator point comes in. It's also sometimes called the base point, which I think is a better name for it, but everyone I've seen calls it the generator point. The generator point is a point which, when repeatedly doubled, visits every single possible point in the curve before returning to the point at infinity and reiterating through the field. To understand that even better, another big "aha" moment is to understand what's happening when you add points together, and how multiplication works as well. Point addition is not exactly like adding numbers together, because there's no exact relationship between the coordinates of two points. --- To add two points together (called the "group operation"), you draw a line between the two points, and because of the way that elliptic curves work, that line will intersect with the curve at some other point with a negative y coordinate that just so happens to be another valid point on the curve. If you take that point and reflect it across the x axis (on a symmetric curve, multiply the y coordinate by -1), that point is the result of adding the first two points together. Altogether, this group operation using elliptic curve points is called "dotting". Because every time you dot between points you end up with another positive point, you can then dot that point with another point to yield the next, and so on. This is called Point Addition. --- The rules around point addition also apply to subtraction, though it works slightly different. For every point Q (x,y), there is another point -Q (x,-y) which is the "additive inverse" of Q. If you wish to subtract one point from another, you can do P + -Q and do the dotting operation using those two points as usual. This is Point Negation. --- There's another rule which has to do with adding a point to itself (doubling it). Because you cannot draw a line between a point and itself, you instead use the "tangent" of the point on the curve to find the result. The tangent is a line can be thought of as parallel to the curve at the point you're drawing from. Where that line intersects with the curve again is the result of doubling the original point. This is Point Doubling. --- When we talk about multiplying a point on an elliptic curve, we're not talking about point multiplication. Instead, multiplication of a point happens through "scalar multiplication". Scalar multiplication of a point is done through the double-and-add method. A scalar in most cases is an integer value, and the double-and-add is performed by iterating the bits of the scalar - starting from most-significant - and for each bit doubling the point, and then if the bit is 1 (the remaining bits represent an odd number) you add the doubled point to the result. This approach is pretty efficient, and is akin to exponentiation of the point. Where Q is the original point, and P starts at the point at infinity (0), an iteration of double-and-add looks like this: P = P + P if bit == 1: P += Q This is Scalar Multiplication. --- The last rule has to do with how you deal with adding together the positive and negative of the same point (P ⋅ -P). The result of this is the point at infinity. If you think of the generator point G as being 1, then G - G (G ⋅ -G) is like 1 - 1, which is 0. However, the point at infinity does not itself satisfy the curve equation. --- Now that we have the rules of elliptic curve operations, we might wonder why these are secure, and why they're so useful? The basic approach to security in elliptic curves is called the Elliptic Curve Discrete Logarithm Problem, which is an extension of the Discrete Logarithm Problem. The Discrete Logarithm Problem basically says that it's easy to multiply an element of certain large prime order subgroup by a value to yield a result, but knowing the result and knowing the original element it's not possible to compute the value that the original element was multiplied by. If a = bᵏ, you cannot find k from b and a. This problem gets even harder to solve on elliptic curves, because the group operation is not simply multiplication, but is instead point addition, and multiplication is done through the double-and-add approach to scalar multiplication. Point doubling is easy, point division is basically impossible. There is no known efficient solution to solving P = Q/2, unless you know the multiplicand of Q. --- So, that's how elliptic curves give you security - operations only go "forward" easily, never backwards, so you can perform a series of point operations and the result doesn't tell you anything about what you did to get there. You only know that it's a valid point. This is called a Trapdoor Function. The scalar multiplicand of a point is referred to as the trapdoor. --- The usefulness of point addition as the trapdoor function of elliptic curves becomes super obvious when you realize the relationship between the multiplicands of points that you're adding together. Let's say that we want to generate the point that corresponds to the number 10. To do this, you could