package crypto import "math/big" // addMod computes z = (x + y) % p. func addMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) { z = new(big.Int).Add(x, y) z.Mod(z, p) return z } // subMod computes z = (x - y) % p. func subMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) { z = new(big.Int).Sub(x, y) z.Mod(z, p) return z } // mulMod computes z = (x * y) % p. func mulMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) { n := new(big.Int).Set(x) z = big.NewInt(0) for i := 0; i < y.BitLen(); i++ { if y.Bit(i) == 1 { z = addMod(z, n, p) } n = addMod(n, n, p) } return z } // invMod computes z = (1/x) % p. func invMod(x *big.Int, p *big.Int) (z *big.Int) { z = new(big.Int).ModInverse(x, p) return z } // expMod computes z = (x^e) % p. func expMod(x *big.Int, y *big.Int, p *big.Int) (z *big.Int) { z = new(big.Int).Exp(x, y, p) return z } // sqrtMod computes z = sqrt(x) % p. func sqrtMod(x *big.Int, p *big.Int) (z *big.Int) { /* assert that p % 4 == 3 */ if new(big.Int).Mod(p, big.NewInt(4)).Cmp(big.NewInt(3)) != 0 { panic("p is not equal to 3 mod 4!") } /* z = sqrt(x) % p = x^((p+1)/4) % p */ /* e = (p+1)/4 */ e := new(big.Int).Add(p, big.NewInt(1)) e = e.Rsh(e, 2) z = expMod(x, e, p) return z }