/// <summary> /// Derives an unpredictable element of the group, using the input. Each /// construction defines its own derivation mechanism, but each takes an /// optional context string and an index, and returns a counter. Calling /// this method with the same parameter values returns the same element /// and counter, calling it with a different context or index value must /// return a different element. /// </summary> /// <param name="context">An optional context used by the derivation /// mechanism, can be null.</param> /// <param name="index">An 8-bit integer index value.</param> /// <param name="counter">A counter value indicating the state at which the /// derivation mechanism stopped.</param> /// <returns>A random group element.</returns> public override GroupElement DeriveElement(byte[] context, byte index, out int counter) { // concatenate context and curve name BouncyCastle.FpCurve curve = this.domainParams.Curve as BouncyCastle.FpCurve; int count = 0; BouncyCastle.ECFieldElement x = null, y = null; while (y == null) { x = GetX(context, curve, index, count); BouncyCastle.ECFieldElement alpha = x.Multiply(x.Square().Add(curve.A)).Add(curve.B); if (alpha.ToBigInteger() == BCBigInt.Zero) { y = alpha; } else { y = alpha.Sqrt(); // returns null if sqrt does not exist } count++; } // determine which sqrt to return, i.e., Min(y, -y) BouncyCastle.ECFieldElement minusY = y.Negate(); counter = count - 1; return(new ECGroupElementBCImpl(new BouncyCastle.FpPoint(curve, x, y.ToBigInteger() < minusY.ToBigInteger() ? y : minusY))); }
private void CheckOnCurve(GroupElement e) { ECGroupElementBCImpl ecge = e as ECGroupElementBCImpl; if (ecge == null) { throw new ArgumentNullException(); } BouncyCastle.FpPoint p = ecge.Point; BouncyCastle.ECFieldElement x = p.AffineXCoord, y = p.AffineYCoord; if (!y.Square().Equals(x.Multiply(x.Square().Add(domainParams.Curve.A)).Add(domainParams.Curve.B))) { throw new InvalidUProveArtifactException("point is not on curve"); } }