package main type WCurve struct { p, r, a, b, h bigint g *JacobiPoint montA, conversionFromM bigint conversion bigint } func NewWCurve() *WCurve { curve := WCurve{} curve.p = NewBigintFromString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16) curve.r = NewBigintFromString("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16) curve.montA = NewBigintFromString("486662", 10) curve.a = NewBigintFromString("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa984914a144", 16) curve.b = NewBigintFromString("7b425ed097b425ed097b425ed097b425ed097b425ed097b4260b5e9c7710c864", 16) curve.h = NewBigintFromString("8", 10) curve.conversionFromM = curve.montA.Mul(modinv(NewBigint(3), curve.p)).Mod(curve.p) curve.conversion = curve.p.Sub(curve.montA.Mul(modinv(NewBigint(3), curve.p))).Mod(curve.p) curve.g = curve.liftX(NewBigint(9), false) return &curve } func (curve *WCurve) Eq(other *WCurve) bool { return curve.p.Eq(other.p) && curve.a.Mod(curve.p).Eq(other.a.Mod(curve.p)) && curve.b.Mod(curve.p).Eq(other.b.Mod(curve.p)) } func (curve *WCurve) containsPoint(x, y bigint) bool { p1 := x.Mul(x).Add(curve.a).Mul(x).Add(curve.b) return y.Mul(y).Sub(p1).Mod(curve.p).EqInt(0) } func (curve *WCurve) genPublicKey(priv []byte) (pub []byte, parity bool) { if len(priv) != 32 { panic("invalid private key length") } p := NewBigintFromBytes(priv) pt := curve.g.Mul(p) return curve.toMontgomery(pt) } func (self *WCurve) toMontgomery(pt *JacobiPoint) (bytes []byte, parity bool) { x := pt.AffineX().Add(self.conversion).Mod(self.p) return x.ToBytes(32), pt.AffineY().AndInt(1).EqInt(1) } func (self *WCurve) liftX(x bigint, parity bool) *JacobiPoint { x = x.Mod(self.p) ySquared := x.Mul(x).Mul(x).Add(self.montA.Mul(x).Mul(x).Add(x)).Mod(self.p) x = x.Add(self.conversionFromM).Mod(self.p) ys0, ys1 := primeModSqrt(ySquared, self.p) if ys0.Empty() && ys1.Empty() { return nil } else { pt1 := NewJacobiPoint(self, x, ys0, NewBigint(1), self.r) pt2 := NewJacobiPoint(self, x, ys1, NewBigint(1), self.r) if pt1.AffineY().AndInt(1).EqInt(1) && parity { return pt1 } else if pt2.AffineY().AndInt(1).EqInt(1) && parity { return pt2 } else if pt1.AffineY().AndInt(1).EqInt(0) && !parity { return pt1 } else { return pt2 } } } func (self *WCurve) redp1(bytes []byte, parity bool) *JacobiPoint { x := getSHA2Digest(bytes) for { x2 := getSHA2Digest(x) pt := self.liftX(NewBigintFromBytes(x2), parity) if pt == nil { x = NewBigintFromBytes(x).AddInt(1).ToBytes(32) } else { return pt } } } func (self *WCurve) check(a *JacobiPoint) bool { ax := a.AffineX() ay := a.AffineY() left := ay.Mul(ay).Mod(self.p) right := ax.Mul(ax).Mul(ax).Add(self.a.Mul(ax)).Add(self.b).Mod(self.p) return left.Eq(right) } func (self *WCurve) multiplyByG(a bigint) *JacobiPoint { return self.g.Mul(a) } func (self *WCurve) finiteFieldValue(a bigint) bigint { return a.Mod(self.r) }