ZK/SEC Research notes from zkSecurity
All posts
educative

Optimizing Barrett Reduction: Tighter Bounds Eliminate Redundant Subtractions

Barrett reduction

Barrett reduction is a widely used algorithm for reducing a value modulo $m$. Our analysis, conducted during the Rust p256 crate audit, shows that the error bound for Barrett reduction can be tighter than traditionally assumed. For most moduli used in cryptography (e.g., NIST curves), the quotient approximation error is at most 1 (not 2). This improvement eliminates the need for a second subtraction in practice. By adopting this optimization, RustCrypto p256 achieves a 14% performance improvement in scalar multiplication.

What Is Barrett Reduction?

Barrett reduction is a method for efficiently computing the remainder of a division operation (i.e., modulus operation), $x \mod m$, without performing an actual division.

We want to compute $r = x \mod m$, which can be expressed as $x = q \cdot m + r$, where $q$ is the quotient and $r$ is the remainder. In practice (e.g., cryptographic field arithmetic), the modulus $m$ can be a large integer represented using $k$ limbs. Each limb is a 32-bit or 64-bit value (depending on the machine word), making the radix $b = 2^{32}$ or $2^{64}$. In practice, the value $x$ is a $2k$-limb integer because it results from the multiplication of two $k$-limb integers.

One way to compute $r$ is to first calculate $q$ as:

$$ q = \lfloor x / m \rfloor $$

Once $q$ is determined, $r$ can be computed as $r = x - q \cdot m$. Barrett reduction provides a more efficient way to approximate $q$, avoiding the need for direct division, which is computationally expensive.

First, let's rewrite the formula above as:

$$ q = \lfloor x / m \rfloor = \left\lfloor\frac{x}{m} \cdot \frac{b^{2k}}{b^{2k}}\right\rfloor = \left\lfloor\frac{x}{m} \cdot \frac{b^{2k}}{b^{k+1}\cdot b^{k-1}}\right\rfloor = \left\lfloor\frac{b^{2k}}{m} \cdot \frac{x}{b^{k-1}} \cdot \frac{1}{b^{k+1}}\right\rfloor $$

So far, our computation is exact. However, instead of computing $q$ exactly, we'll approximate it by computing:

$$ \tilde{q} = \left\lfloor \frac{{\color{red}{\lfloor}} \frac{x}{b^{k-1}} {\color{red}{\rfloor}} \cdot {\color{red}{\lfloor}} \frac{b^{2k}}{m} {\color{red}{\rfloor}}}{b^{k+1}}\right\rfloor $$

This allows us to precompute $\mu = \lfloor \frac{b^{2k}}{m} \rfloor$ and rewrite the above as:

$$ q= \left\lfloor \frac{\lfloor \frac{x}{b^{k-1}} \rfloor \cdot \mu}{b^{k+1}}\right\rfloor $$

Note: Both $\lfloor \frac{\cdot}{b^{k-1}} \rfloor$ and $\lfloor \frac{\cdot}{b^{k+1}} \rfloor$ are fast to compute using right shifts.

Since the two approximations can be smaller than their exact computations, we have $\tilde{q} \leq q$. Traditional analysis has shown that $\tilde{q} \in [q - 2, q]$ (we will elaborate on this in the analysis section). This means the approximate quotient $\tilde{q}$ is at most 2 less than the true quotient $q$.

Computing $r$ in $x \approx \tilde{q} \cdot m + r$

If we had computed $q$ exactly, we would simply compute:

$$r = x - q \cdot m$$

Since $r \in [0, m)$, only the bit length of $m$ is involved in that subtraction. Thus, we can compute it faster by involving only the least significant $b^k$ bits:

$$r = x - q \cdot m \mod{b^k} = (x \mod{b^k}) - (q \cdot m \mod{b^k})$$

(where modulo $b^k$ can be computed efficiently)

r-mod

However, remember that we have computed an approximation $\tilde{q}$ of $q$, where $\tilde{q} \in [q-2, q]$.

We know that either:

  1. $r = x - \tilde{q} \cdot m$
  2. $r = x - (\tilde{q} + 1) \cdot m$
  3. $r = x - (\tilde{q} + 2) \cdot m$

To compute $r$, we first calculate case 1. If the result is not smaller than $m$, we subtract $m$ once or twice to bring it into the correct range.

This means that we might not have $\tilde{r} = x - \tilde{q} \cdot m < b^k$ immediately. Instead, the value could be $m$ or $2m$ times larger.

Since $m < b^k$, we know $2 \cdot m < 2 \cdot b^k$. This allows us to upper bound our approximation:

$$r \leq\tilde{r} \leq r + 2m < b^k + 2 \cdot b^k < b^{k+1}$$

Then, we can calculate $\tilde{r}$ more efficiently:

$$\tilde{r} = ((x \bmod{b^{k+1}}) - (\tilde{q}\cdot m \bmod{b^{k+1}})) \bmod{b^{k+1}}$$

tilde-r-mod

Again, the $\bmod{b^{k+1}}$ operation is very efficient on binary machines.

We finally arrive at the algorithm as described in Handbook of Applied Cryptography, Chapter 14. The steps outlined above closely follow the process detailed in the book.

Barrett Algorithm

Source: Handbook of Applied Cryptography, Chapter 14

A Tighter Bound Analysis

The bound of $\tilde{q}$ directly determines how many times $r$ needs to be subtracted by $m$ to fall within the correct range. Traditionally, the bound is known to be $\tilde{q} \in [q-2, q]$. In this section, we will show that for almost all moduli in practice, the tighter bound holds: $\tilde{q} \in [q-1, q]$.

Remember that

$$q = \lfloor \frac{x}{m} \rfloor$$ $$\tilde{q} = \lfloor \frac{\lfloor \frac{x}{b^{k-1}} \rfloor \cdot \lfloor \frac{b^{2k}}{m} \rfloor}{b^{k+1}} \rfloor$$

Since $\tilde{q}$ is derived from a truncated approximation of $\frac{x}{m}$, it naturally satisfies $\tilde{q} \le q$.

Let's denote $\alpha = x \mod {b^{k-1}}$, where $\alpha \lt b^{k-1}$. Denote $\beta = b^{2k} \mod m$, where $\beta \lt m$. Then we can remove the floor operation:

$$\lfloor \frac{x}{b^{k-1}} \rfloor = \frac{x - \alpha}{b^{k-1}}$$ $$\lfloor \frac{b^{2k}}{m} \rfloor = \frac{b^{2k} - \beta}{m}$$

Then we can simplify $\tilde{q}$:

$$ \begin{align*} \tilde{q} &= \lfloor \frac{\lfloor \frac{x}{b^{k-1}} \rfloor \cdot \lfloor \frac{b^{2k}}{m} \rfloor}{b^{k+1}} \rfloor\\ &= \lfloor \frac{ \frac{x - \alpha}{b^{k-1}} \cdot \frac{b^{2k} - \beta}{m}}{b^{k+1}} \rfloor \\ &= \lfloor \frac{(x - \alpha) \cdot (b^{2k} - \beta)}{m \cdot b^{2k}} \rfloor \\ &= \lfloor \frac{x}{m} - {\color{red}{\frac{\alpha \cdot b^{2k} + \beta \cdot (x - \alpha)}{m \cdot b^{2k}}}} \rfloor \end{align*} $$

We use ${\color{red}{z}}$ to denote the red part (note that $z \ge 0$). Then we have $\tilde{q} = \lfloor \frac{x}{m} - {\color{red}{z}} \rfloor$. By the floor function inequality $\lfloor x \rfloor + \lfloor y \rfloor + 1 \ge \lfloor x + y \rfloor$, we have:

$$\lfloor \frac{x}{m} - z \rfloor + \lfloor z \rfloor + 1 \ge \lfloor \left(\frac{x}{m} - z\right) + z \rfloor = \lfloor \frac{x}{m} \rfloor = q$$

That is saying $\tilde{q} + \lfloor z \rfloor + 1 \ge q$.

The bound of $z$ is the key to analyzing the bound of $\tilde{q}$. If we can prove that $0 \le z \lt 2$, then we will have $\lfloor z \rfloor \le 1$ and finally $\tilde{q} + 2 \ge \tilde{q} + \lfloor z \rfloor + 1 \ge q$. Let's analyze the bound of $z$.

Prove that $\tilde{q} \in [q-2, q]$

We have:

$$ \begin{align*} z &= \frac{\alpha \cdot b^{2k} + \beta \cdot (x-\alpha)}{m \cdot b^{2k}} \\ &\lt \frac{{\color{red}{b^{k-1}}} \cdot b^{2k} + \beta \cdot {\color{red}{b^{2k}}}}{m\cdot b^{2k}} \\ &= \frac{b^{k-1} + \beta}{m} \end{align*} $$

We know that $b^{k-1} \lt m$ (because $m$ is $k$-limb) and $\beta \lt m$. Then we have:

$$z \lt \frac{b^{k-1} + \beta}{m} \lt \frac{m + m}{m} = 2$$

And thus:

$$\lfloor z \rfloor \le 1$$

That's exactly what we want. Therefore, we conclude that $\tilde{q} + 2 \ge \tilde{q} + \lfloor z \rfloor + 1 \ge q$.

Tighter Bound in Practice: $\tilde{q} \in [q-1, q]$

We have proved that $\tilde{q} \in [q-2, q]$ under all circumstances. However, this is a loose bound. Here, we claim that for almost all moduli $m$ in practice, we have a tighter bound: $z \lt 1$, and thus $\tilde{q} + 1 \ge \tilde{q} + \lfloor z \rfloor + 1 \ge q$.

Let's examine which moduli $m$ satisfy this tighter bound. Recall that $z \lt \frac{b^{k-1} + \beta}{m}$, so $z \lt 1$ holds if the following is true:

$$\frac{b^{k-1} + \beta}{m} \le 1$$

Which means:

$$b^{k-1} + \beta \le m$$

Further:

$$\beta \le m - b ^{k-1}$$

That's saying if $\beta$ is no greater than $m-b^{k-1}$, then $z \lt 1$ and thus $\tilde{q} \in [q-1, q]$. We can formalize this as the Tighter Bound Criterion:

$$ \boxed{\text{Given a modulus } m \text{, if } \beta \le m - b^{k-1} \text{ (where } \beta = b^{2k} \bmod{m}\text{), then } \tilde{q} \in [q-1, q] \text{.}} $$

It's worth noting that $\beta = b^{2k} \mod{m}$ falls within $[0, m)$. In practice, where $b$ is either $2^{32}$ or $2^{64}$, and $m$ approaches $b^k$, the value $m - b^{k-1}$ is very close to $m$.

The behavior of $\beta = b^{2k} \bmod{m}$ resembles a uniform random distribution over $[0, m)$ for any random modulus $m$. This makes it highly probable that $\beta \le m - b^{k-1}$. Consequently, most moduli $m$ will satisfy $z \lt 1$, leading to $\tilde{q} + 1 \ge q$.

To quantify this probability, let's assume the common case where $\frac{b^k}{2} \lt m \lt b^k$ and $\beta$ follows a uniform distribution. Under these conditions:

$$ \Pr[\beta \le m - b^{k-1}] = \frac{m-b^{k-1}}{m} > 1 - \frac{2}{b} $$

To put this in perspective:

  • When $b = 2^{32}$, the probability of achieving the tighter bound exceeds $1 - \frac{1}{2^{31}}$.
  • When $b = 2^{64}$, the probability of achieving the tighter bound exceeds $1 - \frac{1}{2^{63}}$.

That is, for nearly all moduli in practice, the tighter bound $\tilde{q} \in [{q-1}, q]$ holds.

Here is an intuitive explanation: $\mu$ (i.e., $\lfloor \frac{b^{2k}}{m} \rfloor$) is the quotient of $m$ divide $b^{2k}$, and $\beta$ is the remainder. If $\beta$ is very small, then $\mu$ will be very close to the actual quotient and thus the calculation of $\tilde{q}$ will have less approximation errors. Our analysis shows that as long as $\beta$ is no greater than $m - b^{k-1}$, the calculated $\tilde{q}$ is at most $1$ less than $q$. As that is a very loose requirement for $\beta$ (or $m$), most of the moduli have a tighter bound.

Practical Optimization For Barrett Reduction Implementation

The tighter bound enables faster Barrett reduction implementation. According to traditional analysis, we may need to subtract $r$ by $m$ twice to get the final result. For a given modulus $m$, if the tighter bound holds, then we can subtract $r$ by $m$ at most once. This means we can save one subtraction.

This is very useful for constant time implementation where it always substract the max times. For example, in RustCrypto P-256 scalar field implementation, it always subtracts twice.

pub(super) const fn barrett_reduce(lo: U256, hi: U256) -> U256 {
    [...]

    let r1 = [a0, a1, a2, a3, a4];
    let r2 = q3_times_n_keep_five(&q3);
    let r = sub_inner_five(r1, r2);

    // Result is in range (0, 3*n - 1),
    // and 90% of the time, no subtraction will be needed.
    let r = subtract_n_if_necessary(r);
    let r = subtract_n_if_necessary(r);
    U256::new([r[0], r[1], r[2], r[3]])
}

As P-256 scalar field satisfies $\beta \le m - b^{k-1}$, the tighter bound $\tilde{q} \in [{q-1}, q]$ holds. This implies the calculated $\tilde{q}$ is at most $1$ less than the actual quotient $q$. This means r can be subtracted at most once to get the final result. The second subtract_n_if_necessary call in the code above is unnecessary and can be safely removed.

Benchmarks show that simply removing the second subtraction improves multiplication and inversion performance by 14%.

scalar operations/mul
    time:   [38.900 ns 38.957 ns 39.026 ns]
    change: [-14.379% -14.052% -13.734%] (p = 0.00 < 0.05)
    Performance has improved.
scalar operations/invert
    time:   [20.716 µs 20.758 µs 20.823 µs]
    change: [-14.817% -14.331% -13.969%] (p = 0.00 < 0.05)
    Performance has improved.

As analyzed in the previous section, the tighter bound holds for almost all moduli. Thus, this optimization applies to most of the Barrett reductions with fixed moduli (e.g., ECC, ZKP).

Here is the Python script to test if a modulus $m$ has the tighter bound:

# Tighter Bound Criterion for the Barret reduction
def tighter_bound_criterion(m):
    def inner_test(m, b):
        # k chosen such that b^{k-1} < m < b^k
        k = 1
        while b**k < m:
            k += 1
        print("k = ", k)
        beta = b**(2*k) % m

        # calculate criterion
        return beta <= m - b**(k-1)

    # test both b=2^32 and b=2^64
    return inner_test(m, 2**32) and inner_test(m, 2**64)

# P-256 scalar field
assert(tighter_bound_criterion(0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551) == True)

# P-256 base field
assert(tighter_bound_criterion(0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff) == True)

Conclusion

Our analysis demonstrates that the error bound for the quotient approximation $\tilde{q}$ can be tightened from $[q-2, q]$ to $[q-1, q]$ for almost all moduli used in practice. This tighter bound eliminates the need for a second subtraction in most cases, enabling faster and more efficient implementations.

We showed how this optimization applies to real-world cryptographic libraries, such as RustCrypto's P-256 scalar field implementation, where removing the unnecessary subtraction improved performance significantly. These findings are broadly applicable to other cryptographic systems and zero-knowledge proof frameworks that rely on fixed moduli.

Keep reading
Recommended

Circle STARKs: Part I, Mersenne

Discover the intriguing world of Circle STARKs and how they can supercharge zero-knowledge proofs. This blog post sets the stage for a fascinating series about utilizing Mersenne prime fields to achieve lightning-fast arithmetic operations in STARK systems. You'll explore recent breakthroughs that make these fields more practical despite their previous limitations, and you'll get a sneak peek at what’s to come, including delving into group structures and implementing circle FFTs. If you're keen on cryptography and zero-knowledge proofs, this series will unveil how modern advancements are pushing the boundaries of what's possible.

Mathias Hall-Andersen · June 03, 2024

Accelerating ZK Proving with WebGPU: Techniques and Challenges

Hey there! We're diving into how leveraging WebGPU can revolutionize client-side proving for privacy-preserving zero-knowledge apps. By tackling the usual time and memory bottlenecks with innovative techniques like using GPUs, we're achieving significant performance gains. We'll share our experiences using WebGPU with various frameworks, offering insights into optimizing operations and managing data transfer efficiently. Plus, learn about the challenges and exciting potential of integrating WebGPU into zero-knowledge frameworks. Join us to explore the future of privacy tech!

Jaehun Kim, Jason Park · April 25, 2025

Faster Sumchecks: Part I

In this blog post, we explore how to optimize the sumcheck protocol, particularly when working with values in a small field and randomness from a large field, as often needed in zkVMs. We introduce various algorithms aimed at reducing expensive operations, focusing on minimizing large multiplications. Starting from using simple evaluation tables to more sophisticated techniques like precomputing accumulators and leveraging Lagrange interpolation, we demonstrate how to efficiently organize computations to speed up proving times. Readers will gain insights into handling arithmetic operations within the sumcheck protocol and learn about optimizing specific cases in zero-knowledge proofs.

Jason Park · November 21, 2025
More to explore

zkSecurity partners with ZPrize to make you win hundreds of thousands of dollars!

We're gearing up for this year's ZPrize competition, where we'll be hosting the High Throughput Signature Verification category. This challenge is all about creating the most efficient signature verification circuit using Aleo's Varuna proof system. Participants will work with ECDSA on the Bitcoin and Ethereum curve and the Ethereum hash function, keccak256. It's a great chance to dive into some of the hottest problems in arithmetic circuits and optimize cryptographic algorithms. If you're curious about pushing the boundaries in ZK, join us and share your feedback on our prize specification through our Discord channel.

ZK/SEC · August 27, 2023

Variants of KZG: Part II, Multilinear Commitments with PST

In this blog post, we extend the ideas behind univariate KZG commitments to multilinear polynomials through the PST commitment scheme. We derive the multilinear quotient identity, explain how PST commits to and opens multilinear polynomials using a specialized multilinear setup and walk through its opening protocol. We conclude by examining the proof size, prover and verifier costs, and the limitations that motivate other multilinear polynomial commitment schemes.

Varun Thakore · July 28, 2026

Lean4 formalization of "A Simplified Round-by-round Soundness Proof of FRI"

A Lean4 formalization of the paper "A Simplified Round-by-round Soundness Proof of FRI" by Albert Garreta, Nicolas Mohnblatt, and Benedikt Wagner, completed using Harmonic's Aristotle agent and Claude Code. Welcome to the strange world of machine-led formalization of cryptography.

Yoichi Hirai · January 26, 2026