/// <summary> /// Used by the initiator. Generates an initial point to be submitted to the token service for signing. /// </summary> /// <param name="curve">Curve parameters</param> /// <returns>The seed t for a random point, the initial mask r of the point, and the masked point P</returns> public (byte[] t, BigInteger r, ECPoint P) Initiate(ECCurve curve) { BigInteger r = ECCurveRandomNumberGenerator.GenerateRandomNumber(curve, _random); // Sample random bytes t such that x = hash(t) is a valid // x-coordinate on the curve. Then T = HashToWeierstrassCurve(t). byte[]? t = new byte[32]; ECPoint?T; for (; ;) { _random.NextBytes(t); T = ECCurveHash.HashToWeierstrassCurve(curve, t); if (T == null) { continue; } break; } if (T == null) { throw new AnonymousTokensException("Point T is null after unsuccessfull hashing"); } // Compute P = r*T ECPoint P = T.Multiply(r); return(t, r, P); }
/// <summary> /// Used by the token service. Creates a full transcript of a Chaum-Pedersen protocol instance, using the strong Fiat-Shamir transform. /// The Chaum-Pedersen proof proves that the same secret key k is used to compute K = k*G and Q = k*P, without revealing k. /// </summary> /// <param name="ecParameters">Curve parameters</param> /// <param name="k">The private key of the token scheme</param> /// <param name="K">The public key of the token scheme</param> /// <param name="P">Point submitted by the initiator</param> /// <param name="Q">Point signed using the secret key</param> /// <returns></returns> private (BigInteger c, BigInteger z) CreateProof( X9ECParameters ecParameters, BigInteger k, ECPoint K, ECPoint P, ECPoint Q) { // Sample a random integer 0 < r < N BigInteger r = ECCurveRandomNumberGenerator.GenerateRandomNumber(ecParameters.Curve, _random); // Computes X = r*G ECPoint X = ecParameters.G.Multiply(r); // Computes Y = r*P ECPoint Y = P.Multiply(r); BigInteger c = CPChallengeGenerator.CreateChallenge(ecParameters.G, P, K, Q, X, Y); // Compute proof z = r - ck mod N BigInteger z = r.Subtract(c.Multiply(k)).Mod(ecParameters.Curve.Order); return(c, z); }