0

If the result of my point addition is point Q = ( x, y ) then what is the arithmetic to do the mod p?

Is the mod to be done on x or y as soon as they exceed p?

Maybe here is the answer. This is an elliptic curve and, to my novice knowledge, must be manipulated with the correct field arithmetic. Standard arithmetic does not apply to the entire point, Q for example, having two parts. But, individual arithmetic steps are subject to standard arithmetic such as 1 + 1 =2 and 4 / 2 = 2. Is that what is to be done rather than some eliptic curve operation such as elliptic addition? Just use regular arithmetic on the x or y of Q = (x,y)? Just regular integer division and keep the remainder?

Yes, I have searched for this extensively and not been able to recognize the answer. A link to an answer that provides the individual arithmetic steps would be wonderful.


Update following this answer:

The use of $-977$ for $p$ surprised me but I was able to figure it out. Most places subtract all powers of two. I have visited a few sites and have found that the basic algebra works out to these two equations. $$\begin{align} x_r &= \left(\frac{y_q - y_p}{x_q - x_p}\right)^2 - x_p - x_q\\ \\ y_r &= \frac{y_q - y_p}{x_q - x_p}(x_p - x_r) - y_p \end{align}$$ (presuming some specific conditions)

I can convert those to arithmetic and can write code in C or C++ to do the long arithmetic. To my understanding the above is addition on the field that composes, or defines, or makes up, (best phrase?) the secp256k1 curve.

But I never see an explanation of how to do the modulo operation. I just assumed it was another special operation like the addition. But as I wrote my question, the insight (possibly wrong) occurred to me that the modulo is an individual action, not a field action, and should be done with regular arithmetic. In this case, meaning regular division, albeit using very long numbers.

And: referring to the equations above, when $x_r$ or $y_r$ exceed $p$, do the modulo $p$ operation. That can be done with division or repetitive subtraction.
Subtraction would probably be less subject to error.

I think the answer is implicit in the first paragraph, but not certain. Do I have the right concept about the use of mod $p$?

fgrieu
  • 149,326
  • 13
  • 324
  • 622

1 Answers1

2

secp256k1 uses the prime field $\mathbb F_p$, where $p$ is the prime $2^{256}-2^{32}-977$. This is a special case of the ring of integers modulo $p$ for prime modulus. We can think of this field/ring as the set of integers in the interval $[0,p)$, with an addition and multiplication performed modulo $p$, that is: after the usual addition or multiplication, we conceptually remove (or add) $p$ as many times as needed so that the end result lies in the interval $[0,p)$. But after a multiplication in the context of secp256k1, it's not feasible to actually do that, for the number of operations is infeasibly large.

how to do the modulo operation

In Python, addition and multiplication modulo $p$ is as simple as (u+v)%p and (u*v)%p.

$w\bmod p$ can be defined as the integer $r$ in $[0,p)$ with $w-r$ a multiple of $p$. When $w\ge 0$, that $r$ is the remainder of the Euclidean division of $w$ by $p$, and can be computed as $\displaystyle r=w-\left\lfloor\frac w p\right\rfloor p$, where $\lfloor\;\rfloor$ denotes rounding down to the nearest integer. When $w<0$, it can be used $r=p-1-(((-w)-1)\bmod p)$. All these operations must be performed exactly, despite the integers involved having perhaps hundreds of digits.

Many usual rules of algebra apply in the field $\mathbb F_p$: addition and multiplication are associative, commutative, with the distributive property. Identity elements are $0$ for addition and $1$ for multiplication. Any element $x\in\mathbb F_p$ has an opposite $-x$ such that $(-x)+x=0=x+(-x)$, and if $x\ne0$ then $x$ has an inverse $x^{-1}$ such that $x^{-1}\times x=1=x\times x^{-1}$ (that inverse property holds because the modulus $p$ is prime). The equation $x^2=u$ in the field $\mathbb F_p$ has one solution $x=0$ for $u=0$, and for other $u$ either no or two solutions, opposite one another.

Note: we can divide (except by $0$) in $\mathbb F_p$, but that's not the usual division. We first compute the inverse of the denominator, e.g. using the (half) Extended Euclidean algorithm, then multiply by the numerator.

secp256k1 is the set consisting of “points” that can be defined by a pair of coordinates $(x,y)$ in $\mathbb F_p$, matching the equation $y^2=x^3+7$ in $\mathbb F_p$, plus a special “point at infinity” $\mathcal O$. If we want to assign $(x,y)$ coordinates to $\mathcal O$, that can be $x=0$ or/and $y=0$; but notice that these coordinates won't match the equation. The total number of points in secp256k1 is the prime $n=p-432420386565659656852420866390673177326$.

It's defined “point addition” on secp256k1. That's not addition in $\mathbb F_p$, but uses operations in $\mathbb F_p$. Point addition makes secp256k1 a group. That is, addition of any two points in secp256k1 yields another point in secp256k1; and this addition law has associativity, commutativity, identity element $\mathcal O$, and any secp256k1 point has an opposite. See sec1-v2 §2.2.1 for the rules of point addition (and multiplication of a point by an integer), noting that $a=0$ and $b=7$, as stated in sec2-v2 §2.4.1. Example implementation in modern Python:

def secp256k1_add(P:tuple[int,int], Q:tuple[int, int])->tuple[int,int]:
    """add two secp256k1 points in Cartesian coordinates"""
    p=2**256-2**32-977                          # prime for secp256k1's field
    # normalize the inputs
    Px = P[0]%p; Py = P[1]%p
    if Px==0: Py = 0
    elif Py==0: Px = 0
    else: assert (Px**3+7-Py**2)%p==0, "incorrect P"
    Qx = Q[0]%p; Qy = Q[1]%p
    if Qx==0: Qy = 0
    elif Qy==0: Qx = 0
    else: assert (Qx**3+7-Qy**2)%p==0, "incorrect Q"
    # actual computation
    if Px==0: return Q
    if Qx==0: return P
    u = Qx-Px; v = Qy-Py
    if u!=0: u = pow(u, -1, p)*v%p              # regular addition
    elif v==0: u = Px*Px*pow(Py<<1, -1, p)*3%p  # doubling
    else: return (0,0)                          # point at infinity
    v = (u*u-Px-Qx)%p; return (v,((Px-v)*u-Py)%p)

example

Hx = 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63 H = (Hx,p-pow(Hx**3+7, (p+1)>>2, p)) # half the generator point G = secp256k1_add(H, H) # generator point assert G==(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8) assert secp256k1_add(G, G)==secp256k1_add(secp256k1_add(G, H), H), "secp256k1_add is broken"

fgrieu
  • 149,326
  • 13
  • 324
  • 622