📶 [WIP] RouterOS WinBox bruteforce
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mtbf/point.go

384 lines
8.4 KiB

package main
import (
_ "fmt"
)
type Point struct {
curve *WCurve
x, y bigint
order bigint
}
var InfinityPoint *Point = NewInfPoint()
func NewPoint(curve *WCurve, x, y, order bigint) *Point {
point := Point{}
point.x = x
point.y = y
point.order = order
/*if curve != nil && !curve.containsPoint(x, y) {
panic("point is not on a curve")
}/*
/*if curve != nil && curve.h.NeInt(1) && !order.Empty() {
if point.Mul(order).Eq(InfinityPoint) {
panic("point is not a scalar multiple")
}
}*/
return &point
}
func NewInfPoint() *Point {
return NewPoint(nil, NewEmptyBigint(), NewEmptyBigint(), NewEmptyBigint())
}
func (self *Point) IsInf() bool {
return self.curve == nil && self.x.Empty() && self.y.Empty()
}
func (self *Point) Eq(other *Point) bool {
eqCurve := self.curve != nil && other.curve != nil && self.curve.Eq(other.curve)
eqX := !self.x.Empty() && !other.x.Empty() && self.x.Eq(other.x)
eqY := !self.y.Empty() && !other.y.Empty() && self.y.Eq(other.y)
if self.IsInf() && other.IsInf() {
return true
}
return eqCurve && eqX && eqY
}
func (self *Point) Neg() *Point {
return NewPoint(self.curve, self.x, self.curve.p.Sub(self.y), NewEmptyBigint())
}
func (self *Point) Add(other *Point) *Point {
if other.Eq(InfinityPoint) {
return self
}
if self.Eq(InfinityPoint) {
return other
}
if !self.curve.Eq(other.curve) {
panic("cannot add points on different curves")
}
if self.x.Eq(other.x) {
if self.y.Add(other.y).Mod(self.curve.p).EqInt(0) {
return NewInfPoint()
} else {
return self.Double()
}
}
p := self.curve.p
im := modinv(other.x.Sub(self.x), p)
l := other.y.Sub(self.y).Mul(im).Mod(p)
x3 := l.Mul(l).Sub(self.x).Sub(other.x).Mod(p)
y3 := l.Mul(self.x.Sub(x3)).Sub(self.y).Mod(p)
return NewPoint(self.curve, x3, y3, NewEmptyBigint())
}
func (self *Point) Mul(other bigint) *Point {
e := other
if e.EqInt(0) || (!self.order.Empty() && e.Mod(self.order).EqInt(0)) {
return NewInfPoint()
}
if self.Eq(InfinityPoint) {
return NewInfPoint()
}
if e.LtInt(0) {
return self.Neg().Mul(e.Neg())
}
e3 := e.MulInt(3)
negativeSelf := NewPoint(self.curve, self.x, self.y.Neg(), self.order)
i := leftmostBit(e3).DivInt(2)
res := self
for i.GtInt(1) {
res = res.Double()
if !e3.And(i).EqInt(0) && e.And(i).EqInt(0) {
res = res.Add(self)
}
if e3.And(i).EqInt(0) && !e.And(i).EqInt(0) {
res = res.Add(negativeSelf)
}
i = i.DivInt(2)
}
return res
}
func (self *Point) Double() *Point {
if self.Eq(InfinityPoint) {
return NewInfPoint()
}
p := self.curve.p
a := self.curve.a
im := modinv(self.y.MulInt(2), p)
l := self.x.MulInt(3).Mul(self.x).Add(a).Mul(im).Mod(p)
x3 := l.Mul(l).Sub(self.x.MulInt(2)).Mod(p)
y3 := l.Mul(self.x.Sub(x3)).Sub(self.y).Mod(p)
return NewPoint(self.curve, x3, y3, NewEmptyBigint())
}
type JacobiPoint struct {
curve *WCurve
x, y, z bigint
order bigint
}
func NewJacobiPoint(curve *WCurve, x, y, z, order bigint) *JacobiPoint {
// attempt to initialize normal point
NewPoint(curve, x, y, order)
point := JacobiPoint{}
point.x = x
point.y = y
point.z = z
point.curve = curve
point.order = order
return &point
}
func NewInfJacobiPoint() *JacobiPoint {
return NewJacobiPoint(nil, NewEmptyBigint(), NewEmptyBigint(), NewEmptyBigint(), NewEmptyBigint())
}
func (self *JacobiPoint) IsInf() bool {
return self.curve == nil && self.x.Empty() && self.y.Empty() && self.z.Empty()
}
func (self *JacobiPoint) EqCoords(x2, y2, z2 bigint) bool {
x1 := self.x
y1 := self.y
z1 := self.z
p := self.curve.p
zz1 := z1.Mul(z1).Mod(p)
zz2 := z2.Mul(z2).Mod(p)
m1 := x1.Mul(zz2).Sub(x2.Mul(zz1)).Mod(p)
m2 := y1.Mul(zz2).Mul(z2).Sub(y2.Mul(zz1).Mul(z1)).Mod(p)
return m1.EqInt(0) && m2.EqInt(0)
}
func (self *JacobiPoint) EqPoint(other *Point) bool {
if other.IsInf() {
return self.y.Empty() || self.z.Empty()
}
if !self.curve.Eq(other.curve) {
return false
}
return self.EqCoords(other.x, other.y, NewBigint(1))
}
func (self *JacobiPoint) Eq(other *JacobiPoint) bool {
if other.IsInf() {
return self.y.Empty() || self.z.Empty()
}
if !self.curve.Eq(other.curve) {
return false
}
return self.EqCoords(other.x, other.y, other.z)
}
func (self *JacobiPoint) Neg() *JacobiPoint {
return NewJacobiPoint(self.curve, self.x, self.y.Neg(), self.z, self.order)
}
func (self *JacobiPoint) AffineX() bigint {
if self.z.EqInt(1) {
return self.x
}
z := modinv(self.z, self.curve.p)
return self.x.Mul(z.Mul(z)).Mod(self.curve.p)
}
func (self *JacobiPoint) AffineY() bigint {
if self.z.EqInt(1) {
return self.y
}
z := modinv(self.z, self.curve.p)
return self.y.Mul(z.Mul(z).Mul(z)).Mod(self.curve.p)
}
// modifies in-place
func (self *JacobiPoint) Scale() *JacobiPoint {
if self.z.EqInt(1) {
return self
}
p := self.curve.p
zInv := modinv(self.z, p)
zzInv := zInv.Mul(zInv).Mod(p)
x := self.x.Mul(zzInv).Mod(p)
y := self.y.Mul(zzInv).Mul(zInv).Mod(p)
self.x = x
self.y = y
self.z = NewBigint(1)
return self
}
func (self *JacobiPoint) ToAffine() *Point {
if self.y.Empty() || self.z.Empty() {
return NewInfPoint()
}
self.Scale()
return NewPoint(self.curve, self.x, self.y, self.order)
}
func (self *Point) FromAffine() *JacobiPoint {
return NewJacobiPoint(self.curve, self.x, self.y, NewBigint(1), self.order)
}
func (self *JacobiPoint) _Double(x1, y1, z1, p, a bigint) (t, y3, z3 bigint) {
if y1.Empty() || z1.Empty() {
return NewBigint(0), NewBigint(0), NewBigint(1)
}
xx, yy := x1.Mul(x1).Mod(p), y1.Mul(y1).Mod(p)
if yy.Empty() {
return NewBigint(0), NewBigint(0), NewBigint(1)
}
yyyy := yy.Mul(yy).Mod(p)
zz := z1.Mul(z1).Mod(p)
s := NewBigint(2).Mul(x1.Add(yy).Mul(x1.Add(yy)).Sub(xx).Sub(yyyy)).Mod(p)
m := NewBigint(3).Mul(xx).Add(a.Mul(zz).Mul(zz)).Mod(p)
t = m.Mul(m).Sub(NewBigint(2).Mul(s)).Mod(p)
y3 = m.Mul(s.Sub(t)).Sub(NewBigint(8).Mul(yyyy)).Mod(p)
z3 = y1.Add(z1).Mul(y1.Add(z1)).Sub(yy).Sub(zz).Mod(p)
return t, y3, z3
}
func (self *JacobiPoint) Double() *JacobiPoint {
if self.y.Empty() {
return NewInfJacobiPoint()
}
x3, y3, z3 := self._Double(self.x, self.y, self.z, self.curve.p, self.curve.a)
if y3.Empty() || z3.Empty() {
return NewInfJacobiPoint()
}
return NewJacobiPoint(self.curve, x3, y3, z3, self.order)
}
func (self *JacobiPoint) _Add(x1, y1, z1, x2, y2, z2, p bigint) (x3, y3, z3 bigint) {
if y1.Empty() || z1.Empty() {
return x2, y2, z2
}
if y2.Empty() || z2.Empty() {
return x1, y1, z1
}
z1z1 := z1.Mul(z1).Mod(p)
z2z2 := z2.Mul(z2).Mod(p)
u1 := x1.Mul(z2z2).Mod(p)
u2 := x2.Mul(z1z1).Mod(p)
s1 := y1.Mul(z2).Mul(z2z2).Mod(p)
s2 := y2.Mul(z1).Mul(z1z1).Mod(p)
h := u2.Sub(u1)
i := NewBigint(4).Mul(h).Mul(h).Mod(p)
j := h.Mul(i).Mod(p)
r := NewBigint(2).Mul(s2.Sub(s1)).Mod(p)
if h.Empty() && r.Empty() {
return self._Double(x1, y1, z1, p, self.curve.a)
}
v := u1.Mul(i)
x3 = r.Mul(r).Sub(j).Sub(NewBigint(2).Mul(v)).Mod(p)
y3 = r.Mul(v.Sub(x3)).Sub(NewBigint(2).Mul(s1).Mul(j)).Mod(p)
z3 = z1.Add(z2).Mul(z1.Add(z2)).Sub(z1z1).Sub(z2z2).Mul(h).Mod(p)
return x3, y3, z3
}
func (self *JacobiPoint) AddPoint(other *Point) *JacobiPoint {
return self.Add(other.FromAffine())
}
func (self *JacobiPoint) Add(other *JacobiPoint) *JacobiPoint {
if other.IsInf() {
return self
}
if self.IsInf() {
return other
}
if !self.curve.Eq(other.curve) {
panic("cannot add with different curves")
}
x3, y3, z3 := self._Add(self.x, self.y, self.z, other.x, other.y, other.z, self.curve.p)
if y3.Empty() || z3.Empty() {
return NewInfJacobiPoint()
}
return NewJacobiPoint(self.curve, x3, y3, z3, self.order)
}
func (self *JacobiPoint) Mul(other bigint) *JacobiPoint {
if self.y.Empty() || other.Empty() {
return NewInfJacobiPoint()
}
if other.EqInt(1) {
return self
}
if !self.order.Empty() {
other = other.Mod(self.order.MulInt(2))
}
self = self.Scale()
x2, y2 := self.x, self.y
x3, y3, z3 := NewBigint(0), NewBigint(0), NewBigint(1)
p, a := self.curve.p, self.curve.a
nf := naf(other)
for i := len(nf) - 1; i >= 0; i-- {
x3, y3, z3 = self._Double(x3, y3, z3, p, a)
if nf[i].LtInt(0) {
x3, y3, z3 = self._Add(x3, y3, z3, x2, y2.Neg(), NewBigint(1), p)
} else if nf[i].GtInt(0) {
x3, y3, z3 = self._Add(x3, y3, z3, x2, y2, NewBigint(1), p)
}
}
if y3.Empty() || z3.Empty() {
return NewInfJacobiPoint()
}
return NewJacobiPoint(self.curve, x3, y3, z3, self.order)
}
func (self *JacobiPoint) MulAdd(selfMul bigint, other *JacobiPoint, otherMul bigint) *JacobiPoint {
return self.Mul(selfMul).Add(other.Mul(otherMul))
}