62 lines
1.2 KiB
Go
62 lines
1.2 KiB
Go
|
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
|
||
|
}
|