Skip to content

API reference

Everything you need is importable from the top level.

from sigma_rangeproof import (
    commit, open_commit, prove_ge, verify_ge,
    RangeProof, Params, DEFAULT_PARAMS, MAX_BITS, rand_scalar,
)

commit

commit(value: int, blinding: int | None = None, *, params=DEFAULT_PARAMS) -> tuple[int, int]

Returns (commitment, blinding). If blinding is omitted, a uniform one is drawn from secrets. The commitment is a group element safe to publish; the blinding is secret and is needed again to prove anything about the value. Both value and blinding must be integers in \([0, q)\); a value that is negative, >= q, or the wrong type raises rather than being silently reduced. For a range proof, keep value a small non-negative integer.

open_commit

open_commit(commitment: int, value: int, blinding: int, *, params=DEFAULT_PARAMS) -> bool

Recomputes the commitment from a claimed opening and reports whether it matches. Useful for tests and for the holder to check its own bookkeeping; it is not part of the zero-knowledge flow, since it requires revealing the value.

prove_ge

prove_ge(value: int, blinding: int, threshold: int, *, bits: int = 32, params=DEFAULT_PARAMS) -> RangeProof

Proves the commitment to (value, blinding) satisfies value >= threshold. Raises ValueError if value - threshold is negative or does not fit in bits bits, because no valid proof exists there. It also raises if bits exceeds MAX_BITS (64), if value or threshold falls outside \([0, q)\), or if the window 2**bits would reach the subgroup order. Cost and proof size are linear in bits; pick the smallest width covering your values.

verify_ge

verify_ge(commitment: int, threshold: int, proof: RangeProof, *, params=DEFAULT_PARAMS) -> bool

Checks proof against the public commitment and threshold. Returns a plain bool. A proof made for one threshold will not verify against another, and a proof will not verify against a commitment it was not made for. Untrusted input is bounded before any modular arithmetic: a proof declaring more than MAX_BITS (64) bits, or a threshold outside \([0, q)\), returns False immediately rather than triggering unbounded work.

RangeProof

A dataclass holding bits, the per-bit commitments, and the per-bit bit_proofs.

proof.to_dict() -> dict                                  # hex strings, JSON-ready
RangeProof.from_dict(d: dict, *, params=DEFAULT_PARAMS) -> RangeProof

Use these to move a proof across a network or into storage. from_dict is a strict parser built for hostile input: it requires bits in [1, MAX_BITS], the commitment and bit-proof lists to have exactly bits entries with the exact expected keys, and every hex field to be no wider than the canonical group-element or scalar encoding. Anything else raises ValueError before the proof reaches verify_ge.

Params, DEFAULT_PARAMS, MAX_BITS, rand_scalar

DEFAULT_PARAMS is the 2048-bit safe-prime group every call uses unless you pass your own. Params is its frozen dataclass; Params.validate(check_primality=...) runs the structural checks always and the primality test only when asked. Its elem_bytes and scalar_bytes properties give the canonical big-endian width of a group element and a scalar, which the strict deserializer uses to cap field sizes.

MAX_BITS (64) is the largest bit width any proof may declare; prove_ge, verify_ge, and RangeProof.from_dict all enforce it.

rand_scalar(params=DEFAULT_PARAMS) returns a uniform scalar in \([0, q)\), the same source the library uses internally for blindings and nonces.

A complete round trip

from sigma_rangeproof import commit, prove_ge, verify_ge, RangeProof
import json

# holder side
score = 740
commitment, blinding = commit(score)        # publish commitment, keep blinding

# prove score >= 700 over a 10-bit range
proof = prove_ge(score, blinding, 700, bits=10)
wire = json.dumps({"commitment": hex(commitment), "proof": proof.to_dict()})

# verifier side
msg = json.loads(wire)
ok = verify_ge(int(msg["commitment"], 16), 700, RangeProof.from_dict(msg["proof"]))
assert ok