/// <summary> /// Used by the initiator. It first verifies that the incoming token is well-formed, and then removes the previously applied mask. /// </summary> /// <param name="ecParameters">Curve parameters</param> /// <param name="K">The public key point for the token scheme</param> /// <param name="P">Masked point initially submitted to the token service</param> /// <param name="Q">Signed masked point returned from the token service</param> /// <param name="c">Claimed challenge from the Chaum-Pedersen proof</param> /// <param name="z">Response from the Chaum-Pedersen proof</param> /// <param name="r">Masking of the initial point</param> /// <returns>A randomised signature W on the point chosen by the initiator</returns> public ECPoint RandomiseToken(X9ECParameters ecParameters, ECPoint K, ECPoint P, ECPoint Q, BigInteger c, BigInteger z, BigInteger r) { ECCurve?curve = ecParameters.Curve; // Check that P is a valid point on the currect curve if (ECPointVerifier.PointIsValid(P, curve) == false) { throw new AnonymousTokensException("P is not a valid point on the curve"); } // Check that Q is a valid point on the currect curve if (ECPointVerifier.PointIsValid(Q, curve) == false) { throw new AnonymousTokensException("Q is not a valid point on the curve"); } // Verify the proof (c,z). if (!VerifyProof(ecParameters, K, P, Q, c, z)) { throw new AnonymousTokensException("Chaum-Pedersen proof is invalid"); } // Removing the initial mask r. W = (1/r)*Q = k*T. BigInteger?rInverse = r.ModInverse(ecParameters.Curve.Order); ECPoint? W = Q.Multiply(rInverse); return(W); }
/// <summary> /// Used by the token verifier. It recreates the initial point from the initiator, signs it, and verifies that they are equal. /// </summary> /// <param name="k">The private key for the token scheme</param> /// <param name="curve">Curve parameters</param> /// <param name="t">Seed for the initial point chosen by the initiator</param> /// <param name="W">Token received from the initiator</param> /// <returns>True if the token is valid, otherwise false</returns> public async Task <bool> VerifyTokenAsync( BigInteger k, ECCurve curve, byte[] t, ECPoint W) { // Check if token t is received earlier if (await _seedStore.ExistsAsync(t)) { return(false); } // Check that W is a valid point on the currect curve if (ECPointVerifier.PointIsValid(W, curve) == false) { throw new AnonymousTokensException("W is not a valid point on the curve"); } await _seedStore.SaveAsync(t); ECPoint?T = ECCurveHash.HashToWeierstrassCurve(curve, t); if (T == null) { return(false); } ECPoint?V = T.Multiply(k); return(V.Equals(W)); }
public void PointIsValid_PointIsOnCurve_ReturnsTrue() { // Arrange var curve = Fp.curve; var point = Fp.p[0]; // Act var actual = ECPointVerifier.PointIsValid(point, curve); // Assert Assert.True(actual); }
public void PointIsValid_PointIsNotOnCurve_ReturnsFalse() { // Arrange var x9 = ECNamedCurveTable.GetByName("prime239v1"); var curve = x9.Curve; var point = Fp.p[0]; // Act var actual = ECPointVerifier.PointIsValid(point, curve); // Assert Assert.False(actual); }
/// <summary> /// Used by the token service. Signs the point submitted by the initiator in order to create a token, and outputs a proof of validity. /// </summary> /// <param name="k">The private key for the token scheme</param> /// <param name="K">The public key for the token scheme</param> /// <param name="ecParameters">Curve parameters</param> /// <param name="P">Point submitted by the app</param> /// <returns>A signed point Q and a Chaum-Pedersen proof (c,z) proving that the point is signed correctly</returns> public (ECPoint Q, BigInteger c, BigInteger z) GenerateToken( BigInteger k, ECPoint K, X9ECParameters ecParameters, ECPoint P) { ECCurve?curve = ecParameters.Curve; // Check that P is a valid point on the currect curve if (ECPointVerifier.PointIsValid(P, curve) == false) { throw new AnonymousTokensException("P is not a valid point on the curve"); } // Compute Q = k*P ECPoint?Q = P.Multiply(k); // Chaum-Pedersen proof of correct signature var(c, z) = CreateProof(ecParameters, k, K, P, Q); return(Q, c, z); }