├── README.md
├── .gitignore
├── src
├── main
│ ├── java
│ │ └── edu
│ │ │ └── stanford
│ │ │ └── crypto
│ │ │ ├── proof
│ │ │ ├── Proof.java
│ │ │ ├── ProofData.java
│ │ │ ├── MemoryProof.java
│ │ │ ├── ProofSystem.java
│ │ │ ├── assets
│ │ │ │ ├── AssetProofData.java
│ │ │ │ ├── AddressProofEntry.java
│ │ │ │ ├── AddressProofData.java
│ │ │ │ ├── AddressProofSystem.java
│ │ │ │ ├── AssetProof.java
│ │ │ │ ├── AssetProofSystem.java
│ │ │ │ └── AddressProof.java
│ │ │ ├── RangeProof.java
│ │ │ ├── balance
│ │ │ │ ├── BalanceProofData.java
│ │ │ │ ├── CustomerInfo.java
│ │ │ │ ├── CustomerSecrets.java
│ │ │ │ ├── BalanceProof.java
│ │ │ │ └── BalanceProofSystem.java
│ │ │ ├── binary
│ │ │ │ ├── BinaryProofData.java
│ │ │ │ ├── BinaryRangeProof.java
│ │ │ │ ├── BinaryProofSystem.java
│ │ │ │ └── BinaryProof.java
│ │ │ ├── RangeProofData.java
│ │ │ └── rangeproof
│ │ │ │ └── BinaryRangeProofSystem.java
│ │ │ ├── verification
│ │ │ ├── VerificationData.java
│ │ │ ├── BalanceVerificationData.java
│ │ │ ├── GeneratorData.java
│ │ │ ├── Verifier.java
│ │ │ ├── RangeProofVerificationData.java
│ │ │ ├── BinaryRangeProofVerifier.java
│ │ │ ├── ParticipationData.java
│ │ │ ├── ParticipationVerifier.java
│ │ │ ├── AddressVerificationData.java
│ │ │ ├── BinaryProofVerifier.java
│ │ │ ├── AddressProofVerifier.java
│ │ │ ├── BalanceVerifier.java
│ │ │ └── AssetsVerifier.java
│ │ │ ├── SQLDatabase.java
│ │ │ ├── bitcoin
│ │ │ ├── CustomerSecretsDatabase.java
│ │ │ ├── PrivateKeyDatabase.java
│ │ │ ├── Blockchain.java
│ │ │ ├── CustomerDatabase.java
│ │ │ ├── BlockchainEntry.java
│ │ │ ├── SQLPrivateKeyDatabase.java
│ │ │ ├── SQLCustomerSecretsDatabase.java
│ │ │ ├── SQLBlockchain.java
│ │ │ └── SQLCustomerDatabase.java
│ │ │ ├── BlockingExecutor.java
│ │ │ ├── ProofUtils.java
│ │ │ ├── ECConstants.java
│ │ │ ├── experiments
│ │ │ ├── AssetProofExperiment.java
│ │ │ └── BalanceProofExperiment.java
│ │ │ ├── ExperimentUtils.java
│ │ │ └── database
│ │ │ └── Database.java
│ └── resources
│ │ └── log4j.properties
└── test
│ └── java
│ └── edu
│ └── stanford
│ └── crypto
│ ├── PlayGround.java
│ └── proof
│ └── assets
│ ├── AddressProofTest.java
│ └── RangeProofTest.java
├── LICENSE.md
└── pom.xml
/README.md:
--------------------------------------------------------------------------------
1 | # provisions
2 | Provisions: Privacy-preserving proofs of solvency for Bitcoin
3 | https://eprint.iacr.org/2015/1008.pdf
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .classpath
2 | .project
3 | dependency-reduced-pom.xml
4 | target/
5 | .settings/*
6 | *.swp
7 | *.json
8 | *.key
9 | *.proof
10 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/Proof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof;
5 |
6 | public interface Proof {
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/ProofData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof;
5 |
6 | public interface ProofData
{
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/MemoryProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof;
5 |
6 | public interface MemoryProof
7 | extends Proof {
8 | byte[] serialize();
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/ProofSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof;
5 |
6 | public interface ProofSystem
> {
7 | P createProof(T var1);
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger = DEBUG, CONSOLE
2 |
3 |
4 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
5 | log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.CONSOLE.layout.conversionPattern=%r [%t] %p %c %x - %m%n
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/VerificationData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.proof.Proof;
7 |
8 | interface VerificationData
{
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AssetProofData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.proof.ProofData;
7 |
8 | public class AssetProofData implements ProofData {
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/SQLDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto;
5 |
6 | import java.sql.SQLException;
7 |
8 | public interface SQLDatabase
9 | extends AutoCloseable {
10 | @Override
11 | void close() throws SQLException;
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/RangeProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof;
5 |
6 | import org.bouncycastle.math.ec.ECPoint;
7 |
8 | import java.math.BigInteger;
9 |
10 | public interface RangeProof
11 | extends MemoryProof {
12 | BigInteger getRange();
13 |
14 | ECPoint getStatement();
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/test/java/edu/stanford/crypto/PlayGround.java:
--------------------------------------------------------------------------------
1 | package edu.stanford.crypto;
2 |
3 | import org.junit.Test;
4 |
5 | import java.io.IOException;
6 | import java.security.NoSuchAlgorithmException;
7 |
8 | /**
9 | * Unit test for simple App.
10 | */
11 | public class PlayGround {
12 |
13 | @Test
14 | public void playGround2() throws IOException, NoSuchAlgorithmException {
15 |
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/CustomerSecretsDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import edu.stanford.crypto.proof.balance.CustomerSecrets;
7 |
8 | import java.math.BigInteger;
9 |
10 | public interface CustomerSecretsDatabase {
11 | void store(String var1, BigInteger var2, BigInteger var3);
12 |
13 | CustomerSecrets retrieve(String var1);
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/PrivateKeyDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import org.bouncycastle.math.ec.ECPoint;
7 |
8 | import java.math.BigInteger;
9 | import java.util.Optional;
10 |
11 | public interface PrivateKeyDatabase {
12 | void store(ECPoint var1, BigInteger var2);
13 |
14 | Optional retrievePrivateKey(ECPoint var1);
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/Blockchain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import org.bouncycastle.math.ec.ECPoint;
7 |
8 | import java.math.BigInteger;
9 | import java.util.Iterator;
10 |
11 | interface Blockchain {
12 | BigInteger getBalance(ECPoint var1);
13 |
14 | void addEntry(ECPoint var1, BigInteger var2);
15 |
16 | Iterator getBlockchainEntries();
17 |
18 | void truncate();
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/balance/BalanceProofData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.balance;
5 |
6 | import edu.stanford.crypto.proof.ProofData;
7 |
8 | public class BalanceProofData
9 | implements ProofData {
10 | private final int maxBits;
11 |
12 | public BalanceProofData(int maxBits) {
13 | this.maxBits = maxBits;
14 | }
15 |
16 | public int getMaxBits() {
17 | return this.maxBits;
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/CustomerDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import edu.stanford.crypto.proof.balance.CustomerInfo;
7 |
8 | import java.math.BigInteger;
9 | import java.util.Iterator;
10 |
11 | interface CustomerDatabase
12 | extends AutoCloseable {
13 | BigInteger getBalance(String var1);
14 |
15 | void addBalance(String var1, BigInteger var2);
16 |
17 | Iterator getCustomers();
18 |
19 | void truncate();
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/BalanceVerificationData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.proof.balance.BalanceProof;
7 |
8 | public class BalanceVerificationData
9 | implements VerificationData {
10 | private final int maxBits;
11 |
12 | public BalanceVerificationData(int maxBits) {
13 | this.maxBits = maxBits;
14 | }
15 |
16 | public int getMaxBits() {
17 | return this.maxBits;
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/balance/CustomerInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.balance;
5 |
6 | import java.math.BigInteger;
7 |
8 | public class CustomerInfo {
9 | private final String id;
10 | private final BigInteger balance;
11 |
12 | public CustomerInfo(String id, BigInteger balance) {
13 | this.id = id;
14 | this.balance = balance;
15 | }
16 |
17 | public String getId() {
18 | return this.id;
19 | }
20 |
21 | public BigInteger getBalance() {
22 | return this.balance;
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/BlockingExecutor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto;
5 |
6 | import java.util.concurrent.ArrayBlockingQueue;
7 | import java.util.concurrent.ThreadPoolExecutor;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | public class BlockingExecutor
11 | extends ThreadPoolExecutor {
12 | public BlockingExecutor() {
13 | super(Runtime.getRuntime().availableProcessors() - 1, Runtime.getRuntime().availableProcessors() - 1, 2, TimeUnit.DAYS, new ArrayBlockingQueue(Runtime.getRuntime().availableProcessors() * 4), new CallerRunsPolicy());
14 | }
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/BlockchainEntry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import org.bouncycastle.math.ec.ECPoint;
7 |
8 | import java.math.BigInteger;
9 |
10 | public class BlockchainEntry {
11 | private final ECPoint pubKey;
12 | private final BigInteger balance;
13 |
14 | public BlockchainEntry(ECPoint pubKey, BigInteger balance) {
15 | this.pubKey = pubKey;
16 | this.balance = balance;
17 | }
18 |
19 | public ECPoint getPubKey() {
20 | return this.pubKey;
21 | }
22 |
23 | public BigInteger getBalance() {
24 | return this.balance;
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/balance/CustomerSecrets.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.balance;
5 |
6 | import java.math.BigInteger;
7 |
8 | public class CustomerSecrets {
9 | private final BigInteger hashSalt;
10 | private final BigInteger combinedRandomness;
11 |
12 | public CustomerSecrets(BigInteger hashSalt, BigInteger combinedRandomness) {
13 | this.hashSalt = hashSalt;
14 | this.combinedRandomness = combinedRandomness;
15 | }
16 |
17 | public BigInteger getHashSalt() {
18 | return this.hashSalt;
19 | }
20 |
21 | public BigInteger getCombinedRandomness() {
22 | return this.combinedRandomness;
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AddressProofEntry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.proof.binary.BinaryProof;
7 | import org.bouncycastle.math.ec.ECPoint;
8 |
9 | public class AddressProofEntry {
10 | private final ECPoint publicKey;
11 | private final AddressProof addressProof;
12 |
13 | public AddressProofEntry(ECPoint publicKey, AddressProof addressProof) {
14 | this.publicKey = publicKey;
15 | this.addressProof = addressProof;
16 | }
17 |
18 | public ECPoint getPublicKey() {
19 | return this.publicKey;
20 | }
21 |
22 | public AddressProof getAddressProof() {
23 | return this.addressProof;
24 | }
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/GeneratorData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.Proof;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | public class GeneratorData
11 | implements VerificationData
{
12 | private final ECPoint g;
13 | private final ECPoint h;
14 |
15 | public GeneratorData() {
16 | this(ECConstants.G, ECConstants.H);
17 | }
18 |
19 | private GeneratorData(ECPoint g, ECPoint h) {
20 | this.g = g;
21 | this.h = h;
22 | }
23 |
24 | public ECPoint getG() {
25 | return this.g;
26 | }
27 |
28 | public ECPoint getH() {
29 | return this.h;
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/Verifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.Proof;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | import java.math.BigInteger;
11 |
12 | interface Verifier
> {
13 | void verify(P var1, T var2);
14 |
15 | default void holds(ECPoint a, ECPoint b) {
16 | if (!a.equals(b)) {
17 | throw new AssertionError((Object)(a.normalize() + " should be equal to " + b.normalize()));
18 | }
19 | }
20 |
21 | default void holds(BigInteger a, BigInteger b) {
22 | if (!a.mod(ECConstants.Q).equals(b.mod(ECConstants.Q))) {
23 | throw new AssertionError((Object)(a + " should be equal to " + b));
24 | }
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/RangeProofVerificationData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.proof.binary.BinaryProof;
7 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
8 |
9 | import java.math.BigInteger;
10 |
11 | public class RangeProofVerificationData implements VerificationData {
12 | private final GeneratorData generatorData;
13 | private final BigInteger maxRange;
14 |
15 | public RangeProofVerificationData(GeneratorData generatorData, BigInteger maxRange) {
16 | this.generatorData = generatorData;
17 | this.maxRange = maxRange;
18 | }
19 |
20 | public GeneratorData getGeneratorData() {
21 | return this.generatorData;
22 | }
23 |
24 | public BigInteger getMaxRange() {
25 | return this.maxRange;
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/BinaryRangeProofVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.proof.binary.BinaryProof;
7 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
8 |
9 | import java.util.List;
10 |
11 | public class BinaryRangeProofVerifier
12 | implements Verifier {
13 | private final BinaryProofVerifier binaryProofVerifier = new BinaryProofVerifier();
14 |
15 | @Override
16 | public void verify(BinaryRangeProof proof, RangeProofVerificationData data) {
17 | if (data.getMaxRange().compareTo(proof.getRange()) > 0) {
18 | throw new AssertionError("Range is to small " + data.getMaxRange() + " should be less than " + proof.getRange());
19 | }
20 | GeneratorData generatorData = data.getGeneratorData();
21 | proof.getBitProofs().forEach(bp -> binaryProofVerifier.verify(bp, generatorData));
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/ParticipationData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.proof.balance.BalanceProof;
7 | import edu.stanford.crypto.proof.balance.CustomerSecrets;
8 |
9 | import java.math.BigInteger;
10 |
11 | public class ParticipationData
12 | implements VerificationData {
13 | private final String customerId;
14 | private final CustomerSecrets secrets;
15 | private final BigInteger balance;
16 |
17 | public ParticipationData(String customerId, CustomerSecrets secrets, BigInteger balance) {
18 | this.customerId = customerId;
19 | this.secrets = secrets;
20 | this.balance = balance;
21 | }
22 |
23 | public String getCustomerId() {
24 | return this.customerId;
25 | }
26 |
27 | public CustomerSecrets getSecrets() {
28 | return this.secrets;
29 | }
30 |
31 | public BigInteger getBalance() {
32 | return this.balance;
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/ParticipationVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.ProofUtils;
8 | import edu.stanford.crypto.proof.balance.BalanceProof;
9 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
10 | import org.bouncycastle.math.ec.ECPoint;
11 |
12 | import java.math.BigInteger;
13 |
14 | public class ParticipationVerifier
15 | implements Verifier {
16 | @Override
17 | public void verify(BalanceProof proof, ParticipationData data) {
18 | BigInteger hashedId = ProofUtils.hash(data.getCustomerId(), data.getSecrets().getHashSalt());
19 | BinaryRangeProof customerProof = proof.getCustomerProof(hashedId);
20 | ECPoint assumedStatement = ECConstants.H.multiply(data.getSecrets().getCombinedRandomness()).add(ECConstants.G.multiply(data.getBalance()));
21 | this.holds(assumedStatement, customerProof.getStatement());
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/binary/BinaryProofData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.binary;
5 |
6 | import edu.stanford.crypto.proof.ProofData;
7 | import org.bouncycastle.math.ec.ECPoint;
8 |
9 | import java.math.BigInteger;
10 |
11 | public class BinaryProofData
12 | implements ProofData {
13 | private final boolean secret;
14 | private final ECPoint g;
15 | private final ECPoint h;
16 | private final BigInteger randomness;
17 |
18 | public BinaryProofData(boolean secret, ECPoint g, ECPoint h, BigInteger randomness) {
19 | this.secret = secret;
20 | this.g = g;
21 | this.h = h;
22 | this.randomness = randomness;
23 | }
24 |
25 | public boolean getSecret() {
26 | return this.secret;
27 | }
28 |
29 | public ECPoint getG() {
30 | return this.g;
31 | }
32 |
33 | public ECPoint getH() {
34 | return this.h;
35 | }
36 |
37 | public BigInteger getRandomness() {
38 | return this.randomness;
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/AddressVerificationData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.proof.assets.AddressProof;
7 | import org.bouncycastle.math.ec.ECPoint;
8 |
9 | import java.math.BigInteger;
10 |
11 | public class AddressVerificationData
12 | implements VerificationData {
13 | private final ECPoint publicKey;
14 | private final BigInteger balance;
15 | private final ECPoint g;
16 | private final ECPoint h;
17 |
18 | public AddressVerificationData(ECPoint publicKey, BigInteger balance, ECPoint g, ECPoint h) {
19 | this.publicKey = publicKey;
20 | this.balance = balance;
21 | this.g = g;
22 | this.h = h;
23 | }
24 |
25 | public ECPoint getPublicKey() {
26 | return this.publicKey;
27 | }
28 |
29 | public BigInteger getBalance() {
30 | return this.balance;
31 | }
32 |
33 | public ECPoint getG() {
34 | return this.g;
35 | }
36 |
37 | public ECPoint getH() {
38 | return this.h;
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
4 |
5 | Gaby G. Dagher,
6 | Benedikt Bunz,
7 | Joseph Bonneau,
8 | Jeremy Clark,
9 | Dan Boneh.
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy
12 | of this software and associated documentation files (the "Software"), to deal
13 | in the Software without restriction, including without limitation the rights
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | copies of the Software, and to permit persons to whom the Software is
16 | furnished to do so, subject to the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be included in all
19 | copies or substantial portions of the Software.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | SOFTWARE.
28 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/RangeProofData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
8 |
9 | import java.math.BigInteger;
10 | import java.util.List;
11 | import java.util.stream.IntStream;
12 |
13 | public class RangeProofData
14 | implements ProofData {
15 | private final BigInteger secret;
16 | private final List randomnes;
17 |
18 | public RangeProofData(BigInteger secret, List randomnes) {
19 | if (secret.bitLength() > randomnes.size()) {
20 | throw new IllegalArgumentException("What are you trying to have me proof here?");
21 | }
22 | this.secret = secret;
23 | this.randomnes = randomnes;
24 | }
25 |
26 | public BigInteger getSecret() {
27 | return this.secret;
28 | }
29 |
30 | public List getRandomnes() {
31 | return this.randomnes;
32 | }
33 |
34 | public BigInteger getTotalRandomness() {
35 | return IntStream.range(0, this.randomnes.size()).mapToObj(i -> this.randomnes.get(i).shiftLeft(i)).reduce(BigInteger.ZERO, BigInteger::add).mod(ECConstants.Q);
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/BinaryProofVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.ProofUtils;
8 | import edu.stanford.crypto.proof.binary.BinaryProof;
9 | import org.bouncycastle.math.ec.ECPoint;
10 |
11 | import java.math.BigInteger;
12 |
13 | public class BinaryProofVerifier
14 | implements Verifier> {
15 | @Override
16 | public void verify(BinaryProof proof, GeneratorData data) {
17 | ECPoint zeroClaim = proof.getStatement().multiply(proof.getChallengeZero());
18 | ECPoint a0 = data.getH().multiply(proof.getResponseZero()).subtract(zeroClaim);
19 | ECPoint oneClaim = proof.getStatement().subtract(data.getG()).multiply(proof.getChallengeOne());
20 | ECPoint a1 = data.getH().multiply(proof.getResponseOne()).subtract(oneClaim);
21 | BigInteger computedChallenge = ProofUtils.computeChallenge(data.getG(), data.getH(), proof.getStatement(), a0, a1);
22 | BigInteger transmittedChallenge = proof.getChallengeZero().add(proof.getChallengeOne()).mod(ECConstants.CHALLENGE_Q);
23 | this.holds(transmittedChallenge, computedChallenge);
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/rangeproof/BinaryRangeProofSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.rangeproof;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.ProofSystem;
8 | import edu.stanford.crypto.proof.RangeProofData;
9 | import edu.stanford.crypto.proof.binary.BinaryProof;
10 | import edu.stanford.crypto.proof.binary.BinaryProofData;
11 | import edu.stanford.crypto.proof.binary.BinaryProofSystem;
12 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
13 |
14 | import java.math.BigInteger;
15 | import java.util.ArrayList;
16 |
17 | public class BinaryRangeProofSystem
18 | implements ProofSystem {
19 | private final BinaryProofSystem bitsProver = new BinaryProofSystem();
20 |
21 | @Override
22 | public BinaryRangeProof createProof(RangeProofData data) {
23 | BigInteger secret = data.getSecret();
24 | ArrayList binaryProofList = new ArrayList<>(data.getRandomnes().size());
25 | for (int i = 0; i < data.getRandomnes().size(); ++i) {
26 | BinaryProofData binaryProofData = new BinaryProofData(secret.testBit(i), ECConstants.G, ECConstants.H, data.getRandomnes().get(i));
27 | binaryProofList.add(this.bitsProver.createProof(binaryProofData));
28 | }
29 | return new BinaryRangeProof(binaryProofList);
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/test/java/edu/stanford/crypto/proof/assets/AddressProofTest.java:
--------------------------------------------------------------------------------
1 | package edu.stanford.crypto.proof.assets;
2 |
3 | import edu.stanford.crypto.ECConstants;
4 | import edu.stanford.crypto.verification.AddressProofVerifier;
5 | import edu.stanford.crypto.verification.AddressVerificationData;
6 | import org.bouncycastle.math.ec.ECPoint;
7 | import org.junit.Test;
8 |
9 | import java.math.BigInteger;
10 | import java.security.SecureRandom;
11 | import java.util.Random;
12 |
13 | /**
14 | * Created by buenz on 06.01.16.
15 | */
16 | public class AddressProofTest {
17 | @Test
18 | public void testAddressProofWithKey() {
19 | AddressProofSystem system = new AddressProofSystem();
20 | Random rng = new SecureRandom();
21 |
22 | BigInteger privateKey = new BigInteger(256, rng);
23 | ECPoint pubKey = ECConstants.G.multiply(privateKey);
24 | BigInteger balance = BigInteger.TEN;
25 | BigInteger balanceRandomness = new BigInteger(256, rng);
26 | BigInteger knownKeyRandomness = new BigInteger(256, rng);
27 |
28 | AddressProofData data = new AddressProofData(privateKey, pubKey, balance, balanceRandomness, knownKeyRandomness, ECConstants.G, ECConstants.H);
29 | AddressProof proof = system.createProof(data);
30 | AddressProofVerifier verifier = new AddressProofVerifier();
31 | AddressVerificationData verificaitonData = new AddressVerificationData(pubKey, balance, ECConstants.G, ECConstants.H);
32 | verifier.verify(proof, verificaitonData);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/ProofUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto;
5 |
6 | import org.bouncycastle.math.ec.ECPoint;
7 |
8 | import java.math.BigInteger;
9 | import java.security.MessageDigest;
10 | import java.security.NoSuchAlgorithmException;
11 | import java.security.SecureRandom;
12 |
13 | public class ProofUtils {
14 | private static final ThreadLocal SHA256;
15 | private static final SecureRandom RNG;
16 |
17 | public static BigInteger computeChallenge(ECPoint ... points) {
18 | for (ECPoint point : points) {
19 | SHA256.get().update(point.getEncoded(false));
20 | }
21 | byte[] hash = SHA256.get().digest();
22 | return new BigInteger(hash).mod(ECConstants.CHALLENGE_Q);
23 | }
24 |
25 | public static BigInteger hash(String id, BigInteger salt) {
26 | SHA256.get().update(id.getBytes());
27 | SHA256.get().update(salt.toByteArray());
28 | return new BigInteger(SHA256.get().digest());
29 | }
30 |
31 | public static BigInteger randomNumber(int bits) {
32 | return new BigInteger(bits, RNG);
33 | }
34 |
35 | public static BigInteger randomNumber() {
36 | return ProofUtils.randomNumber(256);
37 | }
38 |
39 | static {
40 | RNG = new SecureRandom();
41 | SHA256 = ThreadLocal.withInitial(() -> {
42 | try {
43 | return MessageDigest.getInstance("SHA-256");
44 | }
45 | catch (NoSuchAlgorithmException e) {
46 | e.printStackTrace();
47 | throw new IllegalStateException(e);
48 | }
49 | }
50 | );
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/AddressProofVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.ProofUtils;
7 | import edu.stanford.crypto.proof.assets.AddressProof;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | import java.math.BigInteger;
11 |
12 | public class AddressProofVerifier
13 | implements Verifier {
14 | @Override
15 | public void verify(AddressProof proof, AddressVerificationData data) {
16 | ECPoint g = data.getG();
17 | ECPoint h = data.getH();
18 | ECPoint b = g.multiply(data.getBalance());
19 | BigInteger transmittedChallenge = proof.getChallengeZero().add(proof.getChallengeOne());
20 | ECPoint balanceClaim = proof.getCommitmentBalance().multiply(transmittedChallenge);
21 | ECPoint a1 = h.multiply(proof.getResponseV()).add(b.multiply(proof.getResponseS())).subtract(balanceClaim);
22 | ECPoint xHatClaim = proof.getCommitmentXHat().multiply(transmittedChallenge);
23 | ECPoint a2 = data.getPublicKey().multiply(proof.getResponseS()).add(h.multiply(proof.getResponseT())).subtract(xHatClaim);
24 | ECPoint a3 = g.multiply(proof.getResponseXHat()).add(h.multiply(proof.getResponseT())).subtract(xHatClaim);
25 | ECPoint zeroClaim = proof.getCommitmentBalance().multiply(proof.getChallengeZero());
26 | ECPoint oneClaim = proof.getCommitmentBalance().subtract(b).multiply(proof.getChallengeOne());
27 |
28 | ECPoint aZero = h.multiply(proof.getResponseZero()).subtract(zeroClaim);
29 | ECPoint aOne = h.multiply(proof.getResponseOne()).subtract(oneClaim);
30 |
31 | BigInteger computedChallenge = ProofUtils.computeChallenge(g, h, data.getPublicKey(), b, proof.getCommitmentBalance(), proof.getCommitmentXHat(), a1, a2, a3, aZero, aOne);
32 | this.holds(transmittedChallenge, computedChallenge);
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/ECConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto;
5 |
6 | import org.bouncycastle.crypto.ec.CustomNamedCurves;
7 | import org.bouncycastle.math.ec.ECCurve;
8 | import org.bouncycastle.math.ec.ECFieldElement;
9 | import org.bouncycastle.math.ec.ECPoint;
10 | import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve;
11 | import org.bouncycastle.math.ec.custom.sec.SecP256K1FieldElement;
12 |
13 | import java.math.BigInteger;
14 | import java.security.MessageDigest;
15 | import java.security.NoSuchAlgorithmException;
16 |
17 | public final class ECConstants {
18 | static {
19 | SecP256K1Curve curve = new SecP256K1Curve();
20 | BigInteger hash = BigInteger.ZERO;
21 | try {
22 | MessageDigest sha256 = sha256 = MessageDigest.getInstance("SHA-256");
23 | sha256.update("PROVISIONS".getBytes());
24 | hash = new BigInteger(sha256.digest());
25 |
26 | } catch (NoSuchAlgorithmException e) {
27 | e.printStackTrace();
28 | }
29 | ECFieldElement x = new SecP256K1FieldElement(hash.mod(curve.getQ()));
30 | ECFieldElement rhs = x.square().multiply(x.add(curve.getA())).add(curve.getB());
31 | ECFieldElement y = rhs.sqrt();
32 |
33 |
34 | H = curve.validatePoint(x.toBigInteger(), y.toBigInteger());
35 |
36 |
37 | }
38 |
39 | public static final ECCurve BITCOIN_CURVE = new SecP256K1Curve();
40 | public static final ECPoint INFINITY = BITCOIN_CURVE.getInfinity();
41 | public static final int STANDARD_SECURITY = 256;
42 | public static final int CHALLENGE_LENGTH = 256;
43 | public static final ECPoint G = CustomNamedCurves.getByName("secp256k1").getG();
44 | public static final ECPoint H;
45 | public static final BigInteger Q = BITCOIN_CURVE.getOrder();
46 | public static final BigInteger CHALLENGE_Q = Q.min(BigInteger.ONE.shiftLeft(256));
47 |
48 | private ECConstants() {
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/BalanceVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.BlockingExecutor;
7 | import edu.stanford.crypto.ECConstants;
8 | import edu.stanford.crypto.proof.balance.BalanceProof;
9 | import edu.stanford.crypto.proof.binary.BinaryProof;
10 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
11 | import org.bouncycastle.math.ec.ECPoint;
12 |
13 | import java.math.BigInteger;
14 | import java.util.Iterator;
15 | import java.util.concurrent.TimeUnit;
16 | import java.util.concurrent.atomic.AtomicReference;
17 |
18 | public class BalanceVerifier
19 | implements Verifier {
20 | private final BinaryRangeProofVerifier verifier = new BinaryRangeProofVerifier();
21 |
22 | @Override
23 | public void verify(BalanceProof proof, BalanceVerificationData data) {
24 | Iterator rangeProofs = proof.getRangeProofs();
25 | RangeProofVerificationData verificationData = new RangeProofVerificationData(new GeneratorData<>(), BigInteger.ONE.shiftLeft(data.getMaxBits()).subtract(BigInteger.ONE));
26 | AtomicReference totalEncryption = new AtomicReference<>(ECConstants.INFINITY);
27 | BlockingExecutor pool = new BlockingExecutor();
28 | while (rangeProofs.hasNext()) {
29 | BinaryRangeProof rangeProof = rangeProofs.next();
30 | Runnable thread = () -> {
31 | this.verifier.verify(rangeProof, verificationData);
32 | totalEncryption.accumulateAndGet(rangeProof.getStatement(), ECPoint::add);
33 | };
34 | pool.submit(thread);
35 | }
36 | try {
37 | pool.shutdown();
38 | pool.awaitTermination(2, TimeUnit.DAYS);
39 | System.out.println(totalEncryption.get());
40 | }
41 | catch (InterruptedException e) {
42 | e.printStackTrace();
43 | throw new AssertionError(e);
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/binary/BinaryRangeProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.binary;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.RangeProof;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | import java.math.BigInteger;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import java.util.stream.Collectors;
14 |
15 | public class BinaryRangeProof
16 | implements RangeProof {
17 | private final List binaryProofList;
18 |
19 | @Override
20 | public byte[] serialize() {
21 | List bitSerializations = this.binaryProofList.stream().map(BinaryProof::serialize).collect(Collectors.toList());
22 | byte[] serialization = new byte[bitSerializations.stream().mapToInt(arr -> arr.length).sum()];
23 | int index = 0;
24 | for (byte[] arr2 : bitSerializations) {
25 | System.arraycopy(arr2, 0, serialization, index, arr2.length);
26 | index += arr2.length;
27 | }
28 | return serialization;
29 | }
30 |
31 | public BinaryRangeProof(List binaryProofList) {
32 | this.binaryProofList = binaryProofList;
33 | }
34 |
35 | public BinaryRangeProof(byte[] serialization) {
36 | int[] index = new int[]{0};
37 | ArrayList bits = new ArrayList<>();
38 | while (index[0] < serialization.length) {
39 | bits.add(new BinaryProof(serialization, index));
40 | }
41 | this.binaryProofList = bits;
42 | }
43 |
44 | @Override
45 | public BigInteger getRange() {
46 | return BigInteger.ONE.shiftLeft(this.binaryProofList.size()).subtract(BigInteger.ONE);
47 | }
48 |
49 | public List getBitProofs() {
50 | return this.binaryProofList;
51 | }
52 |
53 | @Override
54 | public ECPoint getStatement() {
55 | ECPoint statement = ECConstants.INFINITY;
56 | for (int i = 0; i < this.binaryProofList.size(); ++i) {
57 | statement = statement.add(this.binaryProofList.get(i).getStatement().timesPow2(i));
58 | }
59 | return statement;
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/binary/BinaryProofSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.binary;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.ProofUtils;
8 | import edu.stanford.crypto.proof.ProofSystem;
9 | import org.bouncycastle.math.ec.ECPoint;
10 |
11 | import java.math.BigInteger;
12 |
13 | public class BinaryProofSystem
14 | implements ProofSystem {
15 | @Override
16 | public BinaryProof createProof(BinaryProofData data) {
17 | BinaryProof proof;
18 | BigInteger falseChallenge = ProofUtils.randomNumber(256).mod(ECConstants.CHALLENGE_Q);
19 | BigInteger u0 = ProofUtils.randomNumber();
20 | BigInteger u1 = ProofUtils.randomNumber();
21 | ECPoint h = data.getH();
22 | ECPoint a0 = h.multiply(u0);
23 | ECPoint a1 = h.multiply(u1);
24 | BigInteger randomness = data.getRandomness();
25 | ECPoint statement = h.multiply(randomness);
26 | ECPoint g = data.getG();
27 | if (data.getSecret()) {
28 | statement = statement.add(g);
29 | a0 = a0.add(g.multiply(falseChallenge.negate()));
30 | } else {
31 | a1 = a1.add(g.multiply(falseChallenge));
32 | }
33 | BigInteger challenge = ProofUtils.computeChallenge(g, h, statement, a0, a1);
34 | BigInteger trueChallenge = challenge.subtract(falseChallenge).mod(ECConstants.CHALLENGE_Q);
35 | if (data.getSecret()) {
36 | BigInteger responseZero = u0.add(falseChallenge.multiply(randomness)).mod(ECConstants.Q);
37 | BigInteger responseOne = u1.add(trueChallenge.multiply(randomness)).mod(ECConstants.Q);
38 | proof = new BinaryProof(statement, falseChallenge, trueChallenge, responseZero, responseOne);
39 | } else {
40 | BigInteger responseZero = u0.add(trueChallenge.multiply(randomness)).mod(ECConstants.Q);
41 | BigInteger responseOne = u1.add(falseChallenge.multiply(randomness)).mod(ECConstants.Q);
42 | proof = new BinaryProof(statement, trueChallenge, falseChallenge, responseZero, responseOne);
43 | }
44 | return proof;
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AddressProofData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.proof.ProofData;
7 | import org.bouncycastle.math.ec.ECPoint;
8 |
9 | import java.math.BigInteger;
10 | import java.util.Optional;
11 |
12 | class AddressProofData implements ProofData {
13 | private final ECPoint publicKey;
14 | private final BigInteger balance;
15 | private final Optional privateKey;
16 | private final BigInteger balanceRandomness;
17 | private final BigInteger keyKnownRandomness;
18 | private final ECPoint g;
19 | private final ECPoint h;
20 |
21 | public AddressProofData(BigInteger privateKey, ECPoint publicKey, BigInteger balance, BigInteger balanceRandomness, BigInteger keyKnownRandomness, ECPoint g, ECPoint h) {
22 | this.privateKey = Optional.of(privateKey);
23 | this.balanceRandomness = balanceRandomness;
24 | this.keyKnownRandomness = keyKnownRandomness;
25 | this.publicKey = publicKey;
26 | this.balance = balance;
27 | this.g = g;
28 | this.h = h;
29 | }
30 |
31 | public AddressProofData(Optional privateKey, ECPoint publicKey, BigInteger balance, BigInteger balanceRandomness, BigInteger keyKnownRandomness, ECPoint g, ECPoint h) {
32 | this.privateKey =privateKey;
33 | this.balanceRandomness = balanceRandomness;
34 | this.keyKnownRandomness = keyKnownRandomness;
35 | this.publicKey = publicKey;
36 | this.balance = balance;
37 | this.g = g;
38 | this.h = h;
39 | }
40 |
41 |
42 |
43 | public Optional getPrivateKey() {
44 | return this.privateKey;
45 | }
46 |
47 | public BigInteger getBalanceRandomness() {
48 | return this.balanceRandomness;
49 | }
50 |
51 | public BigInteger getKeyKnownRandomness() {
52 | return this.keyKnownRandomness;
53 | }
54 |
55 | public ECPoint getPublicKey() {
56 | return this.publicKey;
57 | }
58 |
59 | public BigInteger getBalance() {
60 | return this.balance;
61 | }
62 |
63 | public ECPoint getG() {
64 | return this.g;
65 | }
66 |
67 | public ECPoint getH() {
68 | return this.h;
69 | }
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/SQLPrivateKeyDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import edu.stanford.crypto.SQLDatabase;
7 | import edu.stanford.crypto.database.Database;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | import java.math.BigInteger;
11 | import java.sql.Connection;
12 | import java.sql.PreparedStatement;
13 | import java.sql.ResultSet;
14 | import java.sql.SQLException;
15 | import java.util.Optional;
16 |
17 | public class SQLPrivateKeyDatabase
18 | implements PrivateKeyDatabase,
19 | SQLDatabase {
20 | public static final String RETRIEVE_SECRETS_SQL = "SELECT private_key FROM asset_proof_secrets WHERE public_key=?";
21 | public static final String INSERT_INTO_SQL = "INSERT INTO asset_proof_secrets VALUES (?,?)";
22 | private final PreparedStatement retrieveSecrets;
23 | private final PreparedStatement insertSecrets;
24 | private final Connection connection = Database.getConnection();
25 |
26 | public SQLPrivateKeyDatabase() throws SQLException {
27 | this.retrieveSecrets = this.connection.prepareStatement("SELECT private_key FROM asset_proof_secrets WHERE public_key=?");
28 | this.insertSecrets = this.connection.prepareStatement("INSERT INTO asset_proof_secrets VALUES (?,?)");
29 | }
30 |
31 | @Override
32 | public void store(ECPoint publicKey, BigInteger privateKey) {
33 | try {
34 | this.insertSecrets.setBytes(1, publicKey.getEncoded(true));
35 | this.insertSecrets.setBytes(2, privateKey.toByteArray());
36 | this.insertSecrets.execute();
37 | }
38 | catch (SQLException e) {
39 | e.printStackTrace();
40 | }
41 | }
42 |
43 | @Override
44 | public Optional retrievePrivateKey(ECPoint publicKey) {
45 | try {
46 | this.retrieveSecrets.setBytes(1, publicKey.getEncoded(true));
47 | ResultSet resultSet = this.retrieveSecrets.executeQuery();
48 | if (resultSet.next()) {
49 | return Optional.of(new BigInteger(resultSet.getBytes(1)));
50 | }
51 | return Optional.empty();
52 | }
53 | catch (SQLException e) {
54 | e.printStackTrace();
55 | throw new IllegalArgumentException(e);
56 | }
57 | }
58 |
59 | @Override
60 | public void close() throws SQLException {
61 | this.connection.close();
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/test/java/edu/stanford/crypto/proof/assets/RangeProofTest.java:
--------------------------------------------------------------------------------
1 | package edu.stanford.crypto.proof.assets;
2 |
3 | import edu.stanford.crypto.proof.RangeProofData;
4 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
5 | import edu.stanford.crypto.proof.rangeproof.BinaryRangeProofSystem;
6 | import edu.stanford.crypto.verification.BinaryRangeProofVerifier;
7 | import edu.stanford.crypto.verification.GeneratorData;
8 | import edu.stanford.crypto.verification.RangeProofVerificationData;
9 | import org.junit.Rule;
10 | import org.junit.Test;
11 | import org.junit.rules.ExpectedException;
12 |
13 | import java.math.BigInteger;
14 | import java.security.SecureRandom;
15 | import java.util.List;
16 | import java.util.stream.Collectors;
17 | import java.util.stream.Stream;
18 |
19 | /**
20 | * Created by buenz on 07.01.16.
21 | */
22 | public class RangeProofTest {
23 | @Rule
24 | public final ExpectedException exception = ExpectedException.none();
25 |
26 | @Test
27 | public void testRangeProof() {
28 | BinaryRangeProofSystem rangeProofSystem = new BinaryRangeProofSystem();
29 | BigInteger secretData = BigInteger.TEN;
30 | SecureRandom rng = new SecureRandom();
31 | List hidingFactors = Stream.generate(() -> new BigInteger(256, rng)).limit(4).collect(Collectors.toList());
32 | RangeProofData data = new RangeProofData(secretData, hidingFactors);
33 | BinaryRangeProof proof = rangeProofSystem.createProof(data);
34 | BinaryRangeProofVerifier verifier=new BinaryRangeProofVerifier();
35 |
36 | RangeProofVerificationData rangeProofVerificationData=new RangeProofVerificationData(new GeneratorData<>(),BigInteger.valueOf(15));
37 |
38 | verifier.verify(proof,rangeProofVerificationData);
39 |
40 | }
41 | @Test
42 | public void testFailedRangeProof(){
43 | exception.expect(AssertionError.class);
44 | BinaryRangeProofSystem rangeProofSystem = new BinaryRangeProofSystem();
45 | BigInteger secretData = BigInteger.valueOf(2);
46 | SecureRandom rng = new SecureRandom();
47 | List hidingFactors = Stream.generate(() -> new BigInteger(256, rng)).limit(3).collect(Collectors.toList());
48 | RangeProofData data = new RangeProofData(secretData, hidingFactors);
49 | BinaryRangeProof proof = rangeProofSystem.createProof(data);
50 | BinaryRangeProofVerifier verifier=new BinaryRangeProofVerifier();
51 |
52 | RangeProofVerificationData rangeProofVerificationData=new RangeProofVerificationData(new GeneratorData<>(),BigInteger.valueOf(15));
53 |
54 | verifier.verify(proof,rangeProofVerificationData);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/SQLCustomerSecretsDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import edu.stanford.crypto.SQLDatabase;
7 | import edu.stanford.crypto.database.Database;
8 | import edu.stanford.crypto.proof.balance.CustomerSecrets;
9 |
10 | import java.math.BigInteger;
11 | import java.sql.Connection;
12 | import java.sql.PreparedStatement;
13 | import java.sql.ResultSet;
14 | import java.sql.SQLException;
15 |
16 | public class SQLCustomerSecretsDatabase
17 | implements CustomerSecretsDatabase,
18 | SQLDatabase {
19 | public static final String RETRIEVE_SECRETS_SQL = "SELECT hash_salt,balance_salt FROM balance_proof_secrets WHERE customer_id=?";
20 | public static final String INSERT_INTO_SQL = "INSERT INTO balance_proof_secrets VALUES (?,?,?)";
21 | private final PreparedStatement retrieveSecrets;
22 | private final PreparedStatement insertSecrets;
23 | private final Connection connection = Database.getConnection();
24 |
25 | public SQLCustomerSecretsDatabase() throws SQLException {
26 | this.retrieveSecrets = this.connection.prepareStatement("SELECT hash_salt,balance_salt FROM balance_proof_secrets WHERE customer_id=?");
27 | this.insertSecrets = this.connection.prepareStatement("INSERT INTO balance_proof_secrets VALUES (?,?,?)");
28 | }
29 |
30 | @Override
31 | public void store(String customerId, BigInteger hashSalt, BigInteger balanceSalt) {
32 | try {
33 | this.insertSecrets.setString(1, customerId);
34 | this.insertSecrets.setBytes(2, hashSalt.toByteArray());
35 | this.insertSecrets.setBytes(3, balanceSalt.toByteArray());
36 | this.insertSecrets.execute();
37 | }
38 | catch (SQLException e) {
39 | e.printStackTrace();
40 | }
41 | }
42 |
43 | @Override
44 | public CustomerSecrets retrieve(String customerId) {
45 | try {
46 | this.retrieveSecrets.setString(1, customerId);
47 | ResultSet resultSet = this.retrieveSecrets.executeQuery();
48 | if (resultSet.next()) {
49 | BigInteger hashSalt = new BigInteger(resultSet.getBytes(1));
50 | BigInteger balanceRandomness = new BigInteger(resultSet.getBytes(2));
51 | return new CustomerSecrets(hashSalt, balanceRandomness);
52 | }
53 | throw new IllegalArgumentException("Customer not found " + customerId);
54 | }
55 | catch (SQLException e) {
56 | e.printStackTrace();
57 | throw new IllegalArgumentException(e);
58 | }
59 | }
60 |
61 | @Override
62 | public void close() throws SQLException {
63 | this.connection.close();
64 | }
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AddressProofSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.ProofUtils;
8 | import edu.stanford.crypto.proof.ProofSystem;
9 | import org.bouncycastle.math.ec.ECPoint;
10 |
11 | import java.math.BigInteger;
12 | import java.util.Optional;
13 |
14 | /**
15 | * Zero knowledge proof for public key y with balance b of the statement:
16 | * "Either I know the private key x such that xG=y and p is a commitment to b or p is a commitment to 0."
17 | */
18 | public class AddressProofSystem implements ProofSystem {
19 | @Override
20 | public AddressProof createProof(AddressProofData data) {
21 | BigInteger u1 = ProofUtils.randomNumber();
22 | BigInteger u2 = ProofUtils.randomNumber();
23 | BigInteger u3 = ProofUtils.randomNumber();
24 | BigInteger u4 = ProofUtils.randomNumber();
25 | ECPoint g = data.getG();
26 | ECPoint h = data.getH();
27 | ECPoint y = data.getPublicKey();
28 | ECPoint b = data.getG().multiply(data.getBalance());
29 | ECPoint a1 = b.multiply(u1).add(h.multiply(u2));
30 | ECPoint a2 = y.multiply(u1).add(h.multiply(u3));
31 | ECPoint a3 = g.multiply(u4).add(h.multiply(u3));
32 | Optional privateKey = data.getPrivateKey();
33 | BigInteger v = data.getBalanceRandomness();
34 | BigInteger t = data.getKeyKnownRandomness();
35 | BigInteger s = privateKey.isPresent() ? BigInteger.ONE : BigInteger.ZERO;
36 | ECPoint p = b.multiply(s).add(h.multiply(v));
37 | ECPoint l = y.multiply(s).add(h.multiply(t));
38 |
39 | //Binary proof
40 | BigInteger uZero = ProofUtils.randomNumber();
41 | BigInteger uOne = ProofUtils.randomNumber();
42 | BigInteger falseChallenge = ProofUtils.randomNumber(256).mod(ECConstants.CHALLENGE_Q);
43 | ECPoint falseChallengeElement = b.multiply(falseChallenge);
44 | ECPoint aZero = h.multiply(uZero).subtract(falseChallengeElement.multiply(s));
45 | ECPoint aOne = h.multiply(uOne).add(falseChallengeElement.multiply(BigInteger.ONE.subtract(s)));
46 |
47 |
48 | BigInteger challenge = ProofUtils.computeChallenge(g, h, y, b, p, l, a1, a2, a3, aZero, aOne);
49 | BigInteger responseS = u1.add(challenge.multiply(s));
50 | BigInteger responseV = u2.add(challenge.multiply(v));
51 | BigInteger responseT = u3.add(challenge.multiply(t));
52 | BigInteger responseX = u4.add(challenge.multiply(privateKey.orElse(BigInteger.ZERO)));
53 | BigInteger trueChallenge = challenge.subtract(falseChallenge).mod(ECConstants.CHALLENGE_Q);
54 | BigInteger falseV = falseChallenge.multiply(v);
55 | BigInteger trueV = trueChallenge.multiply(v);
56 |
57 | BigInteger responseZero = uZero.add(trueV.multiply(BigInteger.ONE.subtract(s))).add(falseV.multiply(s)).mod(ECConstants.Q);
58 | BigInteger responseOne = uOne.add(falseV.multiply(BigInteger.ONE.subtract(s))).add(trueV.multiply(s)).mod(ECConstants.Q);
59 |
60 |
61 | return new AddressProof(p, l, privateKey.isPresent() ? falseChallenge : trueChallenge, privateKey.isPresent() ? trueChallenge : falseChallenge, responseS, responseV, responseT, responseX, responseZero, responseOne);
62 | }
63 |
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/experiments/AssetProofExperiment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.experiments;
5 |
6 | import edu.stanford.crypto.ExperimentUtils;
7 | import edu.stanford.crypto.database.Database;
8 | import edu.stanford.crypto.proof.assets.AssetProof;
9 | import edu.stanford.crypto.proof.assets.AssetProofSystem;
10 | import edu.stanford.crypto.verification.AssetsVerifier;
11 | import edu.stanford.crypto.verification.GeneratorData;
12 |
13 | import java.io.IOException;
14 | import java.io.OutputStream;
15 | import java.nio.file.Files;
16 | import java.nio.file.OpenOption;
17 | import java.nio.file.Path;
18 | import java.nio.file.Paths;
19 | import java.sql.SQLException;
20 |
21 | public class AssetProofExperiment {
22 | public static void main(String[] args) throws IOException, SQLException {
23 | Path outputFile = Paths.get(args[0], new String[0]);
24 | OutputStream stream = Files.newOutputStream(outputFile, new OpenOption[0]);
25 | Throwable throwable = null;
26 | try {
27 | int[] numberOfAddresses;
28 | stream.write("Addresses;Proof Time;Verify time;File size\n".getBytes());
29 | for (int numKeys : numberOfAddresses = new int[]{10, 100, 1000, 10000, 100000, 200000, 500000}) {
30 | AssetProofSystem proofSystem = new AssetProofSystem();
31 | AssetsVerifier verifier = new AssetsVerifier();
32 | GeneratorData data = new GeneratorData();
33 | long startClearing = System.currentTimeMillis();
34 | System.out.println("Starting to clear proofs ");
35 | Database.clearProofs();
36 | long endClearing = System.currentTimeMillis();
37 | System.out.println("Took " + (double)(endClearing - startClearing) / 1000.0 + "s");
38 | ExperimentUtils.generatePublicKeys(numKeys);
39 | long endCreating = System.currentTimeMillis();
40 | System.out.println("Took " + (double)(endCreating - endClearing) / 1000.0 + "s to create keys");
41 | long startProof = System.currentTimeMillis();
42 | AssetProof proof = proofSystem.createProof(null);
43 | long endProof = System.currentTimeMillis();
44 | System.out.println("Finished balance proof in " + (endProof - startProof) / 1000 + "s");
45 | verifier.verify(proof, data);
46 | long endVerifyFull = System.currentTimeMillis();
47 | System.out.println("Finished verification in " + (endVerifyFull - endProof) / 1000 + "s");
48 | stream.write(("" + numKeys + ";" + (endProof - startProof) + ";" + (endVerifyFull - endProof) + ";" + proof.getSizeInfo() + "\n").getBytes());
49 | stream.flush();
50 | proof.close();
51 | System.out.println("Connections closed");
52 | }
53 | }
54 | catch (Throwable numberOfAddresses) {
55 | throwable = numberOfAddresses;
56 | throw numberOfAddresses;
57 | }
58 | finally {
59 | if (stream != null) {
60 | if (throwable != null) {
61 | try {
62 | stream.close();
63 | }
64 | catch (Throwable numberOfAddresses) {
65 | throwable.addSuppressed(numberOfAddresses);
66 | }
67 | } else {
68 | stream.close();
69 | }
70 | }
71 | }
72 | System.out.println("Proof Sucess");
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | edu.stanford.crypto
6 | bitcoinprovisions
7 | 0.0.1-SNAPSHOT
8 | jar
9 |
10 | bitcoinprovisions
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 | 1.7.7
16 |
17 | 2.0.2
18 |
19 |
20 |
21 |
22 | org.apache.maven.plugins
23 | maven-shade-plugin
24 | 2.3
25 |
26 |
27 |
28 | *:*
29 |
30 | META-INF/*.SF
31 | META-INF/*.DSA
32 | META-INF/*.RSA
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | package
41 |
42 | shade
43 |
44 |
45 |
46 |
47 |
48 | org.apache.maven.plugins
49 | maven-compiler-plugin
50 | 3.1
51 |
52 | 1.8
53 | 1.8
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | junit
66 | junit
67 | 4.12
68 | test
69 |
70 |
71 |
72 | org.easytesting
73 | fest-assert-core
74 | 2.0M10
75 | test
76 |
77 |
78 |
79 | org.bouncycastle
80 | bcpkix-jdk15on
81 | 1.54
82 |
83 |
84 | org.apache.logging.log4j
85 | log4j-api
86 | 2.5
87 |
88 |
89 | org.apache.logging.log4j
90 | log4j-core
91 | 2.5
92 |
93 |
94 |
95 | org.postgresql
96 | postgresql
97 | 9.4-1201-jdbc41
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/binary/BinaryProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.binary;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.MemoryProof;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | import java.math.BigInteger;
11 | import java.util.Arrays;
12 | import java.util.List;
13 |
14 | public class BinaryProof
15 | implements MemoryProof {
16 | private final ECPoint statement;
17 | private final BigInteger challengeZero;
18 | private final BigInteger challengeOne;
19 | private final BigInteger responseZero;
20 | private final BigInteger responseOne;
21 |
22 | public BinaryProof(ECPoint statement, BigInteger challengeZero, BigInteger challengeOne, BigInteger responseZero, BigInteger responseOne) {
23 | this.statement = statement;
24 | this.challengeZero = challengeZero;
25 | this.challengeOne = challengeOne;
26 | this.responseZero = responseZero;
27 | this.responseOne = responseOne;
28 | }
29 |
30 | public BinaryProof(byte[] array) {
31 | this(array, new int[]{0});
32 | }
33 |
34 | public BinaryProof(byte[] array, int[] index) {
35 | int n = index[0];
36 | index[0] = n + 1;
37 | byte statementLength = array[n];
38 | this.statement = ECConstants.BITCOIN_CURVE.decodePoint(Arrays.copyOfRange(array, index[0], statementLength + index[0]));
39 | index[0] = index[0] + statementLength;
40 | int n2 = index[0];
41 | index[0] = n2 + 1;
42 | statementLength = array[n2];
43 | this.challengeZero = new BigInteger(Arrays.copyOfRange(array, index[0], statementLength + index[0]));
44 | index[0] = index[0] + statementLength;
45 | int n3 = index[0];
46 | index[0] = n3 + 1;
47 | statementLength = array[n3];
48 | this.challengeOne = new BigInteger(Arrays.copyOfRange(array, index[0], statementLength + index[0]));
49 | index[0] = index[0] + statementLength;
50 | int n4 = index[0];
51 | index[0] = n4 + 1;
52 | statementLength = array[n4];
53 | this.responseZero = new BigInteger(Arrays.copyOfRange(array, index[0], statementLength + index[0]));
54 | index[0] = index[0] + statementLength;
55 | int n5 = index[0];
56 | index[0] = n5 + 1;
57 | statementLength = array[n5];
58 | this.responseOne = new BigInteger(Arrays.copyOfRange(array, index[0], statementLength + index[0]));
59 | index[0] = index[0] + statementLength;
60 | }
61 |
62 | public ECPoint getStatement() {
63 | return this.statement;
64 | }
65 |
66 | public BigInteger getChallengeZero() {
67 | return this.challengeZero;
68 | }
69 |
70 | public BigInteger getChallengeOne() {
71 | return this.challengeOne;
72 | }
73 |
74 | public BigInteger getResponseZero() {
75 | return this.responseZero;
76 | }
77 |
78 | public BigInteger getResponseOne() {
79 | return this.responseOne;
80 | }
81 |
82 | @Override
83 | public byte[] serialize() {
84 | byte[] encodedStatement = this.statement.getEncoded(true);
85 | byte[] chall0Arr = this.challengeZero.toByteArray();
86 | byte[] challOneArr = this.challengeOne.toByteArray();
87 | byte[] responseZeroArr = this.responseZero.toByteArray();
88 | byte[] responseOneArr = this.responseOne.toByteArray();
89 | List arrList = Arrays.asList(encodedStatement, chall0Arr, challOneArr, responseZeroArr, responseOneArr);
90 | int totalLength = arrList.stream().mapToInt(arr -> arr.length).map(i -> i + 1).sum();
91 | byte[] fullArray = new byte[totalLength];
92 | int currIndex = 0;
93 | for (byte[] arr2 : arrList) {
94 | fullArray[currIndex++] = (byte)arr2.length;
95 | System.arraycopy(arr2, 0, fullArray, currIndex, arr2.length);
96 | currIndex += arr2.length;
97 | }
98 | return fullArray;
99 | }
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/verification/AssetsVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.verification;
5 |
6 | import edu.stanford.crypto.BlockingExecutor;
7 | import edu.stanford.crypto.ECConstants;
8 | import edu.stanford.crypto.bitcoin.SQLBlockchain;
9 | import edu.stanford.crypto.proof.assets.AddressProof;
10 | import edu.stanford.crypto.proof.assets.AddressProofEntry;
11 | import edu.stanford.crypto.proof.assets.AssetProof;
12 | import edu.stanford.crypto.proof.binary.BinaryProof;
13 | import org.bouncycastle.math.ec.ECPoint;
14 |
15 | import java.math.BigInteger;
16 | import java.sql.SQLException;
17 | import java.util.Iterator;
18 | import java.util.concurrent.ArrayBlockingQueue;
19 | import java.util.concurrent.BlockingQueue;
20 | import java.util.concurrent.TimeUnit;
21 | import java.util.concurrent.atomic.AtomicReference;
22 | import java.util.stream.Stream;
23 |
24 | public class AssetsVerifier
25 | implements Verifier> {
26 | private final AddressProofVerifier addressVerifier = new AddressProofVerifier();
27 | private final BlockingQueue proofsQueue = new ArrayBlockingQueue<>(Runtime.getRuntime().availableProcessors() * 3);
28 | private final AtomicReference totalEncryption = new AtomicReference<>(ECConstants.INFINITY);
29 |
30 | @Override
31 | public void verify(AssetProof proof, GeneratorData data) {
32 | Iterator addressProofs = proof.getAddressProofs();
33 | BlockingExecutor pool = new BlockingExecutor();
34 | int nThreads = Runtime.getRuntime().availableProcessors() - 1;
35 | Stream.generate(AssetsVerificationWorker::new).limit(nThreads).forEach(pool::submit);
36 |
37 | try (SQLBlockchain blockchain = new SQLBlockchain()) {
38 | AddressProofEntry addressProofEntry;
39 | while (addressProofs.hasNext()) {
40 | addressProofEntry = addressProofs.next();
41 | if (this.proofsQueue.offer(addressProofEntry)) continue;
42 | this.verifyAddressProof(blockchain, addressProofEntry);
43 | }
44 | while ((addressProofEntry = this.proofsQueue.poll()) != null) {
45 | this.verifyAddressProof(blockchain, addressProofEntry);
46 | }
47 | pool.shutdownNow();
48 | pool.awaitTermination(1, TimeUnit.MINUTES);
49 | System.out.println("Total Encryption " + this.totalEncryption.get().normalize());
50 |
51 |
52 | } catch (SQLException e) {
53 | e.printStackTrace();
54 | throw new AssertionError(e);
55 | } catch (InterruptedException e) {
56 | e.printStackTrace();
57 | throw new IllegalArgumentException("Couldn't complete proof");
58 | }
59 | }
60 |
61 | private void verifyAddressProof(SQLBlockchain blockchain, AddressProofEntry addressProofEntry) {
62 | ECPoint publicKey = addressProofEntry.getPublicKey();
63 | BigInteger balance = blockchain.getBalance(publicKey);
64 | AddressVerificationData addressVerificationData = new AddressVerificationData(publicKey, balance, ECConstants.G, ECConstants.H);
65 | AddressProof addressProof = addressProofEntry.getAddressProof();
66 | this.addressVerifier.verify(addressProof, addressVerificationData);
67 | this.totalEncryption.accumulateAndGet(addressProof.getCommitmentBalance(), ECPoint::add);
68 | }
69 |
70 | private class AssetsVerificationWorker
71 | implements Runnable {
72 | private AssetsVerificationWorker() {
73 | }
74 |
75 | @Override
76 | public void run() {
77 | try (SQLBlockchain blockchain = new SQLBlockchain()) {
78 |
79 | while (!Thread.interrupted()) {
80 | try {
81 | AddressProofEntry addressProofEntry = AssetsVerifier.this.proofsQueue.take();
82 | AssetsVerifier.this.verifyAddressProof(blockchain, addressProofEntry);
83 | } catch (InterruptedException e) {
84 | // empty catch block
85 | break;
86 | }
87 | }
88 |
89 | } catch (SQLException e) {
90 | e.printStackTrace();
91 | throw new AssertionError(e);
92 | }
93 | }
94 | }
95 |
96 | }
97 |
98 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/SQLBlockchain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.SQLDatabase;
8 | import edu.stanford.crypto.database.Database;
9 | import org.bouncycastle.math.ec.ECPoint;
10 |
11 | import java.math.BigInteger;
12 | import java.sql.Connection;
13 | import java.sql.PreparedStatement;
14 | import java.sql.ResultSet;
15 | import java.sql.SQLException;
16 | import java.util.Iterator;
17 |
18 | public class SQLBlockchain
19 | implements Blockchain,
20 | SQLDatabase {
21 | private static final String INSERT_ENTRY_SQL = "INSERT INTO blockchain VALUES (?,?)";
22 | private static final String LIST_ENTRIES_SQL = "SELECT public_key,balance FROM blockchain";
23 | private static final String GET_BALANCE_SQL = "SELECT balance FROM blockchain WHERE public_key=?";
24 | public static final String TRUNCATE_TABLE_SQL = "TRUNCATE TABLE asset_proof,asset_proof_secrets,blockchain";
25 | private final Connection connection = Database.getConnection();
26 | private final PreparedStatement getBalance;
27 | private final PreparedStatement insertEntry;
28 | private final PreparedStatement truncateDB;
29 |
30 | public SQLBlockchain() throws SQLException {
31 | getBalance = this.connection.prepareStatement("SELECT balance FROM blockchain WHERE public_key=?");
32 | insertEntry = this.connection.prepareStatement("INSERT INTO blockchain VALUES (?,?)");
33 | truncateDB = this.connection.prepareStatement("TRUNCATE TABLE asset_proof,asset_proof_secrets,blockchain");
34 | }
35 |
36 | @Override
37 | public BigInteger getBalance(ECPoint publicKey) {
38 | try {
39 | this.getBalance.setBytes(1, publicKey.getEncoded(true));
40 | ResultSet resultSet = this.getBalance.executeQuery();
41 | if (resultSet.next()) {
42 | long balance = resultSet.getLong(1);
43 | return BigInteger.valueOf(balance);
44 | }
45 | }
46 | catch (SQLException e) {
47 | e.printStackTrace();
48 | }
49 | throw new IllegalArgumentException("Can't find " + publicKey);
50 | }
51 |
52 | @Override
53 | public void addEntry(ECPoint pubKey, BigInteger balance) {
54 | try {
55 | this.insertEntry.setBytes(1, pubKey.getEncoded(true));
56 | this.insertEntry.setLong(2, balance.longValueExact());
57 | this.insertEntry.execute();
58 | }
59 | catch (SQLException e) {
60 | e.printStackTrace();
61 | }
62 | }
63 |
64 | @Override
65 | public Iterator getBlockchainEntries() {
66 | try {
67 | final ResultSet resultSet = this.connection.createStatement().executeQuery("SELECT public_key,balance FROM blockchain");
68 | return new Iterator(){
69 |
70 | @Override
71 | public boolean hasNext() {
72 | try {
73 | return resultSet.next();
74 | }
75 | catch (SQLException e) {
76 | e.printStackTrace();
77 | throw new IllegalStateException(e);
78 | }
79 | }
80 |
81 | @Override
82 | public BlockchainEntry next() {
83 | try {
84 | byte[] pubKey = resultSet.getBytes(1);
85 | long balance = resultSet.getLong(2);
86 | return new BlockchainEntry(ECConstants.BITCOIN_CURVE.decodePoint(pubKey), BigInteger.valueOf(balance));
87 | }
88 | catch (SQLException e) {
89 | e.printStackTrace();
90 | throw new IllegalStateException(e);
91 | }
92 | }
93 | };
94 | }
95 | catch (SQLException e) {
96 | e.printStackTrace();
97 | throw new IllegalStateException(e);
98 | }
99 | }
100 |
101 | @Override
102 | public void close() throws SQLException {
103 | this.connection.close();
104 | }
105 |
106 | @Override
107 | public void truncate() {
108 | try {
109 | this.truncateDB.execute();
110 | }
111 | catch (SQLException e) {
112 | e.printStackTrace();
113 | }
114 | }
115 |
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/ExperimentUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto;
5 |
6 | import edu.stanford.crypto.bitcoin.SQLBlockchain;
7 | import edu.stanford.crypto.bitcoin.SQLCustomerDatabase;
8 | import edu.stanford.crypto.bitcoin.SQLPrivateKeyDatabase;
9 | import org.bouncycastle.math.ec.ECPoint;
10 |
11 | import java.math.BigInteger;
12 | import java.sql.SQLException;
13 | import java.util.Random;
14 | import java.util.concurrent.ForkJoinTask;
15 | import java.util.concurrent.Semaphore;
16 |
17 | public class ExperimentUtils {
18 | public static void generateRandomCustomers(int numCustomers, int maxBits) throws SQLException {
19 | try {
20 | SQLCustomerDatabase database = new SQLCustomerDatabase();
21 | try {
22 | database.truncate();
23 | } finally {
24 |
25 | database.close();
26 |
27 | }
28 | } catch (Exception e) {
29 | e.printStackTrace();
30 | throw new RuntimeException(e);
31 | }
32 | Random rng = new Random();
33 | int availableProcessors = Runtime.getRuntime().availableProcessors();
34 | Semaphore semaphore = new Semaphore(0);
35 | int process = 0;
36 | while (process < availableProcessors) {
37 | SQLCustomerDatabase processDb = new SQLCustomerDatabase();
38 | int processId = process++;
39 | ForkJoinTask.adapt(() -> {
40 | for (int i = processId; i < numCustomers; i += availableProcessors) {
41 | String customerId = "C" + i;
42 | BigInteger balance = rng.nextDouble() > 0.9 ? new BigInteger(maxBits, rng) : new BigInteger(10, rng);
43 | processDb.addBalance(customerId, balance);
44 | }
45 | try {
46 | processDb.close();
47 | } catch (Exception e) {
48 | e.printStackTrace();
49 | }
50 | semaphore.release();
51 | }
52 | ).fork();
53 | }
54 | try {
55 | semaphore.acquire(availableProcessors);
56 | } catch (InterruptedException e) {
57 | e.printStackTrace();
58 | }
59 | }
60 |
61 | public static void generatePublicKeys(int numAddresses) throws SQLException {
62 | SQLBlockchain blockchain = new SQLBlockchain();
63 | try {
64 | blockchain.truncate();
65 | } finally {
66 |
67 | blockchain.close();
68 | }
69 | Random rng = new Random();
70 | int availableProcessors = Runtime.getRuntime().availableProcessors();
71 | Semaphore semaphore = new Semaphore(0);
72 | int process = 0;
73 | while (process < availableProcessors) {
74 | SQLBlockchain processBlockchain = new SQLBlockchain();
75 | SQLPrivateKeyDatabase privateKeyDatabase = new SQLPrivateKeyDatabase();
76 | int processId = process++;
77 | ForkJoinTask.adapt(() -> {
78 | try {
79 | for (int i = processId; i < numAddresses; i += availableProcessors) {
80 | BigInteger privateKey = new BigInteger(256, rng);
81 | ECPoint publicKey = ECConstants.G.multiply(privateKey);
82 | BigInteger balance = new BigInteger(10, rng);
83 | processBlockchain.addEntry(publicKey, balance);
84 | if (rng.nextDouble() >= 0.05) continue;
85 | privateKeyDatabase.store(publicKey, privateKey);
86 | }
87 | } finally {
88 | try {
89 | privateKeyDatabase.close();
90 | processBlockchain.close();
91 | } catch (SQLException e) {
92 | e.printStackTrace();
93 | }
94 |
95 | semaphore.release();
96 | }
97 | }
98 | ).fork();
99 | }
100 | try {
101 | semaphore.acquire(availableProcessors);
102 | } catch (InterruptedException e) {
103 | e.printStackTrace();
104 | }
105 | }
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/balance/BalanceProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.balance;
5 |
6 | import com.sun.org.apache.regexp.internal.RE;
7 | import edu.stanford.crypto.SQLDatabase;
8 | import edu.stanford.crypto.database.Database;
9 | import edu.stanford.crypto.proof.Proof;
10 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
11 |
12 | import java.math.BigInteger;
13 | import java.sql.Connection;
14 | import java.sql.PreparedStatement;
15 | import java.sql.ResultSet;
16 | import java.sql.SQLException;
17 | import java.util.Arrays;
18 | import java.util.Iterator;
19 |
20 | public class BalanceProof
21 | implements Proof,
22 | SQLDatabase {
23 | public static final String ADD_USER_SQL = "INSERT INTO balance_proof VALUES (?, ?) ";
24 | public static final String GET_PROOF_SQL = "SELECT balance_proof.range_proof FROM balance_proof WHERE customer_id_hash= ?";
25 | public static final String LIST_PROOFS_SQL = "SELECT balance_proof.range_proof FROM balance_proof ";
26 | public static final String READ_SIZE = "SELECT pg_size_pretty(pg_total_relation_size('public.balance_proof'))";
27 | private final PreparedStatement updateStatement;
28 | private final PreparedStatement readStatement;
29 | private final Connection connection = Database.getConnection();
30 |
31 | public BalanceProof() throws SQLException {
32 | this.updateStatement = this.connection.prepareStatement(ADD_USER_SQL);
33 | this.readStatement = this.connection.prepareStatement(GET_PROOF_SQL);
34 | }
35 |
36 | public void addCustomer(BigInteger hashedId, BinaryRangeProof balanceProof) {
37 | try {
38 | this.updateStatement.setBytes(1, hashedId.toByteArray());
39 | this.updateStatement.setBytes(2, balanceProof.serialize());
40 | this.updateStatement.executeUpdate();
41 | } catch (SQLException ex) {
42 | throw new IllegalArgumentException(ex);
43 | }
44 | }
45 |
46 | public BinaryRangeProof getCustomerProof(BigInteger hashedId) {
47 | try {
48 | this.readStatement.setBytes(1, hashedId.toByteArray());
49 | ResultSet resultSet = this.readStatement.executeQuery();
50 | if (resultSet.next()) {
51 | byte[] proof = resultSet.getBytes(1);
52 | return new BinaryRangeProof(proof);
53 | }
54 | } catch (SQLException ex) {
55 | ex.printStackTrace();
56 | }
57 | throw new IllegalArgumentException("No such id " + Arrays.toString(hashedId.toByteArray()));
58 | }
59 |
60 | public Iterator getRangeProofs() {
61 | try {
62 | this.connection.setAutoCommit(false);
63 | final ResultSet resultSet = this.connection.createStatement().executeQuery(LIST_PROOFS_SQL);
64 | resultSet.setFetchSize(1000);
65 | return new Iterator() {
66 |
67 | @Override
68 | public boolean hasNext() {
69 | try {
70 | boolean next = resultSet.next();
71 | if (!next) {
72 | BalanceProof.this.connection.setAutoCommit(true);
73 | }
74 | return next;
75 | } catch (SQLException e) {
76 | e.printStackTrace();
77 | throw new IllegalStateException(e);
78 | }
79 | }
80 |
81 | @Override
82 | public BinaryRangeProof next() {
83 | try {
84 | byte[] bytes = resultSet.getBytes(1);
85 | return new BinaryRangeProof(bytes);
86 | } catch (SQLException e) {
87 | e.printStackTrace();
88 | throw new IllegalStateException(e);
89 | }
90 | }
91 | };
92 | } catch (SQLException e) {
93 | e.printStackTrace();
94 | throw new IllegalStateException(e);
95 | }
96 | }
97 |
98 | public String getSizeInfo() {
99 | try {
100 | ResultSet resultSet = this.connection.createStatement().executeQuery(READ_SIZE);
101 | if (resultSet.next()) {
102 | return resultSet.getString(1);
103 | }
104 | } catch (SQLException e) {
105 | e.printStackTrace();
106 | }
107 | throw new IllegalStateException("Couldn't run query " + READ_SIZE);
108 | }
109 |
110 | @Override
111 | public void close() throws SQLException {
112 | this.connection.close();
113 | }
114 |
115 | public Connection getConnection() {
116 | return this.connection;
117 | }
118 |
119 | }
120 |
121 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/bitcoin/SQLCustomerDatabase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.bitcoin;
5 |
6 | import edu.stanford.crypto.SQLDatabase;
7 | import edu.stanford.crypto.database.Database;
8 | import edu.stanford.crypto.proof.balance.CustomerInfo;
9 |
10 | import java.math.BigInteger;
11 | import java.sql.Connection;
12 | import java.sql.PreparedStatement;
13 | import java.sql.ResultSet;
14 | import java.sql.SQLException;
15 | import java.util.Iterator;
16 |
17 | public class SQLCustomerDatabase
18 | implements CustomerDatabase,
19 | SQLDatabase {
20 | public static final String QUERY_BALANCE_SQL = "SELECT balance FROM customer_balance WHERE customer_id=?";
21 | public static final String LIST_CUSTOMERS_SQL = "SELECT customer_id,balance FROM customer_balance";
22 | public static final String INSERT_CUSTOMER_SQL = "INSERT INTO customer_balance VALUES (?,?)";
23 | public static final String TRUNCATE_TABLE_SQL = "TRUNCATE TABLE customer_balance,balance_proof_secrets";
24 | private final PreparedStatement queryBalance;
25 | private final PreparedStatement listCustomers;
26 | private final PreparedStatement insertCustomer;
27 | private final PreparedStatement truncateDB;
28 | private final Connection connection = Database.getConnection();
29 |
30 | public SQLCustomerDatabase() throws SQLException {
31 | this.queryBalance = this.connection.prepareStatement("SELECT balance FROM customer_balance WHERE customer_id=?");
32 | this.listCustomers = this.connection.prepareStatement("SELECT customer_id,balance FROM customer_balance");
33 | this.insertCustomer = this.connection.prepareStatement("INSERT INTO customer_balance VALUES (?,?)");
34 | this.truncateDB = this.connection.prepareStatement("TRUNCATE TABLE customer_balance,balance_proof_secrets");
35 | }
36 |
37 | @Override
38 | public BigInteger getBalance(String customerId) {
39 | try {
40 | this.queryBalance.setString(1, customerId);
41 | ResultSet resultSet = this.queryBalance.executeQuery();
42 | if (resultSet.next()) {
43 | long balance = resultSet.getLong(1);
44 | return BigInteger.valueOf(balance);
45 | }
46 | throw new AssertionError((Object)("Customer not found " + customerId));
47 | }
48 | catch (SQLException e) {
49 | e.printStackTrace();
50 | throw new AssertionError(e);
51 | }
52 | }
53 |
54 | @Override
55 | public void addBalance(String customerId, BigInteger balance) {
56 | try {
57 | PreparedStatement statement = this.insertCustomer;
58 | statement.setString(1, customerId);
59 | statement.setLong(2, balance.longValueExact());
60 | statement.execute();
61 | }
62 | catch (SQLException e) {
63 | e.printStackTrace();
64 | throw new IllegalStateException(e);
65 | }
66 | }
67 |
68 | @Override
69 | public Iterator getCustomers() {
70 | try {
71 | this.connection.setAutoCommit(false);
72 | final ResultSet resultSet = this.listCustomers.executeQuery();
73 | resultSet.setFetchSize(1000);
74 | return new Iterator(){
75 |
76 | @Override
77 | public boolean hasNext() {
78 | try {
79 | boolean hasNext = resultSet.next();
80 | if (!hasNext) {
81 | SQLCustomerDatabase.this.connection.setAutoCommit(true);
82 | }
83 | return hasNext;
84 | }
85 | catch (SQLException e) {
86 | throw new IllegalStateException(e);
87 | }
88 | }
89 |
90 | @Override
91 | public CustomerInfo next() {
92 | try {
93 | String id = resultSet.getString(1);
94 | long balance = resultSet.getLong(2);
95 | return new CustomerInfo(id, BigInteger.valueOf(balance));
96 | }
97 | catch (SQLException e) {
98 | throw new IllegalStateException(e);
99 | }
100 | }
101 | };
102 | }
103 | catch (SQLException e) {
104 | e.printStackTrace();
105 | throw new AssertionError(e);
106 | }
107 | }
108 |
109 | @Override
110 | public void truncate() {
111 | try {
112 | this.truncateDB.execute();
113 | }
114 | catch (SQLException e) {
115 | e.printStackTrace();
116 | }
117 | }
118 |
119 | @Override
120 | public void close() throws SQLException {
121 | this.connection.close();
122 | }
123 |
124 | }
125 |
126 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AssetProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.SQLDatabase;
8 | import edu.stanford.crypto.database.Database;
9 | import edu.stanford.crypto.proof.Proof;
10 | import edu.stanford.crypto.proof.binary.BinaryProof;
11 | import org.bouncycastle.math.ec.ECPoint;
12 |
13 | import java.sql.Connection;
14 | import java.sql.PreparedStatement;
15 | import java.sql.ResultSet;
16 | import java.sql.SQLException;
17 | import java.util.Iterator;
18 |
19 | public class AssetProof
20 | implements Proof,
21 | SQLDatabase {
22 | public static final String ADD_ADDRESS = "INSERT INTO asset_proof VALUES (?, ?) ";
23 | public static final String GET_PROOF_SQL = "SELECT asset_proof.main_proof FROM asset_proof WHERE public_key= ?";
24 | public static final String LIST_PROOFS_SQL = "SELECT asset_proof.public_key,asset_proof.main_proof FROM asset_proof ";
25 | public static final String READ_SIZE = "SELECT pg_size_pretty(pg_total_relation_size('public.asset_proof'))";
26 | private final PreparedStatement updateStatement;
27 | private final PreparedStatement readStatement;
28 | private final Connection connection = Database.getConnection();
29 |
30 | public AssetProof() throws SQLException {
31 | this.updateStatement = this.connection.prepareStatement(ADD_ADDRESS);
32 | this.readStatement = this.connection.prepareStatement(GET_PROOF_SQL);
33 | }
34 |
35 | @Override
36 | public void close() throws SQLException {
37 | this.connection.close();
38 | }
39 |
40 | public void addAddressProof(ECPoint publicKey, AddressProof proof) {
41 | try {
42 | this.updateStatement.setBytes(1, publicKey.getEncoded(true));
43 | this.updateStatement.setBytes(2, proof.serialize());
44 | this.updateStatement.executeUpdate();
45 | }
46 | catch (SQLException ex) {
47 | throw new IllegalArgumentException(ex);
48 | }
49 | }
50 |
51 | public AddressProof getAddressProof(ECPoint publicKey) {
52 | try {
53 | this.readStatement.setBytes(1, publicKey.getEncoded(true));
54 | ResultSet resultSet = this.readStatement.executeQuery();
55 | if (resultSet.next()) {
56 | byte[] proof = resultSet.getBytes(1);
57 | return new AddressProof(proof);
58 | }
59 | }
60 | catch (SQLException ex) {
61 | ex.printStackTrace();
62 | }
63 | throw new IllegalArgumentException("No such id " + publicKey.normalize());
64 | }
65 |
66 | public Iterator getAddressProofs() {
67 | try {
68 | this.connection.setAutoCommit(false);
69 | final ResultSet resultSet = this.connection.createStatement().executeQuery(LIST_PROOFS_SQL);
70 | resultSet.setFetchSize(1000);
71 | return new Iterator(){
72 |
73 | @Override
74 | public boolean hasNext() {
75 | try {
76 | boolean next = resultSet.next();
77 | if (!next) {
78 | AssetProof.this.connection.setAutoCommit(true);
79 | }
80 | return next;
81 | }
82 | catch (SQLException e) {
83 | e.printStackTrace();
84 | throw new IllegalStateException(e);
85 | }
86 | }
87 |
88 | @Override
89 | public AddressProofEntry next() {
90 | try {
91 | byte[] publicKeyBytes = resultSet.getBytes(1);
92 | byte[] proofBytes = resultSet.getBytes(2);
93 | ECPoint publicKey = ECConstants.BITCOIN_CURVE.decodePoint(publicKeyBytes);
94 | AddressProof addressProof = new AddressProof(proofBytes);
95 | return new AddressProofEntry(publicKey, addressProof);
96 | }
97 | catch (SQLException e) {
98 | e.printStackTrace();
99 | throw new IllegalStateException(e);
100 | }
101 | }
102 | };
103 | }
104 | catch (SQLException e) {
105 | e.printStackTrace();
106 | throw new IllegalStateException(e);
107 | }
108 | }
109 |
110 | public Connection getConnection() {
111 | return this.connection;
112 | }
113 |
114 | public String getSizeInfo() {
115 | try {
116 | ResultSet resultSet = this.connection.createStatement().executeQuery(READ_SIZE);
117 | if (resultSet.next()) {
118 | return resultSet.getString(1);
119 | }
120 | }
121 | catch (SQLException e) {
122 | e.printStackTrace();
123 | }
124 | throw new IllegalStateException("Couldn't run query "+READ_SIZE);
125 | }
126 |
127 | }
128 |
129 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/database/Database.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.database;
5 |
6 | import java.net.UnknownHostException;
7 | import java.sql.*;
8 |
9 | public final class Database {
10 | public static final String URL = "jdbc:postgresql://127.0.0.1/provisions";
11 | public static final String USER = "admin";
12 | public static final String PASSWORD = "password";
13 |
14 | private Database() throws UnknownHostException, ClassNotFoundException, SQLException {
15 | }
16 |
17 | public static Connection getConnection() throws SQLException {
18 | DriverManager.setLoginTimeout(10);
19 | return DriverManager.getConnection(URL, USER, PASSWORD);
20 | }
21 |
22 | public static void clearProofs() {
23 | try {
24 | Connection connection = Database.getConnection();
25 | Throwable throwable = null;
26 | try {
27 | Statement statement = connection.createStatement();
28 | statement.execute("TRUNCATE TABLE balance_proof,balance_proof_secrets,asset_proof");
29 | }
30 | catch (Throwable statement) {
31 | throwable = statement;
32 | throw statement;
33 | }
34 | finally {
35 | if (connection != null) {
36 | if (throwable != null) {
37 | try {
38 | connection.close();
39 | }
40 | catch (Throwable statement) {
41 | throwable.addSuppressed(statement);
42 | }
43 | } else {
44 | connection.close();
45 | }
46 | }
47 | }
48 | }
49 | catch (SQLException e) {
50 | e.printStackTrace();
51 | throw new IllegalStateException(e);
52 | }
53 | }
54 |
55 | public static void createTables() throws SQLException {
56 | Connection connection = Database.getConnection();
57 | String CREATE_BALANCE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS balance_proof ( customer_id_hash BYTEA NOT NULL,\n range_proof BYTEA,\n CONSTRAINT balance_proof_pkey PRIMARY KEY (customer_id_hash)\n)WITH ( OIDS=FALSE);ALTER TABLE balance_proof OWNER TO USER";
58 | PreparedStatement createBalanceStatement = connection.prepareStatement(CREATE_BALANCE_TABLE_SQL);
59 | createBalanceStatement.execute();
60 | String CREATE_BALANCE_SECRETS_TABLE_SQL = "CREATE TABLE IF NOT EXISTS balance_proof_secrets\n(\n customer_id CHARACTER VARYING(9) NOT NULL,\n hash_salt BYTEA,\n balance_salt BYTEA,\n CONSTRAINT balance_proof_secrets_pkey PRIMARY KEY (customer_id),\n CONSTRAINT balance_proof_secrets_customer_id_fkey FOREIGN KEY (customer_id)\n REFERENCES customer_balance (customer_id) MATCH SIMPLE\n ON UPDATE CASCADE ON DELETE CASCADE\n)\nWITH (\n OIDS=FALSE\n);\nALTER TABLE balance_proof_secrets\n OWNER TO USER;";
61 | PreparedStatement createBalanceSecretsTable = connection.prepareStatement(CREATE_BALANCE_SECRETS_TABLE_SQL);
62 | createBalanceSecretsTable.execute();
63 | String CREATE_CUSTOMER_BALANCE = "CREATE TABLE IF NOT EXISTS customer_balance\n(\n customer_id CHARACTER VARYING(9) NOT NULL,\n balance BIGINT,\n CONSTRAINT customer_balance_pkey PRIMARY KEY (customer_id)\n)\nWITH (\n OIDS=FALSE\n);\nALTER TABLE customer_balance\n OWNER TO USER;\n";
64 | PreparedStatement createCustomerBalance = connection.prepareStatement(CREATE_CUSTOMER_BALANCE);
65 | createCustomerBalance.execute();
66 | String CREATE_ASSETS_TABLE_SQL = "CREATE TABLE IF NOT EXISTS assets_proof(hash_salt BYTEA,balance_salt BYTEA);";
67 | PreparedStatement createAssetsTable = connection.prepareStatement(CREATE_ASSETS_TABLE_SQL);
68 | createAssetsTable.execute();
69 | String CREATE_BLOCKCHAIN_SQL = "CREATE TABLE IF NOT EXISTS blockchain\n(\n pubkey BYTEA NOT NULL,\n balance BIGINT,\n CONSTRAINT blockchain_pkey PRIMARY KEY (pubkey)\n)\nWITH (\n OIDS=FALSE\n);\nALTER TABLE blockchain\n OWNER TO USER;";
70 | PreparedStatement createBlockchain = connection.prepareStatement(CREATE_BLOCKCHAIN_SQL);
71 | createBlockchain.execute();
72 | String CREATE_ASSET_PROOF_SQL = "CREATE TABLE IF NOT EXISTS asset_proof\n(\n public_key BYTEA NOT NULL,\n main_proof BYTEA,\n binary_proof BYTEA,\n CONSTRAINT asset_proof_pkey PRIMARY KEY (public_key),\n CONSTRAINT asset_proof_public_key_fkey FOREIGN KEY (public_key)\n REFERENCES blockchain (public_key) MATCH SIMPLE\n ON UPDATE NO ACTION ON DELETE NO ACTION\n)\nWITH (\n OIDS=FALSE\n);\nALTER TABLE asset_proof\n OWNER TO USER;\n";
73 | PreparedStatement createAssetProof = connection.prepareStatement(CREATE_ASSET_PROOF_SQL);
74 | createAssetProof.execute();
75 | String CREATE_ASSET_PROOF_SECRETS_SQL = "CREATE TABLE IF NOT EXISTS asset_proof_secrets \n(\n public_key BYTEA NOT NULL,\n private_key BYTEA,\n CONSTRAINT asset_proof_secrets_pkey PRIMARY KEY (public_key),\n CONSTRAINT asset_proof_secrets_public_key_fkey FOREIGN KEY (public_key)\n REFERENCES blockchain (public_key) MATCH SIMPLE\n ON UPDATE NO ACTION ON DELETE NO ACTION\n)\nWITH (\n OIDS=FALSE\n);\nALTER TABLE asset_proof_secrets\n OWNER TO USER;\n";
76 | PreparedStatement createAssetProofSecrets = connection.prepareStatement(CREATE_ASSET_PROOF_SECRETS_SQL);
77 | createAssetProofSecrets.execute();
78 | connection.close();
79 | }
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AssetProofSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.ProofUtils;
8 | import edu.stanford.crypto.bitcoin.BlockchainEntry;
9 | import edu.stanford.crypto.bitcoin.PrivateKeyDatabase;
10 | import edu.stanford.crypto.bitcoin.SQLBlockchain;
11 | import edu.stanford.crypto.bitcoin.SQLPrivateKeyDatabase;
12 | import edu.stanford.crypto.proof.ProofSystem;
13 | import edu.stanford.crypto.proof.binary.BinaryProof;
14 | import edu.stanford.crypto.proof.binary.BinaryProofData;
15 | import edu.stanford.crypto.proof.binary.BinaryProofSystem;
16 | import org.apache.logging.log4j.LogManager;
17 | import org.apache.logging.log4j.Logger;
18 | import org.apache.logging.log4j.Marker;
19 | import org.bouncycastle.math.ec.ECPoint;
20 |
21 | import java.math.BigInteger;
22 | import java.sql.SQLException;
23 | import java.util.Iterator;
24 | import java.util.Optional;
25 | import java.util.concurrent.*;
26 | import java.util.stream.Stream;
27 |
28 | public class AssetProofSystem
29 | implements ProofSystem {
30 | private static final Logger LOGGER = LogManager.getLogger();
31 | private final AddressProofSystem addressProofSystem = new AddressProofSystem();
32 | private final BlockingQueue blockchainEntriesQueue = new ArrayBlockingQueue<>(Runtime.getRuntime().availableProcessors() * 3);
33 | private final BinaryProofSystem binaryProofSystem = new BinaryProofSystem();
34 |
35 | /*
36 | * Enabled aggressive block sorting
37 | * Enabled unnecessary exception pruning
38 | * Enabled aggressive exception aggregation
39 | */
40 | @Override
41 | public AssetProof createProof(AssetProofData data) {
42 | try {
43 | SQLBlockchain blockchain = new SQLBlockchain();
44 | SQLPrivateKeyDatabase privateKeyDatabase = new SQLPrivateKeyDatabase();
45 | try {
46 | AssetProof proof;
47 | ExecutorService executorService;
48 | Iterator blockchainEntries = blockchain.getBlockchainEntries();
49 | proof = new AssetProof();
50 | int nThreads = Runtime.getRuntime().availableProcessors() - 1;
51 | executorService = Executors.newFixedThreadPool(nThreads);
52 | proof.getConnection().setAutoCommit(false);
53 | Stream.generate(AddressProofWorkerThread::new).limit(nThreads).forEach(executorService::submit);
54 | BlockchainEntry blockchainEntry;
55 | while (blockchainEntries.hasNext()) {
56 | blockchainEntry = blockchainEntries.next();
57 | if (this.blockchainEntriesQueue.offer(blockchainEntry)) continue;
58 | this.createAddressProof(blockchainEntry, proof, privateKeyDatabase);
59 | }
60 | while ((blockchainEntry = this.blockchainEntriesQueue.poll()) != null) {
61 | this.createAddressProof(blockchainEntry, proof, privateKeyDatabase);
62 | }
63 |
64 | executorService.shutdownNow();
65 | executorService.awaitTermination(1, TimeUnit.MINUTES);
66 | proof.getConnection().setAutoCommit(true);
67 | return proof;
68 | } finally {
69 | privateKeyDatabase.close();
70 | blockchain.close();
71 | }
72 | } catch (SQLException | InterruptedException e) {
73 | LOGGER.error("Exception while running asset proof", e);
74 | throw new IllegalArgumentException("Couldn't complete proof");
75 | }
76 | }
77 |
78 | private void createAddressProof(BlockchainEntry blockchainEntry, AssetProof proof, PrivateKeyDatabase privateKeyDatabase) {
79 | BigInteger balanceRandomness = ProofUtils.randomNumber();
80 | BigInteger keyKnownRandomness = ProofUtils.randomNumber();
81 | ECPoint pubKey = blockchainEntry.getPubKey();
82 | Optional privateKey = privateKeyDatabase.retrievePrivateKey(pubKey);
83 | AddressProofData addressProofData = new AddressProofData(privateKey, pubKey, blockchainEntry.getBalance(), balanceRandomness, keyKnownRandomness, ECConstants.G, ECConstants.H);
84 | AddressProof addressProof = this.addressProofSystem.createProof(addressProofData);
85 |
86 | proof.addAddressProof(pubKey, addressProof);
87 | }
88 |
89 | private class AddressProofWorkerThread
90 | implements Runnable {
91 | private AddressProofWorkerThread() {
92 | }
93 |
94 | @Override
95 | public void run() {
96 | try (AssetProof assetProof = new AssetProof()) {
97 | try (SQLPrivateKeyDatabase database = new SQLPrivateKeyDatabase()) {
98 | while (!Thread.interrupted()) {
99 | try {
100 | BlockchainEntry entry = AssetProofSystem.this.blockchainEntriesQueue.take();
101 | AssetProofSystem.this.createAddressProof(entry, assetProof, database);
102 | } catch (InterruptedException e) {
103 | // empty catch block
104 | break;
105 | }
106 | }
107 |
108 |
109 | }
110 | } catch (SQLException e) {
111 | e.printStackTrace();
112 | throw new RuntimeException(e);
113 | }
114 | }
115 | }
116 |
117 | }
118 |
119 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/balance/BalanceProofSystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.balance;
5 |
6 | import edu.stanford.crypto.ProofUtils;
7 | import edu.stanford.crypto.bitcoin.CustomerSecretsDatabase;
8 | import edu.stanford.crypto.bitcoin.SQLCustomerDatabase;
9 | import edu.stanford.crypto.bitcoin.SQLCustomerSecretsDatabase;
10 | import edu.stanford.crypto.proof.ProofSystem;
11 | import edu.stanford.crypto.proof.RangeProofData;
12 | import edu.stanford.crypto.proof.binary.BinaryRangeProof;
13 | import edu.stanford.crypto.proof.rangeproof.BinaryRangeProofSystem;
14 |
15 | import java.math.BigInteger;
16 | import java.sql.SQLException;
17 | import java.util.Iterator;
18 | import java.util.List;
19 | import java.util.concurrent.*;
20 | import java.util.concurrent.atomic.AtomicReference;
21 | import java.util.stream.Collectors;
22 | import java.util.stream.Stream;
23 |
24 | public class BalanceProofSystem
25 | implements ProofSystem {
26 | private final BinaryRangeProofSystem rangeProofSystem = new BinaryRangeProofSystem();
27 | private final BlockingQueue customerInfos = new ArrayBlockingQueue(Runtime.getRuntime().availableProcessors() * 3);
28 | private final AtomicReference balanceKey = new AtomicReference(BigInteger.ZERO);
29 |
30 | /*
31 | * Enabled aggressive block sorting
32 | * Enabled unnecessary exception pruning
33 | * Enabled aggressive exception aggregation
34 | */
35 | @Override
36 | public BalanceProof createProof(BalanceProofData data) {
37 | try (SQLCustomerDatabase customerSecretsDatabase = new SQLCustomerDatabase()) {
38 | BalanceProof proof;
39 | ExecutorService executorService;
40 | Iterator customerInfoIterator = customerSecretsDatabase.getCustomers();
41 | proof = new BalanceProof();
42 | int nThreads = Runtime.getRuntime().availableProcessors() - 1;
43 | executorService = Executors.newFixedThreadPool(nThreads);
44 | proof.getConnection().setAutoCommit(false);
45 | Stream.generate(() -> new RangeProofWorkerThread(data.getMaxBits())).limit(nThreads).forEach(executorService::submit);
46 | try (SQLCustomerSecretsDatabase database2 = new SQLCustomerSecretsDatabase()) {
47 | CustomerInfo info;
48 | while (customerInfoIterator.hasNext()) {
49 | CustomerInfo customerInfo = customerInfoIterator.next();
50 | if (this.customerInfos.offer(customerInfo)) continue;
51 | this.createRangeProof(customerInfo, proof, database2, data.getMaxBits());
52 | }
53 | while ((info = this.customerInfos.poll()) != null) {
54 | this.createRangeProof(info, proof, database2, data.getMaxBits());
55 | }
56 | }
57 | executorService.shutdownNow();
58 | executorService.awaitTermination(1, TimeUnit.MINUTES);
59 | proof.getConnection().setAutoCommit(true);
60 | return proof;
61 |
62 | } catch (SQLException e) {
63 | e.printStackTrace();
64 | throw new IllegalArgumentException("Couldn't complete proof");
65 | } catch (InterruptedException e) {
66 | e.printStackTrace();
67 | }
68 | throw new IllegalArgumentException("Couldn't complete proof");
69 | }
70 |
71 | public BigInteger getBalanceKey() {
72 | return this.balanceKey.get();
73 | }
74 |
75 | private void createRangeProof(CustomerInfo customerInfo, BalanceProof proof, CustomerSecretsDatabase database, int maxBits) {
76 | List randomness = Stream.generate(ProofUtils::randomNumber).limit(maxBits).collect(Collectors.toList());
77 | BigInteger totalRandomness = BigInteger.ZERO;
78 | for (int i = 0; i < randomness.size(); ++i) {
79 | totalRandomness = totalRandomness.add(randomness.get(i).shiftLeft(i));
80 | }
81 | this.balanceKey.accumulateAndGet(totalRandomness, BigInteger::add);
82 | RangeProofData rangeProofData = new RangeProofData(customerInfo.getBalance(), randomness);
83 | BinaryRangeProof rangeProof = this.rangeProofSystem.createProof(rangeProofData);
84 | BigInteger hashSalt = ProofUtils.randomNumber();
85 | BigInteger hashedId = ProofUtils.hash(customerInfo.getId(), hashSalt);
86 | proof.addCustomer(hashedId, rangeProof);
87 | database.store(customerInfo.getId(), hashSalt, rangeProofData.getTotalRandomness());
88 | }
89 |
90 | private class RangeProofWorkerThread
91 | implements Runnable {
92 | private final int maxBits;
93 |
94 | private RangeProofWorkerThread(int maxBits) {
95 | this.maxBits = maxBits;
96 | }
97 |
98 | @Override
99 | public void run() {
100 | try (BalanceProof balanceProof = new BalanceProof()) {
101 | try (SQLCustomerSecretsDatabase database = new SQLCustomerSecretsDatabase()) {
102 |
103 | while (!Thread.interrupted()) {
104 | try {
105 | CustomerInfo info = BalanceProofSystem.this.customerInfos.take();
106 | BalanceProofSystem.this.createRangeProof(info, balanceProof, database, this.maxBits);
107 | } catch (InterruptedException e) {
108 | // empty catch block
109 | break;
110 | }
111 | }
112 |
113 | }
114 | } catch (SQLException e) {
115 | e.printStackTrace();
116 | }
117 | }
118 | }
119 |
120 | }
121 |
122 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/proof/assets/AddressProof.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.proof.assets;
5 |
6 | import edu.stanford.crypto.ECConstants;
7 | import edu.stanford.crypto.proof.MemoryProof;
8 | import org.bouncycastle.math.ec.ECPoint;
9 |
10 | import java.math.BigInteger;
11 | import java.util.Arrays;
12 | import java.util.List;
13 |
14 | public class AddressProof
15 | implements MemoryProof {
16 | private final ECPoint commitmentBalance;
17 | private final ECPoint commitmentXHat;
18 | private final BigInteger challengeZero;
19 | private final BigInteger challengeOne;
20 |
21 | private final BigInteger responseS;
22 | private final BigInteger responseV;
23 | private final BigInteger responseT;
24 | private final BigInteger responseXHat;
25 | private final BigInteger responseZero;
26 | private final BigInteger responseOne;
27 |
28 | public AddressProof(ECPoint commitmentBalance, ECPoint commitmentXHat, BigInteger challengeZero, BigInteger challengeOne, BigInteger responseS, BigInteger responseV, BigInteger responseT, BigInteger responseXHat, BigInteger responseZero, BigInteger responseOne) {
29 | this.commitmentBalance = commitmentBalance;
30 | this.commitmentXHat = commitmentXHat;
31 | this.challengeZero = challengeZero;
32 | this.challengeOne = challengeOne;
33 | this.responseS = responseS;
34 | this.responseV = responseV;
35 | this.responseT = responseT;
36 | this.responseXHat = responseXHat;
37 | this.responseZero = responseZero;
38 | this.responseOne = responseOne;
39 | }
40 |
41 | public AddressProof(byte[] array) {
42 | int index = 0;
43 | byte statementLength = array[index++];
44 | this.commitmentBalance = ECConstants.BITCOIN_CURVE.decodePoint(Arrays.copyOfRange(array, index, statementLength + index));
45 | index += statementLength;
46 | statementLength = array[index++];
47 | this.commitmentXHat = ECConstants.BITCOIN_CURVE.decodePoint(Arrays.copyOfRange(array, index, statementLength + index));
48 | index += statementLength;
49 | statementLength = array[index++];
50 | this.challengeZero = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
51 | index += statementLength;
52 | statementLength = array[index++];
53 | this.challengeOne = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
54 | index += statementLength;
55 | statementLength = array[index++];
56 | this.responseS = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
57 | index += statementLength;
58 | statementLength = array[index++];
59 | this.responseT = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
60 | index += statementLength;
61 | statementLength = array[index++];
62 | this.responseV = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
63 | index += statementLength;
64 | statementLength = array[index++];
65 | this.responseXHat = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
66 | index += statementLength;
67 | statementLength = array[index++];
68 | this.responseZero = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
69 | index += statementLength;
70 | statementLength = array[index++];
71 | this.responseOne = new BigInteger(Arrays.copyOfRange(array, index, statementLength + index));
72 | }
73 |
74 | @Override
75 | public byte[] serialize() {
76 | byte[] commitmentBalanceEncoded = this.commitmentBalance.getEncoded(true);
77 | byte[] commitmentXHatEncoded = this.commitmentXHat.getEncoded(true);
78 | byte[] challengeZeroEncoded = this.challengeZero.toByteArray();
79 | byte[] challengeOneEncoded = this.challengeOne.toByteArray();
80 |
81 | byte[] responseSEncoded = this.responseS.toByteArray();
82 | byte[] responseTEncoded = this.responseT.toByteArray();
83 | byte[] responseVEncoded = this.responseV.toByteArray();
84 | byte[] responseXHatEncoded = this.responseXHat.toByteArray();
85 | byte[] responseZeroEncoded = this.responseZero.toByteArray();
86 | byte[] responseOneEncoded = this.responseOne.toByteArray();
87 |
88 | List arrList = Arrays.asList(commitmentBalanceEncoded, commitmentXHatEncoded, challengeZeroEncoded, challengeOneEncoded,responseSEncoded, responseTEncoded, responseVEncoded, responseXHatEncoded, responseZeroEncoded, responseOneEncoded);
89 | int totalLength = arrList.stream().mapToInt(arr -> arr.length).map(i -> i + 1).sum();
90 | byte[] fullArray = new byte[totalLength];
91 | int currIndex = 0;
92 | for (byte[] arr2 : arrList) {
93 | fullArray[currIndex++] = (byte) arr2.length;
94 | System.arraycopy(arr2, 0, fullArray, currIndex, arr2.length);
95 | currIndex += arr2.length;
96 | }
97 | return fullArray;
98 | }
99 |
100 | public BigInteger getChallengeZero() {
101 | return this.challengeZero;
102 | }
103 |
104 | public BigInteger getChallengeOne() {
105 | return challengeOne;
106 | }
107 |
108 | public BigInteger getResponseS() {
109 | return this.responseS;
110 | }
111 |
112 | public ECPoint getCommitmentBalance() {
113 | return this.commitmentBalance;
114 | }
115 |
116 | public ECPoint getCommitmentXHat() {
117 | return this.commitmentXHat;
118 | }
119 |
120 | public BigInteger getResponseV() {
121 | return this.responseV;
122 | }
123 |
124 | public BigInteger getResponseT() {
125 | return this.responseT;
126 | }
127 |
128 | public BigInteger getResponseXHat() {
129 | return this.responseXHat;
130 | }
131 |
132 | public BigInteger getResponseZero() {
133 | return responseZero;
134 | }
135 |
136 | public BigInteger getResponseOne() {
137 | return responseOne;
138 | }
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/src/main/java/edu/stanford/crypto/experiments/BalanceProofExperiment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Decompiled with CFR 0_110.
3 | */
4 | package edu.stanford.crypto.experiments;
5 |
6 | import edu.stanford.crypto.ExperimentUtils;
7 | import edu.stanford.crypto.bitcoin.SQLCustomerDatabase;
8 | import edu.stanford.crypto.bitcoin.SQLCustomerSecretsDatabase;
9 | import edu.stanford.crypto.database.Database;
10 | import edu.stanford.crypto.proof.balance.BalanceProof;
11 | import edu.stanford.crypto.proof.balance.BalanceProofData;
12 | import edu.stanford.crypto.proof.balance.BalanceProofSystem;
13 | import edu.stanford.crypto.proof.balance.CustomerSecrets;
14 | import edu.stanford.crypto.verification.BalanceVerificationData;
15 | import edu.stanford.crypto.verification.BalanceVerifier;
16 | import edu.stanford.crypto.verification.ParticipationData;
17 | import edu.stanford.crypto.verification.ParticipationVerifier;
18 |
19 | import java.io.IOException;
20 | import java.io.OutputStream;
21 | import java.math.BigInteger;
22 | import java.nio.file.Files;
23 | import java.nio.file.OpenOption;
24 | import java.nio.file.Path;
25 | import java.nio.file.Paths;
26 | import java.sql.SQLException;
27 |
28 | public class BalanceProofExperiment {
29 | public static void main(String[] args) throws IOException, SQLException {
30 | Path outputFile = Paths.get(args[0], new String[0]);
31 | OutputStream stream = Files.newOutputStream(outputFile, new OpenOption[0]);
32 | Throwable throwable = null;
33 | try {
34 | stream.write("Bits;Customers;Proof Time;Verify time;Participation verify;File size\n".getBytes());
35 | int[] numberOfCustomers = new int[]{100, 200000, 2000000};
36 | int[] numberOfBits = new int[]{51};
37 | BalanceProofSystem proofSystem = new BalanceProofSystem();
38 | BalanceVerifier verifier = new BalanceVerifier();
39 | ParticipationVerifier participationVerifier = new ParticipationVerifier();
40 | for (int customers : numberOfCustomers) {
41 | for (int bits : numberOfBits) {
42 | long startClearing = System.currentTimeMillis();
43 | System.out.println("Starting to clear proofs ");
44 | Database.clearProofs();
45 | long endClearing = System.currentTimeMillis();
46 | System.out.println("Took " + (double)(endClearing - startClearing) / 1000.0 + "s");
47 | ExperimentUtils.generateRandomCustomers(customers, bits);
48 | long endCreating = System.currentTimeMillis();
49 | System.out.println("Took " + (double)(endCreating - endClearing) / 1000.0 + "s to create customers");
50 | BalanceProofData data = new BalanceProofData(bits);
51 | long startProof = System.currentTimeMillis();
52 | BalanceProof proof = proofSystem.createProof(data);
53 | long endProof = System.currentTimeMillis();
54 | System.out.println("Finished balance proof in " + (endProof - startProof) / 1000 + "s");
55 | verifier.verify(proof, new BalanceVerificationData(bits));
56 | long endVerifyFull = System.currentTimeMillis();
57 | System.out.println("Finished verification in " + (endVerifyFull - endProof) / 1000 + "s");
58 | String customer = "C0";
59 | SQLCustomerDatabase customerDatabase = new SQLCustomerDatabase();
60 | Throwable throwable2 = null;
61 | try {
62 | SQLCustomerSecretsDatabase secretsDatabase = new SQLCustomerSecretsDatabase();
63 | Throwable throwable3 = null;
64 | try {
65 | CustomerSecrets secrets = secretsDatabase.retrieve(customer);
66 | BigInteger balance = customerDatabase.getBalance(customer);
67 | ParticipationData participationData = new ParticipationData(customer, secrets, balance);
68 | participationVerifier.verify(proof, participationData);
69 | }
70 | catch (Throwable secrets) {
71 | throwable3 = secrets;
72 | throw secrets;
73 | }
74 | finally {
75 | if (secretsDatabase != null) {
76 | if (throwable3 != null) {
77 | try {
78 | secretsDatabase.close();
79 | }
80 | catch (Throwable secrets) {
81 | throwable3.addSuppressed(secrets);
82 | }
83 | } else {
84 | secretsDatabase.close();
85 | }
86 | }
87 | }
88 | }
89 | catch (Throwable secretsDatabase) {
90 | throwable2 = secretsDatabase;
91 | throw secretsDatabase;
92 | }
93 | finally {
94 | if (customerDatabase != null) {
95 | if (throwable2 != null) {
96 | try {
97 | customerDatabase.close();
98 | }
99 | catch (Throwable secretsDatabase) {
100 | throwable2.addSuppressed(secretsDatabase);
101 | }
102 | } else {
103 | customerDatabase.close();
104 | }
105 | }
106 | }
107 | long endVerifyParticipation = System.currentTimeMillis();
108 | stream.write(("" + bits + ";" + customers + ";" + (endProof - startProof) + ";" + (endVerifyFull - endProof) + ";" + (endVerifyParticipation - endVerifyFull) + ";" + proof.getSizeInfo() + "\n").getBytes());
109 | stream.flush();
110 | proof.close();
111 | System.out.println("Connections closed");
112 | }
113 | }
114 | }
115 | catch (Throwable numberOfCustomers) {
116 | throwable = numberOfCustomers;
117 | throw numberOfCustomers;
118 | }
119 | finally {
120 | if (stream != null) {
121 | if (throwable != null) {
122 | try {
123 | stream.close();
124 | }
125 | catch (Throwable numberOfCustomers) {
126 | throwable.addSuppressed(numberOfCustomers);
127 | }
128 | } else {
129 | stream.close();
130 | }
131 | }
132 | }
133 | System.out.println("Proof Sucess");
134 | }
135 | }
136 |
137 |
--------------------------------------------------------------------------------