github.com/hhwill/poc-eth@v0.0.0-20240218063348-3bb107c90dbf/crypto/curve25519/bytes.go (about)

     1  package curve25519
     2  
     3  /* p[m..n+m-1] = q[m..n+m-1] + z * x */
     4  /* n is the size of x */
     5  /* n+m is the size of p and q */
     6  func mulaSmall(p []byte, q []byte, m int, x []byte, n int, z int) int {
     7  	v := 0
     8  	for i := 0; i < n; i++ {
     9  		v += int(q[i+m]&0xFF) + z*int(x[i]&0xFF)
    10  		p[i+m] = byte(v)
    11  		v >>= 8
    12  	}
    13  	return v
    14  }
    15  
    16  /* p += x * y * z  where z is a small integer
    17   * x is size 32, y is size t, p is size 32+t
    18   * y is allowed to overlap with p+32 if you don't care about the upper half  */
    19  func mula32(p []byte, x []byte, y []byte, t int, z int) int {
    20  	const n = 31
    21  	var w, i int
    22  	for ; i < t; i++ {
    23  		zy := z * int(y[i]&0xFF)
    24  		w += mulaSmall(p, p, i, x, n, zy) + int(p[i+n]&0xFF) + zy*int(x[n]&0xFF)
    25  		p[i+n] = byte(w)
    26  		w >>= 8
    27  	}
    28  	p[i+n] = byte(w + int(p[i+n]&0xFF))
    29  	return w >> 8
    30  }
    31  
    32  /* divide r (size n) by d (size t), returning quotient q and remainder r
    33   * quotient is size n-t+1, remainder is size t
    34   * requires t > 0 && d[t-1] != 0
    35   * requires that r[-1] and d[-1] are valid memory locations
    36   * q may overlap with r+t */
    37  func divmod(q []byte, r []byte, n int, d []byte, t int) {
    38  	rn := 0
    39  	dt := int(d[t-1]&0xFF) << 8
    40  	if t > 1 {
    41  		dt |= int(d[t-2] & 0xFF)
    42  	}
    43  	for n >= t {
    44  		n--
    45  		z := (rn << 16) | (int(r[n]&0xFF) << 8)
    46  		if n > 0 {
    47  			z |= int(r[n-1] & 0xFF)
    48  		}
    49  		z /= dt
    50  		rn += mulaSmall(r, r, n-t+1, d, t, -z)
    51  		q[n-t+1] = byte((z + rn) & 0xFF) /* rn is 0 or -1 (underflow) */
    52  		mulaSmall(r, r, n-t+1, d, t, -rn)
    53  		rn = int(r[n] & 0xFF)
    54  		r[n] = 0
    55  	}
    56  	r[t-1] = byte(rn)
    57  }
    58  
    59  func numsize(x []byte, n int) int {
    60  	for n != 0 && x[n-1] == 0 {
    61  		n--
    62  	}
    63  	return n
    64  }
    65  
    66  /* Returns x if a contains the gcd, y if b.
    67   * Also, the returned buffer contains the inverse of a mod b,
    68   * as 32-byte signed.
    69   * x and y must have 64 bytes space for temporary use.
    70   * requires that a[-1] and b[-1] are valid memory locations  */
    71  func egcd32(x []byte, y []byte, a []byte, b []byte) []byte {
    72  	for i := 0; i < 32; i++ {
    73  		x[i] = 0
    74  		y[i] = 0
    75  	}
    76  	x[0] = 1
    77  
    78  	an := numsize(a, 32)
    79  	if an == 0 {
    80  		return y /* division by zero */
    81  	}
    82  	bn := 32
    83  
    84  	temp := make([]byte, 32)
    85  	for {
    86  		qn := bn - an + 1
    87  		divmod(temp, b, bn, a, an)
    88  		bn = numsize(b, bn)
    89  		if bn == 0 {
    90  			return x
    91  		}
    92  		mula32(y, x, temp, qn, -1)
    93  		qn = an - bn + 1
    94  		divmod(temp, a, an, b, bn)
    95  		an = numsize(a, an)
    96  		if an == 0 {
    97  			return y
    98  		}
    99  		mula32(x, y, temp, qn, -1)
   100  	}
   101  }