public void CanProveAndVerifyZeroProofs() { using var rnd = new SecureRandom(); var a0 = Scalar.Zero; var r0 = rnd.GetScalar(); var ma0 = a0 * Generators.Gg + r0 * Generators.Gh; var a1 = Scalar.Zero; var r1 = rnd.GetScalar(); var ma1 = a1 * Generators.Gg + r1 * Generators.Gh; var knowledge = new[] { ProofSystem.ZeroProofKnowledge(ma0, r0), ProofSystem.ZeroProofKnowledge(ma1, r1) }; var proofs = ProofSystem.Prove(new Transcript(Array.Empty <byte>()), knowledge, rnd); var statements = new[] { ProofSystem.ZeroProofStatement(ma0), ProofSystem.ZeroProofStatement(ma1) }; Assert.True(ProofSystem.Verify(new Transcript(Array.Empty <byte>()), statements, proofs)); }
public void CanProveAndVerifyMAC() { // The coordinator generates a composed private key called CoordinatorSecretKey // and derives from that the coordinator's public parameters called CoordinatorParameters. var rnd = new SecureRandom(); var coordinatorKey = new CoordinatorSecretKey(rnd); var coordinatorParameters = coordinatorKey.ComputeCoordinatorParameters(); // A blinded amount is known as an `attribute`. In this case the attribute Ma is the // value 10000 blinded with a random `blindingFactor`. This attribute is sent to // the coordinator. var amount = new Scalar(10_000); var blindingFactor = rnd.GetScalar(); var Ma = amount * Generators.G + blindingFactor * Generators.Gh; // The coordinator generates a MAC and a proof that the MAC was generated using the // coordinator's secret key. The coordinator sends the pair (MAC + proofOfMac) back // to the client. var t = rnd.GetScalar(); var mac = MAC.ComputeMAC(coordinatorKey, Ma, t); var coordinatorStatement = ProofSystem.CreateStatement(coordinatorParameters, mac.V, Ma, t); var proverBuilder = ProofSystem.CreateProver(coordinatorStatement, coordinatorKey); var macProver = proverBuilder(rnd); var proofOfMac = macProver(); // The client receives the MAC and the proofOfMac which let the client know that the MAC // was generated with the coordinator's secret key. var clientStatement = ProofSystem.CreateStatement(coordinatorParameters, mac.V, Ma, mac.T); var verifierBuilder = ProofSystem.CreateVerifier(clientStatement); var macVerifier = verifierBuilder(proofOfMac); var isValidProof = macVerifier(); Assert.True(isValidProof); }
public void CanProveAndVerifyBalance(int presentedAmount, int requestedAmount) { var rnd = new SecureRandom(); var a = new Scalar((uint)presentedAmount); var r = rnd.GetScalar(); var z = rnd.GetScalar(); var Ca = z * Generators.Ga + a * Generators.Gg + r * Generators.Gh; var ap = new Scalar((uint)requestedAmount); var rp = rnd.GetScalar(); var Ma = ap * Generators.Gg + rp * Generators.Gh; var delta = new Scalar((uint)Math.Abs(presentedAmount - requestedAmount)); delta = presentedAmount > requestedAmount?delta.Negate() : delta; var knowledge = ProofSystem.BalanceProof(z, r + rp.Negate()); var proofOfBalance = ProofSystem.Prove(knowledge, rnd); var statement = ProofSystem.BalanceProof(Ca + delta * Generators.Gg - Ma); Assert.True(ProofSystem.Verify(statement, proofOfBalance)); var badStatement = ProofSystem.BalanceProof(Ca + (delta + Scalar.One) * Generators.Gg - Ma); Assert.False(ProofSystem.Verify(badStatement, proofOfBalance)); }
public void CanProveAndVerifyZeroProofs() { var rnd = new SecureRandom(); var a0 = Scalar.Zero; var r0 = rnd.GetScalar(); var Ma0 = a0 * Generators.Gg + r0 * Generators.Gh; var a1 = Scalar.Zero; var r1 = rnd.GetScalar(); var Ma1 = a1 * Generators.Gg + r1 * Generators.Gh; var knowledge = new[] { ProofSystem.ZeroProof(Ma0, r0), ProofSystem.ZeroProof(Ma1, r1) }; var proofs = ProofSystem.Prove(new Transcript(new byte[0]), knowledge, rnd); var statements = new[] { ProofSystem.ZeroProofStmt(Ma0), ProofSystem.ZeroProofStmt(Ma1) }; Assert.True(ProofSystem.Verify(new Transcript(new byte[0]), statements, proofs)); }
public void EqualityTests() { using var rnd = new SecureRandom(); var right = (attribute : rnd.GetScalar() * Generators.G, sk : new CredentialIssuerSecretKey(rnd), t : rnd.GetScalar()); var wrong = (attribute : rnd.GetScalar() * Generators.G, sk : new CredentialIssuerSecretKey(rnd), t : rnd.GetScalar()); var cases = new[]
public void EqualityTests() { var rnd = new SecureRandom(); var right = (attribute : rnd.GetScalar() * Generators.G, sk : new CoordinatorSecretKey(rnd), t : rnd.GetScalar()); var wrong = (attribute : rnd.GetScalar() * Generators.G, sk : new CoordinatorSecretKey(rnd), t : rnd.GetScalar()); var cases = new[]
public void CanProduceAndVerifyMAC() { using var rnd = new SecureRandom(); var sk = new CredentialIssuerSecretKey(rnd); var attribute = rnd.GetScalar() * Generators.G; // any random point var t = rnd.GetScalar(); var mac = MAC.ComputeMAC(sk, attribute, t); Assert.True(mac.VerifyMAC(sk, attribute)); }
public void EqualityTests() { var rnd = new SecureRandom(); var sk = new CoordinatorSecretKey(rnd); var attribute = rnd.GetScalar() * Generators.G; // any random point var differentAttribute = rnd.GetScalar() * Generators.G; // any other random point var t = rnd.GetScalar(); var right = (attribute : rnd.GetScalar() * Generators.G, sk : new CoordinatorSecretKey(rnd), t : rnd.GetScalar()); var wrong = (attribute : rnd.GetScalar() * Generators.G, sk : new CoordinatorSecretKey(rnd), t : rnd.GetScalar()); var cases = new[]
public void CanProveAndVerifyMAC() { // The coordinator generates a composed private key called CoordinatorSecretKey // and derives from that the coordinator's public parameters called CoordinatorParameters. var rnd = new SecureRandom(); var coordinatorKey = new CoordinatorSecretKey(rnd); var coordinatorParameters = coordinatorKey.ComputeCoordinatorParameters(); // A blinded amount is known as an `attribute`. In this case the attribute Ma is the // value 10000 blinded with a random `blindingFactor`. This attribute is sent to // the coordinator. var amount = new Scalar(10_000); var r = rnd.GetScalar(); var Ma = amount * Generators.G + r * Generators.Gh; // The coordinator generates a MAC and a proof that the MAC was generated using the // coordinator's secret key. The coordinator sends the pair (MAC + proofOfMac) back // to the client. var t = rnd.GetScalar(); var mac = MAC.ComputeMAC(coordinatorKey, Ma, t); var coordinatorKnowledge = ProofSystem.IssuerParameters(mac, Ma, coordinatorKey); var proofOfMac = ProofSystem.Prove(coordinatorKnowledge, rnd); // The client receives the MAC and the proofOfMac which let the client know that the MAC // was generated with the coordinator's secret key. var clientStatement = ProofSystem.IssuerParameters(coordinatorParameters, mac, Ma); var isValidProof = ProofSystem.Verify(clientStatement, proofOfMac); Assert.True(isValidProof); var corruptedResponses = new ScalarVector(proofOfMac.Responses.Reverse()); var invalidProofOfMac = new Proof(proofOfMac.PublicNonces, corruptedResponses); isValidProof = ProofSystem.Verify(clientStatement, invalidProofOfMac); Assert.False(isValidProof); var corruptedPublicNonces = new GroupElementVector(proofOfMac.PublicNonces.Reverse()); invalidProofOfMac = new Proof(corruptedPublicNonces, proofOfMac.Responses); isValidProof = ProofSystem.Verify(clientStatement, invalidProofOfMac); Assert.False(isValidProof); }
public void SyntheticNoncesTest() { var protocol = Encoding.UTF8.GetBytes("test TranscriptRng collisions"); using var rnd = new SecureRandom(); var commitment1 = new[] { Generators.Gx0 }; var commitment2 = new[] { Generators.Gx1 }; var witness1 = new[] { rnd.GetScalar() }; var witness2 = new[] { rnd.GetScalar() }; var transcript1 = new Transcript(protocol); var transcript2 = new Transcript(protocol); var transcript3 = new Transcript(protocol); var transcript4 = new Transcript(protocol); transcript1.CommitPublicNonces(commitment1); transcript2.CommitPublicNonces(commitment2); transcript3.CommitPublicNonces(commitment2); transcript4.CommitPublicNonces(commitment2); var secretNonceProvider1 = transcript1.CreateSyntheticSecretNonceProvider(witness1, rnd); var secretNonceProvider2 = transcript2.CreateSyntheticSecretNonceProvider(witness1, rnd); var secretNonceProvider3 = transcript3.CreateSyntheticSecretNonceProvider(witness2, rnd); var secretNonceProvider4 = transcript4.CreateSyntheticSecretNonceProvider(witness2, rnd); var secretNonce1 = secretNonceProvider1.GetScalar(); var secretNonce2 = secretNonceProvider2.GetScalar(); var secretNonce3 = secretNonceProvider3.GetScalar(); var secretNonce4 = secretNonceProvider4.GetScalar(); Assert.NotEqual(secretNonce1, secretNonce2); Assert.NotEqual(secretNonce1, secretNonce3); Assert.NotEqual(secretNonce1, secretNonce4); Assert.NotEqual(secretNonce2, secretNonce3); Assert.NotEqual(secretNonce2, secretNonce4); Assert.NotEqual(secretNonce3, secretNonce4); }
public void SyntheticNoncesTest() { var protocol = Encoding.UTF8.GetBytes("test TranscriptRng collisions"); var rnd = new SecureRandom(); var commitment1 = new[] { Generators.Gx0 }; var commitment2 = new[] { Generators.Gx1 }; var witness1 = new[] { rnd.GetScalar() }; var witness2 = new[] { rnd.GetScalar() }; var transcript1 = new Transcript(protocol); var transcript2 = new Transcript(protocol); var transcript3 = new Transcript(protocol); var transcript4 = new Transcript(protocol); transcript1.CommitPublicNonces(commitment1); transcript2.CommitPublicNonces(commitment2); transcript3.CommitPublicNonces(commitment2); transcript4.CommitPublicNonces(commitment2); var publicNonceGenerator1 = transcript1.CreateSyntheticPublicNoncesProvider(witness1, rnd); var publicNonceGenerator2 = transcript2.CreateSyntheticPublicNoncesProvider(witness1, rnd); var publicNonceGenerator3 = transcript3.CreateSyntheticPublicNoncesProvider(witness2, rnd); var publicNonceGenerator4 = transcript4.CreateSyntheticPublicNoncesProvider(witness2, rnd); var publicNonce1 = publicNonceGenerator1().First(); var publicNonce2 = publicNonceGenerator2().First(); var publicNonce3 = publicNonceGenerator3().First(); var publicNonce4 = publicNonceGenerator4().First(); Assert.NotEqual(publicNonce1, publicNonce2); Assert.NotEqual(publicNonce1, publicNonce3); Assert.NotEqual(publicNonce1, publicNonce4); Assert.NotEqual(publicNonce2, publicNonce3); Assert.NotEqual(publicNonce2, publicNonce4); Assert.NotEqual(publicNonce3, publicNonce4); }
public void CanProveAndVerifyPresentedBalance() { var rnd = new SecureRandom(); var a = new Scalar(10_000u); var r = rnd.GetScalar(); var z = rnd.GetScalar(); var Ca = z * Generators.Ga + a * Generators.Gg + r * Generators.Gh; var knowledge = ProofSystem.BalanceProof(z, r); var proofOfBalance = ProofSystem.Prove(knowledge, rnd); var statement = ProofSystem.BalanceProof(Ca - a * Generators.Gg); Assert.True(ProofSystem.Verify(statement, proofOfBalance)); var badStatement = ProofSystem.BalanceProof(Ca + Generators.Gg - a * Generators.Gg); Assert.False(ProofSystem.Verify(badStatement, proofOfBalance)); badStatement = ProofSystem.BalanceProof(Ca); Assert.False(ProofSystem.Verify(badStatement, proofOfBalance)); }
public void CanProveAndVerifyMacShow() { var rnd = new SecureRandom(); var coordinatorKey = new CoordinatorSecretKey(rnd); var coordinatorParameters = coordinatorKey.ComputeCoordinatorParameters(); // A blinded amount is known as an `attribute`. In this case the attribute Ma is the // value 10000 blinded with a random `blindingFactor`. This attribute is sent to // the coordinator. var amount = new Scalar(10_000); var r = rnd.GetScalar(); var Ma = amount * Generators.Gg + r * Generators.Gh; // The coordinator generates a MAC and a proof that the MAC was generated using the // coordinator's secret key. The coordinator sends the pair (MAC, proofOfMac) back // to the client. var t = rnd.GetScalar(); var mac = MAC.ComputeMAC(coordinatorKey, Ma, t); // The client randomizes the commitments before presenting them to the coordinator proving to // the coordinator that a credential is valid (prover knows a valid MAC on non-randomized attribute) var credential = new Credential(amount, r, mac); var z = rnd.GetScalar(); var randomizedCredential = credential.Present(z); var knowledge = ProofSystem.ShowCredential(randomizedCredential, z, credential, coordinatorParameters); var proofOfMacShow = ProofSystem.Prove(knowledge, rnd); // The coordinator must verify the received randomized credential is valid. var Z = randomizedCredential.ComputeZ(coordinatorKey); Assert.Equal(Z, z * coordinatorParameters.I); var statement = ProofSystem.ShowCredential(randomizedCredential, Z, coordinatorParameters); var isValidProof = ProofSystem.Verify(statement, proofOfMacShow); Assert.True(isValidProof); }
public void CanDetectInvalidMAC() { using var rnd = new SecureRandom(); var sk = new CredentialIssuerSecretKey(rnd); var attribute = rnd.GetScalar() * Generators.G; // any random point var differentAttribute = rnd.GetScalar() * Generators.G; // any other random point var t = rnd.GetScalar(); // Create MAC for realAttribute and verify with fake/wrong attribute var mac = MAC.ComputeMAC(sk, attribute, t); Assert.False(mac.VerifyMAC(sk, differentAttribute)); var differentT = rnd.GetScalar(); var differentMac = MAC.ComputeMAC(sk, attribute, differentT); Assert.NotEqual(mac, differentMac); mac = MAC.ComputeMAC(sk, attribute, differentT); var differentSk = new CredentialIssuerSecretKey(rnd); Assert.False(mac.VerifyMAC(differentSk, attribute)); }
public void CanProveAndVerifyRequestedBalance() { var rnd = new SecureRandom(); var a = new Scalar(10_000u); var r = rnd.GetScalar(); var Ma = a * Generators.Gg + r * Generators.Gh; var knowledge = ProofSystem.BalanceProof(Scalar.Zero, r.Negate()); var proofOfBalance = ProofSystem.Prove(knowledge, rnd); var statement = ProofSystem.BalanceProof(a * Generators.Gg - Ma); Assert.True(ProofSystem.Verify(statement, proofOfBalance)); var badStatement = ProofSystem.BalanceProof(Ma); Assert.False(ProofSystem.Verify(badStatement, proofOfBalance)); }
public void CanProveAndVerifyCommitmentRange(ulong amount, int width, bool pass) { var rnd = new SecureRandom(); var amountScalar = new Scalar(amount); var randomness = rnd.GetScalar(); var commitment = amountScalar * Generators.Gg + randomness * Generators.Gh; var maskedScalar = new Scalar(amount & ((1ul << width) - 1)); var(knowledge, bitCommitments) = ProofSystem.RangeProof(maskedScalar, randomness, width, rnd); var rangeProof = ProofSystem.Prove(knowledge, rnd); Assert.Equal(pass, ProofSystem.Verify(ProofSystem.RangeProof(commitment, bitCommitments), rangeProof)); if (!pass) { Assert.Throws <ArgumentOutOfRangeException>(() => ProofSystem.RangeProof(amountScalar, randomness, width, rnd)); } }
public void CanProveAndVerifyCommitmentRange(ulong amount, int width, bool pass) { using var rnd = new SecureRandom(); var amountScalar = new Scalar(amount); var randomness = rnd.GetScalar(); var commitment = amountScalar * Generators.Gg + randomness * Generators.Gh; // First, generate a proof for the given statement. This proof may // be invalid (verification equation fails to hold) if the statement // is in fact wrong, in which case the verifier should reject. var(knowledge, bitCommitments) = ProofSystem.RangeProofKnowledge(amountScalar, randomness, width, rnd); var rangeProof = ProofSystemHelpers.Prove(knowledge, rnd); Assert.Equal(pass, ProofSystemHelpers.Verify(ProofSystem.RangeProofStatement(commitment, bitCommitments, width), rangeProof)); if (!pass) { Assert.Throws <ArgumentException>(() => knowledge.AssertSoundness()); // When the statement is unprovable, modify the secret input by // clearing the high bits to make sure that the proof is always // formally valid, but when the original statement is false this // will be a valid proof of a different statement. The verifier // should still reject. var maskedScalar = new Scalar(amount & ((1ul << width) - 1)); var(knowledgeOfSomethingElse, incompleteBitCommitments) = ProofSystem.RangeProofKnowledge(maskedScalar, randomness, width, rnd); var incorrectRangeProof = ProofSystemHelpers.Prove(knowledgeOfSomethingElse, rnd); Assert.False(ProofSystemHelpers.Verify(ProofSystem.RangeProofStatement(commitment, incompleteBitCommitments, width), incorrectRangeProof)); // For completeness, make sure other corrupted statements are also rejected Assert.False(ProofSystemHelpers.Verify(ProofSystem.RangeProofStatement(commitment, bitCommitments, width), incorrectRangeProof)); Assert.False(ProofSystemHelpers.Verify(ProofSystem.RangeProofStatement(commitment, incompleteBitCommitments, width), rangeProof)); } }