mta¶
Multiplicative-to-Additive (MtA) Share Conversion for DKLS23
type: share conversion
setting: Elliptic Curve DDH-hard group
assumption: DDH + OT security
MtA converts multiplicative shares (a, b) where two parties hold a and b to additive shares (alpha, beta) such that a*b = alpha + beta (mod q). Neither party learns the other’s share.
- Authors:
Elton de Souza
- Date:
01/2026
Bases:
objectCorrelated Oblivious Transfer for MtA.
Generates correlated random values for OT-based MtA. For each bit of the sender’s input, generates correlation pairs.
- class mta.MtA(groupObj: Any)[source]¶
Bases:
objectMultiplicative-to-Additive share conversion using OT.
Converts multiplicative shares (a, b) where parties hold a and b to additive shares (alpha, beta) where a*b = alpha + beta (mod q).
Curve Agnostic¶
This implementation supports any elliptic curve group that is DDH-hard. The curve is specified via the groupObj parameter.
The protocol works as follows: 1. Sender (holding a) decomposes a into bits 2. For each bit position i, run correlated OT with correlation 2^i * b 3. Receiver (holding b) chooses based on sender’s bits 4. Parties compute their additive shares from OT outputs
>>> from charm.toolbox.eccurve import secp256k1 >>> group = ECGroup(secp256k1) >>> # Create separate instances for Alice (sender) and Bob (receiver) >>> alice_mta = MtA(group) >>> bob_mta = MtA(group) >>> # Alice has share a, Bob has share b >>> a = group.random(ZR) >>> b = group.random(ZR) >>> # Convert to additive shares using the protocol with real OT >>> sender_msg = alice_mta.sender_round1(a) >>> receiver_msg, _ = bob_mta.receiver_round1(b, sender_msg) >>> alpha, ot_data = alice_mta.sender_round2(receiver_msg) >>> beta = bob_mta.receiver_round2(ot_data) >>> # Verify: a*b = alpha + beta (mod q) >>> product = a * b >>> additive_sum = alpha + beta >>> product == additive_sum True
- receiver_complete(sender_bits: List[int]) Any[source]¶
Receiver returns their additive share beta (already computed).
Parameters¶
- sender_bitslist of int
Sender’s bit decomposition (unused in correct protocol)
Returns¶
- ZR element
Receiver’s additive share beta
- receiver_round1(b: Any, sender_msg: Dict[str, Any]) Tuple[Dict[str, Any], None][source]¶
Receiver (holding b) selects OT messages based on bits of b.
Uses real SimpleOT: for each bit b_i, receiver only learns m_{b_i}. The receiver NEVER sees both m0 and m1.
Parameters¶
- bZR element
Receiver’s multiplicative share
- sender_msgdict
Message from sender_round1
Returns¶
- tuple (dict, None)
A tuple containing: - dict: Receiver parameters with ‘ot_responses’ list of OT receiver responses - None: Placeholder for beta (computed in receiver_round2)
- receiver_round2(sender_round2_msg: Dict[str, Any]) Any[source]¶
Receiver retrieves selected OT messages and computes beta.
Parameters¶
- sender_round2_msgdict
Message from sender_round2 containing OT ciphertexts
Returns¶
- ZR element
Receiver’s additive share beta such that a*b = alpha + beta (mod q)
- sender_round1(a: Any) Dict[str, Any][source]¶
Sender (holding a) generates first message.
Sender samples random alpha and prepares OT messages such that receiver can learn beta = a*b - alpha. Uses real SimpleOT for security.
Parameters¶
- aZR element
Sender’s multiplicative share
Returns¶
- dict
OT setup parameters containing: - ‘ot_params’: list of OT sender parameters (one per bit position) - ‘adjustment’: integer for receiver to compute beta
- sender_round2(receiver_msg: Dict[str, Any]) Tuple[Any, Dict[str, Any]][source]¶
Sender processes receiver’s OT responses and returns alpha.
Parameters¶
- receiver_msgdict
Message from receiver_round1 containing OT responses
Returns¶
- tuple (ZR element, dict)
A tuple containing: - ZR element: Sender’s additive share alpha - dict: OT data with ‘ot_ciphertexts’ list for receiver to retrieve
- class mta.MtAwc(groupObj: Any)[source]¶
Bases:
objectMtA with check - includes ZK proof that conversion is correct.
Used for malicious security. Adds commitment and proof phases to verify that parties performed MtA correctly.
The protocol adds: 1. Commitment phase: parties commit to their shares 2. Proof phase: parties prove correctness of OT selections 3. Verification: parties verify each other’s proofs
>>> from charm.toolbox.eccurve import secp256k1 >>> group = ECGroup(secp256k1) >>> mta_wc = MtAwc(group) >>> # Alice has share a, Bob has share b >>> a = group.random(ZR) >>> b = group.random(ZR) >>> # Run MtA with correctness check >>> sender_commit = mta_wc.sender_commit(a) >>> receiver_commit = mta_wc.receiver_commit(b) >>> # Exchange commitments and run MtA >>> sender_msg = mta_wc.sender_round1(a, receiver_commit) >>> receiver_msg, _ = mta_wc.receiver_round1(b, sender_commit, sender_msg) >>> alpha, sender_proof = mta_wc.sender_round2(receiver_msg) >>> beta, valid = mta_wc.receiver_verify(sender_proof) >>> valid True >>> # Verify: a*b = alpha + beta (mod q) >>> product = a * b >>> additive_sum = alpha + beta >>> product == additive_sum True
- receiver_commit(b: Any) Dict[str, Any][source]¶
Receiver commits to share b.
Parameters¶
- bZR element
Receiver’s multiplicative share
Returns¶
- dict
Commitment to send to sender
- receiver_round1(b: Any, sender_commit: Dict[str, Any], sender_msg: Dict[str, Any]) Tuple[Dict[str, Any], None][source]¶
Receiver processes sender message with commitments.
Parameters¶
- bZR element
Receiver’s multiplicative share
- sender_commitdict
Sender’s commitment from sender_commit (includes bit_proof)
- sender_msgdict
Message from sender_round1
Returns¶
- tuple
(receiver_message, beta_placeholder)
- receiver_verify(proof: Dict[str, Any]) Tuple[Any | None, bool][source]¶
Receiver verifies proof including ZK bit decomposition and returns beta.
Implements full ZK verification per DKLS23 Section 3: 1. Verifies challenge-response for commitment 2. Verifies bit decomposition OR-proofs (each bit is 0 or 1) 3. Verifies bits sum to the committed value
Parameters¶
- proofdict
Proof from sender_round2
Returns¶
- tuple
(beta, valid) where: - beta: receiver’s additive share - valid: boolean indicating if proof is valid
- sender_commit(a: Any) Dict[str, Any][source]¶
Sender commits to share a with ZK bit decomposition proof.
Parameters¶
- aZR element
Sender’s multiplicative share
Returns¶
- dict
Commitment and bit decomposition proof to send to receiver
- sender_round1(a: Any, receiver_commit: Dict[str, Any]) Dict[str, Any][source]¶
Sender generates first message with receiver’s commitment.
Parameters¶
- aZR element
Sender’s multiplicative share
- receiver_commitdict
Receiver’s commitment from receiver_commit
Returns¶
- dict
Message to send to receiver
- sender_round2(receiver_msg: Dict[str, Any]) Tuple[Any, Dict[str, Any]][source]¶
Sender completes MtA and generates proof.
Parameters¶
- receiver_msgdict
Message from receiver_round1
Returns¶
- tuple
(alpha, proof) where: - alpha: sender’s additive share - proof: ZK proof of correctness (does NOT reveal sender_bits)
- mta.hash_to_field(group: Any, *args: Any) Any[source]¶
Hash multiple values to a field element with domain separation.
Uses group.hash() for proper domain separation and automatic serialization of different types.
Parameters¶
- groupECGroup
The elliptic curve group
- *argsvarious
Values to hash
Returns¶
- ZR element
Hash output as field element