Common MPC Pitfalls

Fresco `HashBasedCommitment`

In the SPDZ protocol, parties hold additive shares of a global SPDZ MAC $[\alpha \cdot a]$ on every wire under a single global MAC key $\alpha$. To verify that a reconstructed value $a'$ is correct, each party computes $z_i = a' \cdot \alpha_i - (\alpha \cdot a)_i$, commits to $z_i$, and opens; if the reconstructed $z = \sum z_i \ne 0$, they abort. SPDZ also uses the same commitment scheme in coin-tossing and input-sharing subprotocols.

Fresco’s HashBasedCommitment hashed only the value and the randomness,with no opener identity in the input, allowing a malicious party to replay it. Pre-fix commit method (source):

 1// FILE: tools/commitment/src/main/java/dk/alexandra/fresco/tools/commitment/HashBasedCommitment.java
 2// aicis/fresco @ 2dc80dca (vulnerable, pre-PR #433)
 3
 4public byte[] commit(Drbg rand, byte[] value) {
 5  if (commitmentVal != null) {
 6    throw new IllegalStateException("Already committed");
 7  }
 8  // Sample a sufficient amount of random bits
 9  byte[] randomness = new byte[DIGEST_LENGTH];
10  rand.nextBytes(randomness);
11  // Construct an array to contain the bytes to hash
12  byte[] openingInfo = new byte[value.length + randomness.length];
13  System.arraycopy(value, 0, openingInfo, 0, value.length);
14  System.arraycopy(randomness, 0, openingInfo, value.length,
15      randomness.length);
16  commitmentVal = digest.digest(openingInfo);
17  return openingInfo;
18}

Each party’s commitment is $c_i = H(v_i \,\|\, r_i)$, with no opener identity in the hash input. Fresco does not implement SPDZ over binary fields, so the characteristic-2 single-MAC-check copy (where a copied $z_1$ gives $z = z_1 + z_1 = 0$) does not apply to it directly. Fresco is instead hit through the same commitment’s use in coin-tossing: a corrupt party copies an honest party’s seed commitment $H(s_i \,\|\, r_i)$ byte-for-byte and later copies the opening $(s_i, r_i)$, so the two identical seeds cancel in the XOR $s = s_1 \oplus \cdots \oplus s_n$. This strips the honest party’s entropy from the tossed coin, making it adversarially predictable and letting the corrupt party pass the batch MAC check on inconsistent values. The fix (PR #433) added the committer’s party ID as the first input to the hash and required the opener to supply a matching ID at open time (source):

 1// FILE: tools/commitment/src/main/java/dk/alexandra/fresco/tools/commitment/HashBasedCommitment.java
 2// aicis/fresco @ fdada93b (fixed)
 3
 4public byte[] commit(int myId, Drbg rand, byte[] value) {
 5  if (commitmentVal != null) {
 6    throw new IllegalStateException("Already committed");
 7  }
 8  byte[] randomness = new byte[DIGEST_LENGTH];
 9  rand.nextBytes(randomness);
10  // Party ID is now the first ID_LENGTH bytes of the hashed input.
11  byte[] openingInfo = new byte[ID_LENGTH + value.length + randomness.length];
12  System.arraycopy(integerToBytes(myId), 0, openingInfo, 0, ID_LENGTH);
13  System.arraycopy(value, 0, openingInfo, ID_LENGTH, value.length);
14  System.arraycopy(randomness, 0, openingInfo, value.length + ID_LENGTH,
15      randomness.length);
16  commitmentVal = digest.digest(openingInfo);
17  return openingInfo;
18}