mpc_utils - MPC Utility Functions

Overview

The mpc_utils module provides common utility functions for multi-party computation (MPC) protocols in the Charm cryptographic library. These utilities support byte/integer conversions, bit decomposition for OT-based protocols, and Pedersen commitments for hiding values during secure computation.

This module serves as a foundational building block for threshold ECDSA implementations like DKLS23, providing consistent data handling across all MPC components.

Key Features

  • Byte/Integer Conversion: Consistent big-endian conversion between integers and bytes

  • Bit Decomposition: LSB-first bit extraction for oblivious transfer protocols

  • Pedersen Commitments: Information-theoretically hiding, computationally binding commitments

  • Homomorphic Properties: Commitments support additive homomorphism for secure aggregation

  • Elliptic Curve Support: Works with any DDH-hard elliptic curve group

Use Cases

  • Oblivious Transfer: Bit decomposition enables OT-based MtA conversion

  • Zero-Knowledge Proofs: Pedersen commitments provide hiding for ZK protocols

  • Secure Aggregation: Homomorphic commitment addition for distributed protocols

  • Protocol Serialization: Consistent byte encoding for network transmission

Example Usage

Byte/Integer Conversion:

from charm.toolbox.mpc_utils import int_to_bytes, bytes_to_int

# Convert integer to fixed-length bytes (big-endian)
data = int_to_bytes(256, length=4)  # b'\x00\x00\x01\x00'

# Convert back to integer
value = bytes_to_int(data)  # 256

Bit Decomposition:

from charm.toolbox.mpc_utils import bit_decompose, bits_to_int

# Decompose value into bits (LSB first)
bits = bit_decompose(value=5, order=2**256, num_bits=4)  # [1, 0, 1, 0]

# Reconstruct from bits
reconstructed = bits_to_int(bits, order=2**256)  # 5

Pedersen Commitments:

from charm.toolbox.ecgroup import ECGroup, ZR
from charm.toolbox.eccurve import secp256k1
from charm.toolbox.mpc_utils import PedersenCommitment

group = ECGroup(secp256k1)
pc = PedersenCommitment(group)
pc.setup()

# Commit to a value
value = group.random(ZR)
commitment, randomness = pc.commit(value)

# Verify the commitment opens correctly
is_valid = pc.open(commitment, value, randomness)  # True

# Homomorphic addition of commitments
c1, r1 = pc.commit(group.init(ZR, 10))
c2, r2 = pc.commit(group.init(ZR, 20))
c_sum = pc.add(c1, c2)  # Commits to 30

API Reference

MPC Utility Functions for Charm

Common utilities for multi-party computation protocols including: - Byte/integer conversion with consistent big-endian ordering - Bit decomposition and reconstruction for OT-based protocols - Pedersen commitment scheme for hiding commitments

Authors:

Elton de Souza

Date:

01/2026

class mpc_utils.PedersenCommitment(group: ECGroup, g: Any | None = None, h: Any | None = None)[source]

Bases: object

Pedersen Commitment Scheme for Elliptic Curve Groups.

Implements the information-theoretically hiding commitment scheme: C = g^value * h^randomness

where g and h are generators with unknown discrete log relationship.

Properties: - Computationally binding (under DLP assumption) - Information-theoretically hiding - Additively homomorphic

Parameters

groupECGroup

An elliptic curve group object

gGElement, optional

First generator (random if not provided)

hGElement, optional

Second generator (random if not provided)

Examples

>>> from charm.toolbox.eccurve import secp256k1
>>> from charm.toolbox.ecgroup import ECGroup, ZR
>>> group = ECGroup(secp256k1)
>>> pc = PedersenCommitment(group)
>>> pc.setup()
>>> value = group.random(ZR)
>>> c, r = pc.commit(value)
>>> pc.open(c, value, r)
True
add(c1: Any, c2: Any) Any[source]

Homomorphically add two commitments.

If c1 = Commit(v1, r1) and c2 = Commit(v2, r2), then c1 * c2 = Commit(v1 + v2, r1 + r2).

Parameters

c1GElement

First commitment

c2GElement

Second commitment

Returns

GElement

Combined commitment

commit(value: Any, randomness: Any | None = None) Tuple[Any, Any][source]

Create Pedersen commitment: C = g^value * h^randomness.

Parameters

valueZRElement or int

Value to commit to

randomnessZRElement, optional

Randomness for commitment (generated if not provided)

Returns

tuple

(commitment, randomness)

property g: Any

First generator.

property h: Any

Second generator.

open(commitment: Any, value: Any, randomness: Any) bool[source]

Verify that a commitment opens to the given value.

Parameters

commitmentGElement

The commitment to verify

valueZRElement or int

The claimed value

randomnessZRElement

The randomness used in commitment

Returns

bool

True if commitment opens correctly

setup() Tuple[Any, Any][source]

Generate random generators if not already set.

mpc_utils.bit_decompose(value: Any, order: int, num_bits: int) List[int][source]

Decompose a field element into its bit representation.

The input value is first reduced modulo order to ensure consistent behavior for values at or near the group order boundary.

Parameters

valueZR element or int

The value to decompose (will be reduced mod order)

orderint

The group order

num_bitsint

Number of bits to extract

Returns

list of int

List of bits (0 or 1), LSB first

Examples

>>> bit_decompose(5, 2**256, 4)
[1, 0, 1, 0]
>>> bit_decompose(0, 2**256, 4)
[0, 0, 0, 0]
mpc_utils.bits_to_int(bits: List[int], order: int) int[source]

Reconstruct an integer from its bit representation, reduced mod order.

This is the inverse of bit_decompose. The result is always reduced modulo the group order to ensure values stay in the valid field range.

Parameters

bitslist of int

List of bits (0 or 1), LSB first

orderint

The group order

Returns

int

The reconstructed integer, reduced mod order

Examples

>>> bits_to_int([1, 0, 1, 0], 2**256)
5
>>> bits_to_int([0, 0, 0, 0], 2**256)
0
mpc_utils.bytes_to_int(b: bytes) int[source]

Convert a byte string to a non-negative integer.

Uses big-endian byte ordering (most significant byte first), which is standard for cryptographic protocols.

Parameters

bbytes

Byte string to convert.

Returns

int

The integer value represented by the bytes.

Examples

>>> bytes_to_int(b'\x01\x00')
256
>>> bytes_to_int(b'\x00\x00\x00\x00')
0
mpc_utils.int_to_bytes(n: int, length: int) bytes[source]

Convert a non-negative integer to a fixed-length byte string.

Uses big-endian byte ordering (most significant byte first), which is standard for cryptographic protocols.

Parameters

nint

Non-negative integer to convert. Must fit within length bytes.

lengthint

Exact number of bytes in the output. Value is zero-padded if needed.

Returns

bytes

Big-endian representation of n with exactly length bytes.

Raises

OverflowError

If n is too large to fit in length bytes.

ValueError

If n is negative.

Examples

>>> int_to_bytes(256, 2)
b'\x01\x00'
>>> int_to_bytes(0, 4)
b'\x00\x00\x00\x00'