Beispiel #1
0
// RepresentativeToPublicKey converts a uniform representative value for a
// curve25519 public key, as produced by ScalarBaseMult, to a curve25519 public
// key.
func RepresentativeToPublicKey(publicKey, representative *[32]byte) {
	var rr2, v, e edwards25519.FieldElement
	edwards25519.FeFromBytes(&rr2, representative)

	edwards25519.FeSquare2(&rr2, &rr2)
	rr2[0]++
	edwards25519.FeInvert(&rr2, &rr2)
	edwards25519.FeMul(&v, &edwards25519.A, &rr2)
	edwards25519.FeNeg(&v, &v)

	var v2, v3 edwards25519.FieldElement
	edwards25519.FeSquare(&v2, &v)
	edwards25519.FeMul(&v3, &v, &v2)
	edwards25519.FeAdd(&e, &v3, &v)
	edwards25519.FeMul(&v2, &v2, &edwards25519.A)
	edwards25519.FeAdd(&e, &v2, &e)
	chi(&e, &e)
	var eBytes [32]byte
	edwards25519.FeToBytes(&eBytes, &e)
	// eBytes[1] is either 0 (for e = 1) or 0xff (for e = -1)
	eIsMinus1 := int32(eBytes[1]) & 1
	var negV edwards25519.FieldElement
	edwards25519.FeNeg(&negV, &v)
	edwards25519.FeCMove(&v, &negV, eIsMinus1)

	edwards25519.FeZero(&v2)
	edwards25519.FeCMove(&v2, &edwards25519.A, eIsMinus1)
	edwards25519.FeSub(&v, &v, &v2)

	edwards25519.FeToBytes(publicKey, &v)
}
Beispiel #2
0
// extendedToBigAffine converts projective x, y, and z field elements into
// affine x and y coordinates, and returns whether or not the x value
// returned is negative.
func (curve *TwistedEdwardsCurve) extendedToBigAffine(xi, yi,
	zi *edwards25519.FieldElement) (*big.Int, *big.Int, bool) {
	var recip, x, y edwards25519.FieldElement

	// Normalize to Z=1.
	edwards25519.FeInvert(&recip, zi)
	edwards25519.FeMul(&x, xi, &recip)
	edwards25519.FeMul(&y, yi, &recip)

	isNegative := edwards25519.FeIsNegative(&x) == 1

	return FieldElementToBigInt(&x), FieldElementToBigInt(&y), isNegative
}
Beispiel #3
0
func edwardsToMontgomeryX(outX, y *edwards25519.FieldElement) {
	// We only need the x-coordinate of the curve25519 point, which I'll
	// call u. The isomorphism is u=(y+1)/(1-y), since y=Y/Z, this gives
	// u=(Y+Z)/(Z-Y). We know that Z=1, thus u=(Y+1)/(1-Y).
	var oneMinusY edwards25519.FieldElement
	edwards25519.FeOne(&oneMinusY)
	edwards25519.FeSub(&oneMinusY, &oneMinusY, y)
	edwards25519.FeInvert(&oneMinusY, &oneMinusY)

	edwards25519.FeOne(outX)
	edwards25519.FeAdd(outX, outX, y)

	edwards25519.FeMul(outX, outX, &oneMinusY)
}
Beispiel #4
0
// RecoverXFieldElement recovers the X value for some Y value, for a coordinate
// on the Ed25519 curve given as a field element. Y value. Probably the fastest
// way to get your respective X from Y.
func (curve *TwistedEdwardsCurve) RecoverXFieldElement(xIsNeg bool,
	y *edwards25519.FieldElement) *edwards25519.FieldElement {
	// (y^2 - 1)
	l := new(edwards25519.FieldElement)
	edwards25519.FeSquare(l, y)
	edwards25519.FeSub(l, l, &feOne)

	// inv(d*y^2+1)
	r := new(edwards25519.FieldElement)
	edwards25519.FeSquare(r, y)
	edwards25519.FeMul(r, r, &fed)
	edwards25519.FeAdd(r, r, &feOne)
	edwards25519.FeInvert(r, r)

	x2 := new(edwards25519.FieldElement)
	edwards25519.FeMul(x2, r, l)

	// Get a big int so we can do the exponentiation.
	x2Big := FieldElementToBigInt(x2)

	// x = exp(x^2,(P+3)/8, P)
	qp3 := new(big.Int).Add(curve.P, three)
	qp3.Div(qp3, eight) // /= curve.H
	xBig := new(big.Int).Exp(x2Big, qp3, curve.P)

	// Convert back to a field element and do
	// the rest.
	x := BigIntToFieldElement(xBig)

	// check (x^2 - x2) % q != 0
	x22 := new(edwards25519.FieldElement)
	edwards25519.FeSquare(x22, x)
	xsub := new(edwards25519.FieldElement)
	edwards25519.FeSub(xsub, x22, x2)
	xsubBig := FieldElementToBigInt(xsub)
	xsubBig.Mod(xsubBig, curve.P)

	if xsubBig.Cmp(zero) != 0 {
		xi := new(edwards25519.FieldElement)
		edwards25519.FeMul(xi, x, &feI)
		xiModBig := FieldElementToBigInt(xi)
		xiModBig.Mod(xiModBig, curve.P)
		xiMod := BigIntToFieldElement(xiModBig)

		x = xiMod
	}

	xBig = FieldElementToBigInt(x)
	xmod2 := new(big.Int).Mod(xBig, two)
	if xmod2.Cmp(zero) != 0 {
		// TODO replace this with FeSub
		xBig.Sub(curve.P, xBig)
		x = BigIntToFieldElement(xBig)
	}

	// We got the wrong x, negate it to get the right one.
	isNegative := edwards25519.FeIsNegative(x) == 1
	if xIsNeg != isNegative {
		edwards25519.FeNeg(x, x)
	}

	return x
}
Beispiel #5
0
// ScalarBaseMult computes a curve25519 public key from a private key and also
// a uniform representative for that public key. Note that this function will
// fail and return false for about half of private keys.
// See http://elligator.cr.yp.to/elligator-20130828.pdf.
func ScalarBaseMult(publicKey, representative, privateKey *[32]byte) bool {
	var maskedPrivateKey [32]byte
	copy(maskedPrivateKey[:], privateKey[:])

	maskedPrivateKey[0] &= 248
	maskedPrivateKey[31] &= 127
	maskedPrivateKey[31] |= 64

	var A edwards25519.ExtendedGroupElement
	edwards25519.GeScalarMultBase(&A, &maskedPrivateKey)

	var inv1 edwards25519.FieldElement
	edwards25519.FeSub(&inv1, &A.Z, &A.Y)
	edwards25519.FeMul(&inv1, &inv1, &A.X)
	edwards25519.FeInvert(&inv1, &inv1)

	var t0, u edwards25519.FieldElement
	edwards25519.FeMul(&u, &inv1, &A.X)
	edwards25519.FeAdd(&t0, &A.Y, &A.Z)
	edwards25519.FeMul(&u, &u, &t0)

	var v edwards25519.FieldElement
	edwards25519.FeMul(&v, &t0, &inv1)
	edwards25519.FeMul(&v, &v, &A.Z)
	edwards25519.FeMul(&v, &v, &sqrtMinusA)

	var b edwards25519.FieldElement
	edwards25519.FeAdd(&b, &u, &edwards25519.A)

	var c, b3, b8 edwards25519.FieldElement
	edwards25519.FeSquare(&b3, &b)   // 2
	edwards25519.FeMul(&b3, &b3, &b) // 3
	edwards25519.FeSquare(&c, &b3)   // 6
	edwards25519.FeMul(&c, &c, &b)   // 7
	edwards25519.FeMul(&b8, &c, &b)  // 8
	edwards25519.FeMul(&c, &c, &u)
	q58(&c, &c)

	var chi edwards25519.FieldElement
	edwards25519.FeSquare(&chi, &c)
	edwards25519.FeSquare(&chi, &chi)

	edwards25519.FeSquare(&t0, &u)
	edwards25519.FeMul(&chi, &chi, &t0)

	edwards25519.FeSquare(&t0, &b)   // 2
	edwards25519.FeMul(&t0, &t0, &b) // 3
	edwards25519.FeSquare(&t0, &t0)  // 6
	edwards25519.FeMul(&t0, &t0, &b) // 7
	edwards25519.FeSquare(&t0, &t0)  // 14
	edwards25519.FeMul(&chi, &chi, &t0)
	edwards25519.FeNeg(&chi, &chi)

	var chiBytes [32]byte
	edwards25519.FeToBytes(&chiBytes, &chi)
	// chi[1] is either 0 or 0xff
	if chiBytes[1] == 0xff {
		return false
	}

	// Calculate r1 = sqrt(-u/(2*(u+A)))
	var r1 edwards25519.FieldElement
	edwards25519.FeMul(&r1, &c, &u)
	edwards25519.FeMul(&r1, &r1, &b3)
	edwards25519.FeMul(&r1, &r1, &sqrtMinusHalf)

	var maybeSqrtM1 edwards25519.FieldElement
	edwards25519.FeSquare(&t0, &r1)
	edwards25519.FeMul(&t0, &t0, &b)
	edwards25519.FeAdd(&t0, &t0, &t0)
	edwards25519.FeAdd(&t0, &t0, &u)

	edwards25519.FeOne(&maybeSqrtM1)
	edwards25519.FeCMove(&maybeSqrtM1, &edwards25519.SqrtM1, edwards25519.FeIsNonZero(&t0))
	edwards25519.FeMul(&r1, &r1, &maybeSqrtM1)

	// Calculate r = sqrt(-(u+A)/(2u))
	var r edwards25519.FieldElement
	edwards25519.FeSquare(&t0, &c)   // 2
	edwards25519.FeMul(&t0, &t0, &c) // 3
	edwards25519.FeSquare(&t0, &t0)  // 6
	edwards25519.FeMul(&r, &t0, &c)  // 7

	edwards25519.FeSquare(&t0, &u)   // 2
	edwards25519.FeMul(&t0, &t0, &u) // 3
	edwards25519.FeMul(&r, &r, &t0)

	edwards25519.FeSquare(&t0, &b8)   // 16
	edwards25519.FeMul(&t0, &t0, &b8) // 24
	edwards25519.FeMul(&t0, &t0, &b)  // 25
	edwards25519.FeMul(&r, &r, &t0)
	edwards25519.FeMul(&r, &r, &sqrtMinusHalf)

	edwards25519.FeSquare(&t0, &r)
	edwards25519.FeMul(&t0, &t0, &u)
	edwards25519.FeAdd(&t0, &t0, &t0)
	edwards25519.FeAdd(&t0, &t0, &b)
	edwards25519.FeOne(&maybeSqrtM1)
	edwards25519.FeCMove(&maybeSqrtM1, &edwards25519.SqrtM1, edwards25519.FeIsNonZero(&t0))
	edwards25519.FeMul(&r, &r, &maybeSqrtM1)

	var vBytes [32]byte
	edwards25519.FeToBytes(&vBytes, &v)
	vInSquareRootImage := feBytesLE(&vBytes, &halfQMinus1Bytes)
	edwards25519.FeCMove(&r, &r1, vInSquareRootImage)

	edwards25519.FeToBytes(publicKey, &u)
	edwards25519.FeToBytes(representative, &r)
	return true
}