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 }