Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2013-05-25 04:48:27 +0400
committerDavid Hook <dgh@cryptoworkshop.com>2013-05-25 04:48:27 +0400
commitca3db90c40693e8bff67671539d00e208ce9cba1 (patch)
tree17482b18aabb16340c1c56cd27e96035c256adc1
parentca0c5ea98037cc3dc99a7315ddc7adc3b7023169 (diff)
added first commitment implementation
-rw-r--r--src/main/java/org/bouncycastle/crypto/Commitment.java42
-rw-r--r--src/main/java/org/bouncycastle/crypto/Committer.java24
-rw-r--r--src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java81
-rw-r--r--src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java64
-rw-r--r--src/test/java/org/bouncycastle/crypto/test/RegressionTest.java3
5 files changed, 213 insertions, 1 deletions
diff --git a/src/main/java/org/bouncycastle/crypto/Commitment.java b/src/main/java/org/bouncycastle/crypto/Commitment.java
new file mode 100644
index 00000000..f1dc05a3
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/Commitment.java
@@ -0,0 +1,42 @@
+package org.bouncycastle.crypto;
+
+/**
+ * General holding class for a commitment.
+ */
+public class Commitment
+{
+ private final byte[] secret;
+ private final byte[] commitment;
+
+ /**
+ * Base constructor.
+ *
+ * @param secret an encoding of the secret required to reveal the commitment.
+ * @param commitment an encoding of the sealed commitment.
+ */
+ public Commitment(byte[] secret, byte[] commitment)
+ {
+ this.secret = secret;
+ this.commitment = commitment;
+ }
+
+ /**
+ * The secret required to reveal the commitment.
+ *
+ * @return an encoding of the secret associated with the commitment.
+ */
+ public byte[] getSecret()
+ {
+ return secret;
+ }
+
+ /**
+ * The sealed commitment.
+ *
+ * @return an encoding of the sealed commitment.
+ */
+ public byte[] getCommitment()
+ {
+ return commitment;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/Committer.java b/src/main/java/org/bouncycastle/crypto/Committer.java
new file mode 100644
index 00000000..5c93e5d1
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/Committer.java
@@ -0,0 +1,24 @@
+package org.bouncycastle.crypto;
+
+/**
+ * General interface fdr classes that produce and validate commitments.
+ */
+public interface Committer
+{
+ /**
+ * Generate a commitment for the passed in message.
+ *
+ * @param message the message to be committed to,
+ * @return a Commitment
+ */
+ Commitment commit(byte[] message);
+
+ /**
+ * Return true if the passed in commitment represents a commitment to the passed in maessage.
+ *
+ * @param commitment a commitment previously generated.
+ * @param message the message that was expected to have been committed to.
+ * @return true if commitment matches message, false otherwise.
+ */
+ boolean isRevealed(Commitment commitment, byte[] message);
+}
diff --git a/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java b/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
new file mode 100644
index 00000000..1494c3ce
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
@@ -0,0 +1,81 @@
+package org.bouncycastle.crypto.commitments;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.Commitment;
+import org.bouncycastle.crypto.Committer;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.ExtendedDigest;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * A basic hash-committer as described in "Making Mix Nets Robust for Electronic Voting by Randomized Partial Checking",
+ * by Jakobsson, Juels, and Rivest (11th Usenix Security Symposium, 2002).
+ */
+public class HashCommitter
+ implements Committer
+{
+ private final Digest digest;
+ private final int byteLength;
+ private final SecureRandom random;
+
+ /**
+ * Base Constructor. The maximum message length that can be committed to is half the length of the internal
+ * block size for the digest (ExtendedDigest.getBlockLength()).
+ *
+ * @param digest digest to use for creating commitments.
+ * @param random source of randomness for generating secrets.
+ */
+ public HashCommitter(ExtendedDigest digest, SecureRandom random)
+ {
+ this.digest = digest;
+ this.byteLength = digest.getByteLength();
+ this.random = random;
+ }
+
+ /**
+ * Generate a commitment for the passed in message.
+ *
+ * @param message the message to be committed to,
+ * @return a Commitment
+ */
+ public Commitment commit(byte[] message)
+ {
+ if (message.length > byteLength / 2)
+ {
+ throw new DataLengthException("Message to be committed to too large for digest.");
+ }
+
+ byte[] w = new byte[byteLength - message.length];
+
+ random.nextBytes(w);
+
+ return new Commitment(w, calculateCommitment(w, message));
+ }
+
+ /**
+ * Return true if the passed in commitment represents a commitment to the passed in maessage.
+ *
+ * @param commitment a commitment previously generated.
+ * @param message the message that was expected to have been committed to.
+ * @return true if commitment matches message, false otherwise.
+ */
+ public boolean isRevealed(Commitment commitment, byte[] message)
+ {
+ byte[] calcCommitment = calculateCommitment(commitment.getSecret(), message);
+
+ return Arrays.constantTimeAreEqual(commitment.getCommitment(), calcCommitment);
+ }
+
+ private byte[] calculateCommitment(byte[] w, byte[] message)
+ {
+ byte[] commitment = new byte[digest.getDigestSize()];
+
+ digest.update(w, 0, w.length);
+ digest.update(message, 0, message.length);
+ digest.doFinal(commitment, 0);
+
+ return commitment;
+ }
+}
diff --git a/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java b/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java
new file mode 100644
index 00000000..d4bd83de
--- /dev/null
+++ b/src/test/java/org/bouncycastle/crypto/test/HashCommitmentTest.java
@@ -0,0 +1,64 @@
+package org.bouncycastle.crypto.test;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.Commitment;
+import org.bouncycastle.crypto.Committer;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.commitments.HashCommitter;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class HashCommitmentTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "HashCommitmentTest";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ byte[] data = Hex.decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+
+ Committer committer = new HashCommitter(new SHA256Digest(), new SecureRandom());
+
+ Commitment c = committer.commit(data);
+
+ committer = new HashCommitter(new SHA256Digest(), new SecureRandom());
+
+ if (!committer.isRevealed(c, data))
+ {
+ fail("commitment failed to validate");
+ }
+
+ committer = new HashCommitter(new SHA1Digest(), new SecureRandom());
+
+ if (committer.isRevealed(c, data))
+ {
+ fail("commitment validated!!");
+ }
+
+ // SHA1 has a block size of 512 bits, try a message that's too big
+
+ try
+ {
+ c = committer.commit(new byte[33]);
+ }
+ catch (DataLengthException e)
+ {
+ if (!e.getMessage().equals("Message to be committed to too large for digest."))
+ {
+ fail("exception thrown but wrong message");
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ runTest(new HashCommitmentTest());
+ }
+}
diff --git a/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java b/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java
index 906eb910..7f3732d6 100644
--- a/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java
+++ b/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java
@@ -116,7 +116,8 @@ public class RegressionTest
new OCBTest(),
new NonMemoableDigestTest(),
new RSAKeyEncapsulationTest(),
- new ECIESKeyEncapsulationTest()
+ new ECIESKeyEncapsulationTest(),
+ new HashCommitmentTest()
};
public static void main(