-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
197 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,190 @@ | ||
package field | ||
|
||
import ( | ||
"crypto/rand" | ||
"fmt" | ||
"io" | ||
"math/big" | ||
) | ||
|
||
type fp2Elt struct { | ||
a, b *big.Int | ||
} | ||
type fp2Elt [2]fpElt | ||
|
||
func (e fp2Elt) String() string { | ||
return "\na: 0x" + e.a.Text(16) + | ||
"\nb: 0x" + e.b.Text(16) + " * i" | ||
} | ||
|
||
func (e fp2Elt) Copy() Elt { r := &fp2Elt{}; r.a.Set(e.a); r.b.Set(e.b); return r } | ||
func (e fp2Elt) Polynomial() []*big.Int { | ||
return []*big.Int{ | ||
new(big.Int).Set(e.a), | ||
new(big.Int).Set(e.b), | ||
} | ||
} | ||
func (e fp2Elt) String() string { return fmt.Sprintf("\na: %v\nb: %v", e[0], e[1]) } | ||
func (e fp2Elt) Copy() Elt { return &fp2Elt{*(e[0].Copy().(*fpElt)), *(e[1].Copy().(*fpElt))} } | ||
func (e fp2Elt) Polynomial() []*big.Int { return append(e[0].Polynomial(), e[1].Polynomial()...) } | ||
|
||
type fp2 struct { | ||
p *big.Int | ||
hasSqrt | ||
base fp | ||
name string | ||
cte struct { | ||
pMinus1div2 *big.Int | ||
} | ||
} | ||
|
||
// NewFp2 creates a quadratic extension field Z/pZ[x] with irreducible polynomial x^2=-1 and given p as an int, uint, *big.Int or string. | ||
func NewFp2(name string, p interface{}) Field { | ||
prime := FromType(p) | ||
if !prime.ProbablyPrime(4) { | ||
panic("p is not prime") | ||
base := NewFp(name, p).(fp) | ||
f := fp2{base: base, name: name} | ||
f.precmp() | ||
return f | ||
} | ||
|
||
func (f *fp2) precmp() { | ||
t := big.NewInt(16) | ||
pMod16 := t.Mod(f.base.p, t).Uint64() | ||
switch { | ||
case pMod16%4 == uint64(3): | ||
f.hasSqrt = generateSqrtP3mod4(f) | ||
default: | ||
panic("not implemented yet") | ||
} | ||
return fp2{p: prime, name: name} | ||
} | ||
|
||
func (f fp2) Elt(in interface{}) Elt { | ||
var a, b *big.Int | ||
if v, ok := in.([]interface{}); ok && len(v) == 2 { | ||
a = FromType(v[0]) | ||
b = FromType(v[1]) | ||
} else { | ||
a = FromType(in) | ||
b = big.NewInt(0) | ||
return &fp2Elt{ | ||
*(f.base.Elt(v[0]).(*fpElt)), | ||
*(f.base.Elt(v[1]).(*fpElt)), | ||
} | ||
} | ||
return &fp2Elt{ | ||
*(f.base.Elt(in).(*fpElt)), | ||
*(f.base.Zero().(*fpElt)), | ||
} | ||
return f.mod(a, b) | ||
} | ||
func (f fp2) P() *big.Int { return new(big.Int).Set(f.p) } | ||
func (f fp2) Order() *big.Int { return new(big.Int).Mul(f.p, f.p) } | ||
func (f fp2) P() *big.Int { return f.base.P() } | ||
func (f fp2) Order() *big.Int { return new(big.Int).Mul(f.base.p, f.base.p) } | ||
func (f fp2) String() string { return "GF(" + f.name + ") Irred: i^2+1" } | ||
func (f fp2) Ext() uint { return uint(2) } | ||
func (f fp2) Zero() Elt { return f.Elt(0) } | ||
func (f fp2) One() Elt { return f.Elt(1) } | ||
func (f fp2) BitLen() int { return f.p.BitLen() } | ||
func (f fp2) BitLen() int { return f.base.p.BitLen() } | ||
|
||
func (f fp2) AreEqual(x, y Elt) bool { return f.IsZero(f.Sub(x, y)) } | ||
func (f fp2) IsEqual(ff Field) bool { return f.p.Cmp(ff.(fp2).p) == 0 } | ||
func (f fp2) IsEqual(ff Field) bool { return f.base.p.Cmp(ff.(fp2).base.p) == 0 } | ||
func (f fp2) IsZero(x Elt) bool { | ||
e := x.(*fp2Elt) | ||
return e.a.Mod(e.a, f.p).Sign() == 0 && | ||
e.b.Mod(e.b, f.p).Sign() == 0 | ||
return f.base.IsZero(&e[0]) && f.base.IsZero(&e[1]) | ||
} | ||
|
||
func (f fp2) Rand(r io.Reader) Elt { | ||
a, _ := rand.Int(r, f.p) | ||
b, _ := rand.Int(r, f.p) | ||
return &fp2Elt{a, b} | ||
return &fp2Elt{*f.base.Rand(r).(*fpElt), *f.base.Rand(r).(*fpElt)} | ||
} | ||
|
||
func (f fp2) mod(a, b *big.Int) Elt { return &fp2Elt{a: a.Mod(a, f.p), b: b.Mod(b, f.p)} } | ||
func (f fp2) Add(x, y Elt) Elt { | ||
a := new(big.Int).Add(x.(fp2Elt).a, y.(fp2Elt).a) | ||
b := new(big.Int).Add(x.(fp2Elt).b, y.(fp2Elt).b) | ||
a.Mod(a, f.p) | ||
b.Mod(b, f.p) | ||
return fp2Elt{a, b} | ||
xx := x.(*fp2Elt) | ||
yy := y.(*fp2Elt) | ||
z0 := f.base.Add(&xx[0], &yy[0]) | ||
z1 := f.base.Add(&xx[1], &yy[1]) | ||
return &fp2Elt{*(z0.(*fpElt)), *(z1.(*fpElt))} | ||
} | ||
func (f fp2) Sub(x, y Elt) Elt { | ||
a := new(big.Int).Sub(x.(fp2Elt).a, y.(fp2Elt).a) | ||
b := new(big.Int).Sub(x.(fp2Elt).b, y.(fp2Elt).b) | ||
a.Mod(a, f.p) | ||
b.Mod(b, f.p) | ||
return fp2Elt{a, b} | ||
xx := x.(*fp2Elt) | ||
yy := y.(*fp2Elt) | ||
z0 := f.base.Sub(&xx[0], &yy[0]) | ||
z1 := f.base.Sub(&xx[1], &yy[1]) | ||
return &fp2Elt{*(z0.(*fpElt)), *(z1.(*fpElt))} | ||
} | ||
|
||
func (f fp2) Mul(x, y Elt) Elt { return nil } | ||
func (f fp2) Sqr(x Elt) Elt { return nil } | ||
func (f fp2) Inv(x Elt) Elt { return nil } | ||
func (f fp2) Neg(x Elt) Elt { return nil } | ||
func (f fp2) Sqrt(x Elt) Elt { return nil } | ||
func (f fp2) Exp(x Elt, e *big.Int) Elt { return nil } | ||
func (f fp2) IsSquare(x Elt) bool { return false } | ||
func (f fp2) Mul(x, y Elt) Elt { | ||
xx := x.(*fp2Elt) | ||
yy := y.(*fp2Elt) | ||
x0y0 := f.base.Mul(&xx[0], &yy[0]) | ||
x0y1 := f.base.Mul(&xx[0], &yy[1]) | ||
x1y0 := f.base.Mul(&xx[1], &yy[0]) | ||
x1y1 := f.base.Mul(&xx[1], &yy[1]) | ||
|
||
z0 := f.base.Sub(x0y0, x1y1) | ||
z1 := f.base.Add(x0y1, x1y0) | ||
return &fp2Elt{*(z0.(*fpElt)), *(z1.(*fpElt))} | ||
} | ||
func (f fp2) Sqr(x Elt) Elt { return f.Mul(x, x) } | ||
func (f fp2) Inv(x Elt) Elt { | ||
xx := x.(*fp2Elt) | ||
tv1 := f.base.Sqr(&xx[0]) | ||
tv2 := f.base.Sqr(&xx[1]) | ||
tv3 := f.base.Add(tv1, tv2) | ||
tv4 := f.base.Inv(tv3) | ||
z0 := f.base.Mul(&xx[0], tv4) | ||
z1 := f.base.Mul(&xx[1], tv4) | ||
z1 = f.base.Neg(z1) | ||
return &fp2Elt{*(z0.(*fpElt)), *(z1.(*fpElt))} | ||
} | ||
func (f fp2) Neg(x Elt) Elt { | ||
xx := x.(*fp2Elt) | ||
z0 := f.base.Neg(&xx[0]) | ||
z1 := f.base.Neg(&xx[1]) | ||
return &fp2Elt{*(z0.(*fpElt)), *(z1.(*fpElt))} | ||
} | ||
func (f fp2) Exp(x Elt, e *big.Int) Elt { | ||
n := e.BitLen() | ||
z := f.One() | ||
for i := n - 1; i >= 0; i-- { | ||
z = f.Sqr(z) | ||
if e.Bit(i) == 1 { | ||
z = f.Mul(z, x) | ||
} | ||
} | ||
return z | ||
} | ||
func (f fp2) IsSquare(x Elt) bool { | ||
xx := x.(*fp2Elt) | ||
tv1 := f.base.Sqr(&xx[0]) | ||
tv2 := f.base.Sqr(&xx[1]) | ||
tv3 := f.base.Add(tv1, tv2) | ||
tv4 := f.base.Exp(tv3, f.base.cte.pMinus1div2) | ||
return f.base.AreEqual(tv4, f.base.One()) | ||
} | ||
|
||
func (f fp2) Generator() Elt { return f.Elt([]string{"0", "1"}) } | ||
func (f fp2) Inv0(x Elt) Elt { return f.Inv(x) } | ||
func (f fp2) CMov(x, y Elt, b bool) Elt { | ||
var za, zb big.Int | ||
if b { | ||
za.Set(y.(*fp2Elt).a) | ||
zb.Set(y.(*fp2Elt).b) | ||
} else { | ||
za.Set(x.(*fp2Elt).a) | ||
zb.Set(x.(*fp2Elt).b) | ||
} | ||
return &fp2Elt{&za, &zb} | ||
xx := x.(*fp2Elt) | ||
yy := y.(*fp2Elt) | ||
z0 := f.base.CMov(&xx[0], &yy[0], b) | ||
z1 := f.base.CMov(&xx[1], &yy[1], b) | ||
return &fp2Elt{*(z0.(*fpElt)), *(z1.(*fpElt))} | ||
} | ||
func (f fp2) GetSgn0(id Sgn0ID) func(Elt) int { | ||
if id == SignBE { | ||
return f.Sgn0BE | ||
func (f fp2) Sgn0(x Elt) int { | ||
xx := x.(*fp2Elt) | ||
s0 := f.base.Sgn0(&xx[0]) | ||
z0 := 0 | ||
if f.base.IsZero(&xx[0]) { | ||
z0 = 1 | ||
} | ||
if id == SignLE { | ||
return f.Sgn0LE | ||
} | ||
panic("Wrong signID") | ||
s1 := f.base.Sgn0(&xx[1]) | ||
return s0 | (z0 & s1) | ||
} | ||
|
||
type f2sqrtp3mod4 struct { | ||
// This Alg 9. from Adj-Rodriguez | ||
*fp2 | ||
c1 *big.Int // c1 = (p-3)/4 | ||
c2 *big.Int // c2 = (p-1)/2 | ||
} | ||
func (f fp2) Sgn0BE(x Elt) int { | ||
/* [TODO] */ | ||
sb := x.(*fp2Elt).b.Sign() | ||
cb := 2*(f.cte.pMinus1div2.Cmp(x.(*fp2Elt).b)&^1) - 1 | ||
sa := x.(*fp2Elt).a.Sign() | ||
ca := 2*(f.cte.pMinus1div2.Cmp(x.(*fp2Elt).a)&^1) - 1 | ||
return sb*cb + (1-sb)*(sa*ca+(1-sa)*1) | ||
|
||
func generateSqrtP3mod4(f *fp2) hasSqrt { | ||
c1 := big.NewInt(3) | ||
c1.Sub(f.base.p, c1) | ||
c1.Rsh(c1, 2) | ||
c2 := big.NewInt(1) | ||
c2.Sub(f.base.p, c2) | ||
c2.Rsh(c2, 1) | ||
return f2sqrtp3mod4{c1: c1, c2: c2, fp2: f} | ||
} | ||
|
||
func (f fp2) Sgn0LE(x Elt) int { | ||
/* [TODO] */ | ||
sa := x.(*fp2Elt).a.Sign() | ||
ca := 1 - 2*int(x.(*fp2Elt).a.Bit(0)) | ||
sb := x.(*fp2Elt).b.Sign() | ||
cb := 1 - 2*int(x.(*fp2Elt).b.Bit(0)) | ||
return sa*ca + (1-sa)*(sb*cb+(1-sb)*1) | ||
func (s f2sqrtp3mod4) Sqrt(a Elt) Elt { | ||
a1 := s.Exp(a, s.c1) | ||
a1a := s.Mul(a1, a) | ||
alpha := s.Mul(a1, a1a) | ||
x0 := a1a | ||
|
||
var zz Elt | ||
if t := s.Add(alpha, s.One()); s.IsZero(t) { | ||
i := &fp2Elt{ | ||
*(s.base.Zero().(*fpElt)), | ||
*(s.base.One().(*fpElt)), | ||
} | ||
zz = s.Mul(x0, i) | ||
} else { | ||
par := s.Add(s.One(), alpha) | ||
b := s.Exp(par, s.c2) | ||
zz = s.Mul(b, x0) | ||
} | ||
return zz | ||
} |
Oops, something went wrong.