main
Raw Download raw file
  1// Package fp25519 provides prime field arithmetic over GF(2^255-19).
  2package fp25519
  3
  4import (
  5	"errors"
  6
  7	"github.com/cloudflare/circl/internal/conv"
  8)
  9
 10// Size in bytes of an element.
 11const Size = 32
 12
 13// Elt is a prime field element.
 14type Elt [Size]byte
 15
 16func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) }
 17
 18// p is the prime modulus 2^255-19.
 19var p = Elt{
 20	0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 21	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 22	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 23	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
 24}
 25
 26// P returns the prime modulus 2^255-19.
 27func P() Elt { return p }
 28
 29// ToBytes stores in b the little-endian byte representation of x.
 30func ToBytes(b []byte, x *Elt) error {
 31	if len(b) != Size {
 32		return errors.New("wrong size")
 33	}
 34	Modp(x)
 35	copy(b, x[:])
 36	return nil
 37}
 38
 39// IsZero returns true if x is equal to 0.
 40func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} }
 41
 42// SetOne assigns x=1.
 43func SetOne(x *Elt) { *x = Elt{}; x[0] = 1 }
 44
 45// Neg calculates z = -x.
 46func Neg(z, x *Elt) { Sub(z, &p, x) }
 47
 48// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue, which is
 49// indicated by returning isQR = true. Otherwise, when x/y is a quadratic
 50// non-residue, z will have an undetermined value and isQR = false.
 51func InvSqrt(z, x, y *Elt) (isQR bool) {
 52	sqrtMinusOne := &Elt{
 53		0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
 54		0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
 55		0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b,
 56		0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b,
 57	}
 58	t0, t1, t2, t3 := &Elt{}, &Elt{}, &Elt{}, &Elt{}
 59
 60	Mul(t0, x, y)   // t0 = u*v
 61	Sqr(t1, y)      // t1 = v^2
 62	Mul(t2, t0, t1) // t2 = u*v^3
 63	Sqr(t0, t1)     // t0 = v^4
 64	Mul(t1, t0, t2) // t1 = u*v^7
 65
 66	var Tab [4]*Elt
 67	Tab[0] = &Elt{}
 68	Tab[1] = &Elt{}
 69	Tab[2] = t3
 70	Tab[3] = t1
 71
 72	*Tab[0] = *t1
 73	Sqr(Tab[0], Tab[0])
 74	Sqr(Tab[1], Tab[0])
 75	Sqr(Tab[1], Tab[1])
 76	Mul(Tab[1], Tab[1], Tab[3])
 77	Mul(Tab[0], Tab[0], Tab[1])
 78	Sqr(Tab[0], Tab[0])
 79	Mul(Tab[0], Tab[0], Tab[1])
 80	Sqr(Tab[1], Tab[0])
 81	for i := 0; i < 4; i++ {
 82		Sqr(Tab[1], Tab[1])
 83	}
 84	Mul(Tab[1], Tab[1], Tab[0])
 85	Sqr(Tab[2], Tab[1])
 86	for i := 0; i < 4; i++ {
 87		Sqr(Tab[2], Tab[2])
 88	}
 89	Mul(Tab[2], Tab[2], Tab[0])
 90	Sqr(Tab[1], Tab[2])
 91	for i := 0; i < 14; i++ {
 92		Sqr(Tab[1], Tab[1])
 93	}
 94	Mul(Tab[1], Tab[1], Tab[2])
 95	Sqr(Tab[2], Tab[1])
 96	for i := 0; i < 29; i++ {
 97		Sqr(Tab[2], Tab[2])
 98	}
 99	Mul(Tab[2], Tab[2], Tab[1])
100	Sqr(Tab[1], Tab[2])
101	for i := 0; i < 59; i++ {
102		Sqr(Tab[1], Tab[1])
103	}
104	Mul(Tab[1], Tab[1], Tab[2])
105	for i := 0; i < 5; i++ {
106		Sqr(Tab[1], Tab[1])
107	}
108	Mul(Tab[1], Tab[1], Tab[0])
109	Sqr(Tab[2], Tab[1])
110	for i := 0; i < 124; i++ {
111		Sqr(Tab[2], Tab[2])
112	}
113	Mul(Tab[2], Tab[2], Tab[1])
114	Sqr(Tab[2], Tab[2])
115	Sqr(Tab[2], Tab[2])
116	Mul(Tab[2], Tab[2], Tab[3])
117
118	Mul(z, t3, t2) // z = xy^(p+3)/8 = xy^3*(xy^7)^(p-5)/8
119	// Checking whether y z^2 == x
120	Sqr(t0, z)     // t0 = z^2
121	Mul(t0, t0, y) // t0 = yz^2
122	Sub(t1, t0, x) // t1 = t0-u
123	Add(t2, t0, x) // t2 = t0+u
124	if IsZero(t1) {
125		return true
126	} else if IsZero(t2) {
127		Mul(z, z, sqrtMinusOne) // z = z*sqrt(-1)
128		return true
129	} else {
130		return false
131	}
132}
133
134// Inv calculates z = 1/x mod p.
135func Inv(z, x *Elt) {
136	x0, x1, x2 := &Elt{}, &Elt{}, &Elt{}
137	Sqr(x1, x)
138	Sqr(x0, x1)
139	Sqr(x0, x0)
140	Mul(x0, x0, x)
141	Mul(z, x0, x1)
142	Sqr(x1, z)
143	Mul(x0, x0, x1)
144	Sqr(x1, x0)
145	for i := 0; i < 4; i++ {
146		Sqr(x1, x1)
147	}
148	Mul(x0, x0, x1)
149	Sqr(x1, x0)
150	for i := 0; i < 9; i++ {
151		Sqr(x1, x1)
152	}
153	Mul(x1, x1, x0)
154	Sqr(x2, x1)
155	for i := 0; i < 19; i++ {
156		Sqr(x2, x2)
157	}
158	Mul(x2, x2, x1)
159	for i := 0; i < 10; i++ {
160		Sqr(x2, x2)
161	}
162	Mul(x2, x2, x0)
163	Sqr(x0, x2)
164	for i := 0; i < 49; i++ {
165		Sqr(x0, x0)
166	}
167	Mul(x0, x0, x2)
168	Sqr(x1, x0)
169	for i := 0; i < 99; i++ {
170		Sqr(x1, x1)
171	}
172	Mul(x1, x1, x0)
173	for i := 0; i < 50; i++ {
174		Sqr(x1, x1)
175	}
176	Mul(x1, x1, x2)
177	for i := 0; i < 5; i++ {
178		Sqr(x1, x1)
179	}
180	Mul(z, z, x1)
181}
182
183// Cmov assigns y to x if n is 1.
184func Cmov(x, y *Elt, n uint) { cmov(x, y, n) }
185
186// Cswap interchanges x and y if n is 1.
187func Cswap(x, y *Elt, n uint) { cswap(x, y, n) }
188
189// Add calculates z = x+y mod p.
190func Add(z, x, y *Elt) { add(z, x, y) }
191
192// Sub calculates z = x-y mod p.
193func Sub(z, x, y *Elt) { sub(z, x, y) }
194
195// AddSub calculates (x,y) = (x+y mod p, x-y mod p).
196func AddSub(x, y *Elt) { addsub(x, y) }
197
198// Mul calculates z = x*y mod p.
199func Mul(z, x, y *Elt) { mul(z, x, y) }
200
201// Sqr calculates z = x^2 mod p.
202func Sqr(z, x *Elt) { sqr(z, x) }
203
204// Modp ensures that z is between [0,p-1].
205func Modp(z *Elt) { modp(z) }