Skip to content

Commit

Permalink
include sender ethereum address in signed data
Browse files Browse the repository at this point in the history
  • Loading branch information
dtebbs committed Feb 18, 2020
1 parent a2ce0e3 commit 8485e1b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 24 deletions.
48 changes: 26 additions & 22 deletions pyClient/test_commands/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,11 @@ def compute_h_sig_attack_nf(

# Compute the joinSplit signature
joinsplit_sig = joinsplit.joinsplit_sign(
signing_keypair, sender_eph_pk, ciphertexts, proof_json)
signing_keypair,
charlie_eth_address,
sender_eph_pk,
ciphertexts,
proof_json)

tx_hash = zeth_client.mix(
sender_eph_pk,
Expand Down Expand Up @@ -327,14 +331,6 @@ def charlie_corrupt_bob_deposit(
(output_note1, pk_bob),
(output_note2, pk_bob)])

# Sign the primary inputs, pk_sender and the ciphertexts
joinsplit_sig = joinsplit.joinsplit_sign(
joinsplit_keypair,
pk_sender,
ciphertexts,
proof_json
)

# ### ATTACK BLOCK
# Charlie intercepts Bob's deposit, corrupts it and
# sends her transaction before Bob's transaction is accepted
Expand All @@ -347,16 +343,20 @@ def charlie_corrupt_bob_deposit(

result_corrupt1 = None
try:
joinsplit_sig_charlie = joinsplit.joinsplit_sign(
joinsplit_keypair,
charlie_eth_address,
pk_sender,
ciphertexts,
proof_json)
tx_hash = zeth_client.mix(
pk_sender,
fake_ciphertext0,
fake_ciphertext1,
proof_json,
joinsplit_keypair.vk,
joinsplit_sig,
joinsplit_sig_charlie,
charlie_eth_address,
# Pay an arbitrary amount (1 wei here) that will be refunded
# since the `mix` function is payable
Web3.toWei(BOB_DEPOSIT_ETH, 'ether'),
4000000)
result_corrupt1 = \
Expand All @@ -378,25 +378,23 @@ def charlie_corrupt_bob_deposit(
new_joinsplit_keypair = signing.gen_signing_keypair()

# Sign the primary inputs, pk_sender and the ciphertexts
new_joinsplit_sig = joinsplit.joinsplit_sign(
new_joinsplit_keypair,
pk_sender,
[fake_ciphertext0, fake_ciphertext1],
proof_json
)

result_corrupt2 = None
try:
joinsplit_sig_charlie = joinsplit.joinsplit_sign(
new_joinsplit_keypair,
charlie_eth_address,
pk_sender,
[fake_ciphertext0, fake_ciphertext1],
proof_json)
tx_hash = zeth_client.mix(
pk_sender,
fake_ciphertext0,
fake_ciphertext1,
proof_json,
new_joinsplit_keypair.vk,
new_joinsplit_sig,
joinsplit_sig_charlie,
charlie_eth_address,
# Pay an arbitrary amount (1 wei here) that will be refunded since the
# `mix` function is payable
Web3.toWei(BOB_DEPOSIT_ETH, 'ether'),
4000000)
result_corrupt2 = \
Expand All @@ -412,13 +410,19 @@ def charlie_corrupt_bob_deposit(
# ### ATTACK BLOCK

# Bob transaction is finally mined
joinsplit_sig_bob = joinsplit.joinsplit_sign(
joinsplit_keypair,
bob_eth_address,
pk_sender,
ciphertexts,
proof_json)
tx_hash = zeth_client.mix(
pk_sender,
ciphertexts[0],
ciphertexts[1],
proof_json,
joinsplit_keypair.vk,
joinsplit_sig,
joinsplit_sig_bob,
bob_eth_address,
Web3.toWei(BOB_DEPOSIT_ETH, 'ether'),
4000000)
Expand Down
14 changes: 12 additions & 2 deletions pyClient/zeth/joinsplit.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from zeth.zksnark import IZKSnarkProvider, GenericProof, GenericVerificationKey
from zeth.utils import EtherValue, get_trusted_setup_dir, \
hex_digest_to_binary_string, digest_to_binary_string, encrypt, \
decrypt, int64_to_hex, encode_message_to_bytes
decrypt, int64_to_hex, encode_message_to_bytes, encode_eth_address
from zeth.prover_client import ProverClient
from api.util_pb2 import ZethNote, JoinsplitInput
import api.prover_pb2 as prover_pb2
Expand Down Expand Up @@ -538,7 +538,11 @@ def joinsplit(

# Sign
signature = joinsplit_sign(
signing_keypair, sender_eph_pk, ciphertexts, proof_json)
signing_keypair,
sender_eth_address,
sender_eph_pk,
ciphertexts,
proof_json)

# By default transfer exactly v_in, otherwise allow caller to manually
# specify.
Expand Down Expand Up @@ -684,6 +688,7 @@ def _encode_proof_and_inputs(proof_json: GenericProof) -> Tuple[bytes, bytes]:

def joinsplit_sign(
signing_keypair: JoinsplitSigKeyPair,
sender_eth_address: str,
sender_eph_pk: EncryptionPublicKey,
ciphertexts: List[bytes],
proof_json: GenericProof,
Expand All @@ -697,12 +702,17 @@ def joinsplit_sign(
"""
assert len(ciphertexts) == constants.JS_INPUTS

sender_eth_addr_bytes = encode_eth_address(sender_eth_address)
print(f"sender_eth_addr_bytes = {sender_eth_addr_bytes.hex()}")

# The message to sign consists of (in order):
# - senders Ethereum address
# - senders public encryption key
# - ciphertexts
# - proof elements
# - public input elements
h = sha256()
h.update(encode_eth_address(sender_eth_address))
h.update(encode_encryption_public_key(sender_eph_pk))
for ciphertext in ciphertexts:
h.update(ciphertext)
Expand Down
8 changes: 8 additions & 0 deletions pyClient/zeth/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ def encode_abi(type_names: List[str], data: List[bytes]) -> bytes:
return eth_abi.encode_abi(type_names, data) # type: ignore


def encode_eth_address(eth_addr: str) -> bytes:
"""
Binary encoding of ethereum address to 32 bytes
"""
# Strip the leading '0x' and hex-decode.
return extend_32bytes(bytes.fromhex(eth_addr[2:]))


def encode_g1_to_bytes(group_el: G1) -> bytes:
"""
Encode a group element into a byte string
Expand Down
1 change: 1 addition & 0 deletions zeth-contracts/contracts/Groth16Mixer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ contract Groth16Mixer is BaseMixer {
// 2.a Verify the signature on the hash of data_to_be_signed
bytes32 hash_to_be_signed = sha256(
abi.encodePacked(
uint256(msg.sender),
pk_sender,
ciphertext0,
ciphertext1,
Expand Down

0 comments on commit 8485e1b

Please sign in to comment.