コード例 #1
0
ファイル: proj.go プロジェクト: LegoShrimp/crypto
// Equality test for two Points on the same curve.
// We can avoid inversions here because:
//
//	(X1/Z1,Y1/Z1) == (X2/Z2,Y2/Z2)
//		iff
//	(X1*Z2,Y1*Z2) == (X2*Z1,Y2*Z1)
//
func (P1 *projPoint) Equal(CP2 abstract.Point) bool {
	P2 := CP2.(*projPoint)
	var t1, t2 nist.Int
	xeq := t1.Mul(&P1.X, &P2.Z).Equal(t2.Mul(&P2.X, &P1.Z))
	yeq := t1.Mul(&P1.Y, &P2.Z).Equal(t2.Mul(&P2.Y, &P1.Z))
	return xeq && yeq
}
コード例 #2
0
ファイル: curve.go プロジェクト: LegoShrimp/crypto
// Given a y-coordinate, solve for the x-coordinate on the curve,
// using the characteristic equation rewritten as:
//
//	x^2 = (1 - y^2)/(a - d*y^2)
//
// Returns true on success,
// false if there is no x-coordinate corresponding to the chosen y-coordinate.
//
func (c *curve) solveForX(x, y *nist.Int) bool {
	var yy, t1, t2 nist.Int

	yy.Mul(y, y)                     // yy = y^2
	t1.Sub(&c.one, &yy)              // t1 = 1 - y^-2
	t2.Mul(&c.d, &yy).Sub(&c.a, &t2) // t2 = a - d*y^2
	t2.Div(&t1, &t2)                 // t2 = x^2
	return x.Sqrt(&t2)               // may fail if not a square
}
コード例 #3
0
ファイル: el1.go プロジェクト: LegoShrimp/crypto
// Elligator 1 reverse-map from point to uniform representative.
// Returns nil if point has no uniform representative.
// See section 3.3 of the Elligator paper.
func (el *el1param) HideEncode(P point, rand cipher.Stream) []byte {
	ec := el.ec
	x, y := P.getXY()
	var a, b, etar, etarp1, X, z, u, t, t1 nist.Int

	// condition 1: a = y+1 is nonzero
	a.Add(y, &ec.one)
	if a.V.Sign() == 0 {
		return nil // y+1 = 0, no representative
	}

	// etar = r(y-1)/2(y+1)
	t1.Add(y, &ec.one).Add(&t1, &t1) // 2(y+1)
	etar.Sub(y, &ec.one).Mul(&etar, &el.r).Div(&etar, &t1)

	// condition 2: b = (1 + eta r)^2 - 1 is a square
	etarp1.Add(&ec.one, &etar) // etarp1 = (1 + eta r)
	b.Mul(&etarp1, &etarp1).Sub(&b, &ec.one)
	if math.Jacobi(&b.V, b.M) < 0 {
		return nil // b not a square, no representative
	}

	// condition 3: if etar = -2 then x=2s(c-1)Chi(c)/r
	if etar.Equal(&el.m2) && !x.Equal(&el.c3x) {
		return nil
	}

	// X = -(1+eta r)+((1+eta r)^2-1)^((q+1)/4)
	X.Exp(&b, &el.pp1d4).Sub(&X, &etarp1)

	// z = Chi((c-1)sX(1+X)x(X^2+1/c^2))
	z.Mul(&el.cm1s, &X).Mul(&z, t.Add(&ec.one, &X)).Mul(&z, x)
	z.Mul(&z, t.Mul(&X, &X).Add(&t, &el.invc2))
	chi(&z, &z)

	// u = zX
	u.Mul(&z, &X)

	// t = (1-u)/(1+u)
	t.Div(a.Sub(&ec.one, &u), b.Add(&ec.one, &u))

	// Map representative to a byte-string by padding the upper byte.
	// This assumes that the prime c.P is close enough to a power of 2
	// that the adversary will never notice the "missing" values;
	// this is true for the class of curves Elligator1 was designed for.
	rep, _ := t.MarshalBinary()
	padmask := el.padmask()
	if padmask != 0 {
		var pad [1]byte
		rand.XORKeyStream(pad[:], pad[:])
		rep[0] |= pad[0] & padmask
	}
	return rep
}
コード例 #4
0
ファイル: el2.go プロジェクト: LegoShrimp/crypto
// Compute the square root function,
// specified in section 5.5 of the Elligator paper.
func (el *el2param) sqrt(r, a *nist.Int) {
	var b, b2 nist.Int
	b.Exp(a, &el.pp3d8) // b = a^((p+3)/8); b in {a,-a}

	b2.Mul(&b, &b) // b^2 = a?
	if !b2.Equal(a) {
		b.Mul(&b, &el.sqrtm1) // b*sqrt(-1)
	}

	if b.V.Cmp(&el.pm1d2) > 0 { // |b|
		b.Neg(&b)
	}

	r.Set(&b)
}
コード例 #5
0
ファイル: el2.go プロジェクト: LegoShrimp/crypto
// Elligator 2 forward-map from representative to Edwards curve point.
// Currently a straightforward, unoptimized implementation.
// See section 5.2 of the Elligator paper.
func (el *el2param) HideDecode(P point, rep []byte) {
	ec := el.ec
	var r, v, x, y, t1, edx, edy nist.Int

	l := ec.PointLen()
	if len(rep) != l {
		panic("el2Map: wrong representative length")
	}

	// Take the appropriate number of bits from the representative.
	buf := make([]byte, l)
	copy(buf, rep)
	buf[0] &^= el.padmask() // mask off the padding bits
	r.InitBytes(buf, &ec.P)

	// v = -A/(1+ur^2)
	v.Mul(&r, &r).Mul(&el.u, &v).Add(&ec.one, &v).Div(&el.negA, &v)

	// e = Chi(v^3+Av^2+Bv), where B=1 because of ed2mont equivalence
	t1.Add(&v, &el.A).Mul(&t1, &v).Add(&t1, &ec.one).Mul(&t1, &v)
	e := math.Jacobi(&t1.V, t1.M)

	// x = ev-(1-e)A/2
	if e == 1 {
		x.Set(&v)
	} else {
		x.Add(&v, &el.A).Neg(&x)
	}

	// y = -e sqrt(x^3+Ax^2+Bx), where B=1
	y.Add(&x, &el.A).Mul(&y, &x).Add(&y, &ec.one).Mul(&y, &x)
	el.sqrt(&y, &y)
	if e == 1 {
		y.Neg(&y) // -e factor
	}

	// Convert Montgomery to Edwards coordinates
	el.mont2ed(&edx, &edy, &x, &y)

	// Sanity-check
	if !ec.onCurve(&edx, &edy) {
		panic("elligator2 produced invalid point")
	}

	P.initXY(&edx.V, &edy.V, ec.self)
}
コード例 #6
0
ファイル: curve.go プロジェクト: LegoShrimp/crypto
// Test if a supposed point is on the curve,
// by checking the characteristic equation for Edwards curves:
//
//	a*x^2 + y^2 = 1 + d*x^2*y^2
//
func (c *curve) onCurve(x, y *nist.Int) bool {
	var xx, yy, l, r nist.Int

	xx.Mul(x, x) // xx = x^2
	yy.Mul(y, y) // yy = y^2

	l.Mul(&c.a, &xx).Add(&l, &yy) // l = a*x^2 + y^2
	r.Mul(&c.d, &xx).Mul(&r, &yy).Add(&c.one, &r)
	// r = 1 + d*x^2*y^2
	return l.Equal(&r)
}
コード例 #7
0
ファイル: proj.go プロジェクト: LegoShrimp/crypto
// Subtract points so that their scalars subtract homomorphically
func (P *projPoint) Sub(CP1, CP2 abstract.Point) abstract.Point {
	P1 := CP1.(*projPoint)
	P2 := CP2.(*projPoint)
	X1, Y1, Z1 := &P1.X, &P1.Y, &P1.Z
	X2, Y2, Z2 := &P2.X, &P2.Y, &P2.Z
	X3, Y3, Z3 := &P.X, &P.Y, &P.Z
	var A, B, C, D, E, F, G nist.Int

	A.Mul(Z1, Z2)
	B.Mul(&A, &A)
	C.Mul(X1, X2)
	D.Mul(Y1, Y2)
	E.Mul(&C, &D).Mul(&P.c.d, &E)
	F.Add(&B, &E)
	G.Sub(&B, &E)
	X3.Add(X1, Y1).Mul(X3, Z3.Sub(Y2, X2)).Add(X3, &C).Sub(X3, &D).
		Mul(&F, X3).Mul(&A, X3)
	Y3.Mul(&P.c.a, &C).Add(&D, Y3).Mul(&G, Y3).Mul(&A, Y3)
	Z3.Mul(&F, &G)
	return P
}
コード例 #8
0
ファイル: proj.go プロジェクト: LegoShrimp/crypto
// Optimized point doubling for use in scalar multiplication.
func (P *projPoint) double() {
	var B, C, D, E, F, H, J nist.Int

	B.Add(&P.X, &P.Y).Mul(&B, &B)
	C.Mul(&P.X, &P.X)
	D.Mul(&P.Y, &P.Y)
	E.Mul(&P.c.a, &C)
	F.Add(&E, &D)
	H.Mul(&P.Z, &P.Z)
	J.Add(&H, &H).Sub(&F, &J)
	P.X.Sub(&B, &C).Sub(&P.X, &D).Mul(&P.X, &J)
	P.Y.Sub(&E, &D).Mul(&F, &P.Y)
	P.Z.Mul(&F, &J)
}
コード例 #9
0
ファイル: ext.go プロジェクト: Liamsi/crypto
// Subtract points.
func (P *extPoint) Sub(CP1, CP2 abstract.Point) abstract.Point {
	P1 := CP1.(*extPoint)
	P2 := CP2.(*extPoint)
	X1, Y1, Z1, T1 := &P1.X, &P1.Y, &P1.Z, &P1.T
	X2, Y2, Z2, T2 := &P2.X, &P2.Y, &P2.Z, &P2.T
	X3, Y3, Z3, T3 := &P.X, &P.Y, &P.Z, &P.T
	var A, B, C, D, E, F, G, H nist.Int

	A.Mul(X1, X2)
	B.Mul(Y1, Y2)
	C.Mul(T1, T2).Mul(&C, &P.c.d)
	D.Mul(Z1, Z2)
	E.Add(X1, Y1).Mul(&E, F.Sub(Y2, X2)).Add(&E, &A).Sub(&E, &B)
	F.Add(&D, &C)
	G.Sub(&D, &C)
	H.Mul(&P.c.a, &A).Add(&B, &H)
	X3.Mul(&E, &F)
	Y3.Mul(&G, &H)
	T3.Mul(&E, &H)
	Z3.Mul(&F, &G)
	return P
}
コード例 #10
0
ファイル: basic.go プロジェクト: Liamsi/crypto
// Add two points using the basic unified addition laws for Edwards curves:
//
//	x' = ((x1*y2 + x2*y1) / (1 + d*x1*x2*y1*y2))
//	y' = ((y1*y2 - a*x1*x2) / (1 - d*x1*x2*y1*y2))
//
func (P *basicPoint) Add(P1, P2 abstract.Point) abstract.Point {
	E1 := P1.(*basicPoint)
	E2 := P2.(*basicPoint)
	x1, y1 := E1.x, E1.y
	x2, y2 := E2.x, E2.y

	var t1, t2, dm, nx, dx, ny, dy nist.Int

	// Reused part of denominator: dm = d*x1*x2*y1*y2
	dm.Mul(&P.c.d, &x1).Mul(&dm, &x2).Mul(&dm, &y1).Mul(&dm, &y2)

	// x' numerator/denominator
	nx.Add(t1.Mul(&x1, &y2), t2.Mul(&x2, &y1))
	dx.Add(&P.c.one, &dm)

	// y' numerator/denominator
	ny.Sub(t1.Mul(&y1, &y2), t2.Mul(&x1, &x2).Mul(&P.c.a, &t2))
	dy.Sub(&P.c.one, &dm)

	// result point
	P.x.Div(&nx, &dx)
	P.y.Div(&ny, &dy)
	return P
}
コード例 #11
0
ファイル: ext.go プロジェクト: Liamsi/crypto
// Optimized point doubling for use in scalar multiplication.
// Uses the formulae in section 3.3 of:
// https://www.iacr.org/archive/asiacrypt2008/53500329/53500329.pdf
func (P *extPoint) double() {
	X1, Y1, Z1, T1 := &P.X, &P.Y, &P.Z, &P.T
	var A, B, C, D, E, F, G, H nist.Int

	A.Mul(X1, X1)
	B.Mul(Y1, Y1)
	C.Mul(Z1, Z1).Add(&C, &C)
	D.Mul(&P.c.a, &A)
	E.Add(X1, Y1).Mul(&E, &E).Sub(&E, &A).Sub(&E, &B)
	G.Add(&D, &B)
	F.Sub(&G, &C)
	H.Sub(&D, &B)
	X1.Mul(&E, &F)
	Y1.Mul(&G, &H)
	T1.Mul(&E, &H)
	Z1.Mul(&F, &G)
}
コード例 #12
0
ファイル: el2.go プロジェクト: LegoShrimp/crypto
// Elligator 2 reverse-map from point to uniform representative.
// Returns nil if point has no uniform representative.
// See section 5.3 of the Elligator paper.
func (el *el2param) HideEncode(P point, rand cipher.Stream) []byte {
	edx, edy := P.getXY()
	var x, y, r, xpA, t1 nist.Int

	// convert Edwards to Montgomery coordinates
	el.ed2mont(&x, &y, edx, edy)

	// condition 1: x != -A
	if x.Equal(&el.negA) {
		return nil // x = -A, no representative
	}

	// condition 2: if y=0, then x=0
	if y.V.Sign() == 0 && x.V.Sign() != 0 {
		return nil // y=0 but x!=0, no representative
	}

	// condition 3: -ux(x+A) is a square
	xpA.Add(&x, &el.A)
	t1.Mul(&el.u, &x).Mul(&t1, &xpA).Neg(&t1)
	if math.Jacobi(&t1.V, t1.M) < 0 {
		return nil // not a square, no representative
	}

	if y.V.Cmp(&el.pm1d2) <= 0 { // y in image of sqrt function
		r.Mul(&xpA, &el.u).Div(&x, &r)
	} else { // y not in image of sqrt function
		r.Mul(&el.u, &x).Div(&xpA, &r)
	}
	r.Neg(&r)
	el.sqrt(&r, &r)

	// Sanity check on result
	if r.V.Cmp(&el.pm1d2) > 0 {
		panic("el2: r too big")
	}

	// Map representative to a byte-string by padding the upper byte.
	// This assumes that the prime c.P is close enough to a power of 2
	// that the adversary will never notice the "missing" values;
	// this is true for the class of curves Elligator1 was designed for.
	rep, _ := r.MarshalBinary()
	padmask := el.padmask()
	if padmask != 0 {
		var pad [1]byte
		rand.XORKeyStream(pad[:], pad[:])
		rep[0] |= pad[0] & padmask
	}
	return rep
}
コード例 #13
0
ファイル: el1.go プロジェクト: LegoShrimp/crypto
// Elligator 1 forward-map from representative to Edwards curve point.
// Currently a straightforward, unoptimized implementation.
// See section 3.2 of the Elligator paper.
func (el *el1param) HideDecode(P point, rep []byte) {
	ec := el.ec
	var t, u, u2, v, Chiv, X, Y, x, y, t1, t2 nist.Int

	l := ec.PointLen()
	if len(rep) != l {
		panic("el1Map: wrong representative length")
	}

	// Take the appropriate number of bits from the representative.
	b := make([]byte, l)
	copy(b, rep)
	b[0] &^= el.padmask() // mask off the padding bits
	t.InitBytes(b, &ec.P)

	// u = (1-t)/(1+t)
	u.Div(t1.Sub(&ec.one, &t), t2.Add(&ec.one, &t))

	// v = u^5 + (r^2-2)u^3 + u
	u2.Mul(&u, &u)                   // u2 = u^2
	v.Mul(&u2, &u2)                  // v = u^4
	v.Add(&v, t1.Mul(&el.r2m2, &u2)) // v = u^4 + (r^2-2)u^2
	v.Add(&v, &ec.one).Mul(&v, &u)   // v = u^5 + (r^2-2)u^3 + u

	// X = Chi(v)u
	chi(&Chiv, &v)
	X.Mul(&Chiv, &u)

	// Y = (Chi(v)v)^((q+1)/4) Chi(v) Chi(u^2+1/c^2)
	t1.Add(&u2, &el.invc2)
	chi(&t1, &t1) // t1 = Chi(u^2+1/c^2)
	Y.Mul(&Chiv, &v)
	Y.Exp(&Y, &el.pp1d4).Mul(&Y, &Chiv).Mul(&Y, &t1)

	// x = (c-1)sX(1+X)/Y
	x.Add(&ec.one, &X).Mul(&X, &x).Mul(&el.cm1s, &x).Div(&x, &Y)

	// y = (rX-(1+X)^2)/(rX+(1+X)^2)
	t1.Mul(&el.r, &X)                 // t1 = rX
	t2.Add(&ec.one, &X).Mul(&t2, &t2) // t2 = (1+X)^2
	y.Div(u.Sub(&t1, &t2), v.Add(&t1, &t2))

	// Sanity-check
	if !ec.onCurve(&x, &y) {
		panic("elligator1 produced invalid point")
	}

	P.initXY(&x.V, &y.V, ec.self)
}
コード例 #14
0
ファイル: ext.go プロジェクト: Liamsi/crypto
// Check the validity of the T coordinate
func (P *extPoint) checkT() {
	var t1, t2 nist.Int
	if !t1.Mul(&P.X, &P.Y).Equal(t2.Mul(&P.Z, &P.T)) {
		panic("oops")
	}
}
コード例 #15
0
ファイル: el2.go プロジェクト: LegoShrimp/crypto
// Convert from Montgomery form (u,v) to Edwards (x,y) via:
//
//	x = sqrt(B)u/v
//	y = (u-1)/(u+1)
//
func (el *el2param) mont2ed(x, y, u, v *nist.Int) {
	ec := el.ec
	var t1, t2 nist.Int
	x.Mul(u, &el.sqrtB).Div(x, v)
	y.Div(t1.Sub(u, &ec.one), t2.Add(u, &ec.one))
}
コード例 #16
0
ファイル: el2.go プロジェクト: LegoShrimp/crypto
// Convert point from Twisted Edwards form: ax^2+y^2 = 1+dx^2y^2
// to Montgomery form: v^2 = u^3+Au^2+u
// via the equivalence:
//
//	u = (1+y)/(1-y)
//	v = sqrt(B)u/x
//
// where A=2(a+d)/(a-d) and B=4(a-d)
//
// Beware: the Twisted Edwards Curves paper uses B as a factor for v^2,
// whereas the Elligator 2 paper uses B as a factor for the last u term.
//
func (el *el2param) ed2mont(u, v, x, y *nist.Int) {
	ec := el.ec
	var t1, t2 nist.Int
	u.Div(t1.Add(&ec.one, y), t2.Sub(&ec.one, y))
	v.Mul(u, &el.sqrtB).Div(v, x)
}