(*** Barrett Reduction *) (** This file implements a slightly-generalized version of Barrett Reduction on [Z]. This version follows the Handbook of Applied Cryptography (Algorithm 14.42) rather closely; the only deviations are that we generalize from [k ± 1] to [k ± offset] for an arbitrary offset, and we weaken the conditions on the base [b] in [bᵏ] slightly. Contrasted with some other versions, this version does reduction modulo [b^(k+offset)] early (ensuring that we don't have to carry around extra precision), but requires more stringint conditions on the base ([b]), exponent ([k]), and the [offset]. *) Require Import Coq.ZArith.ZArith Coq.micromega.Psatz. Require Import Crypto.Util.Tactics.BreakMatch. Require Import Crypto.Util.ZUtil.Tactics.LtbToLt. Require Import Crypto.Util.ZUtil.Tactics.ZeroBounds. Require Import Crypto.Util.ZUtil.Div. Require Import Crypto.Util.ZUtil.Modulo. Require Import Crypto.Util.ZUtil.Hints. Require Import Crypto.Util.ZUtil.ZSimplify. Local Open Scope Z_scope. Section barrett. (** Quoting the Handbook of Applied Cryptography : *) (** Barrett reduction (Algorithm 14.42) computes [r = x mod m] given [x] and [m]. The algorithm requires the precomputation of the quantity [µ = ⌊b²ᵏ/m⌋]; it is advantageous if many reductions are performed with a single modulus. For example, each RSA encryption for one entity requires reduction modulo that entity’s public key modulus. The precomputation takes a fixed amount of work, which is negligible in comparison to modular exponentiation cost. Typically, the radix [b] is chosen to be close to the word-size of the processor. Hence, assume [b > 3] in Algorithm 14.42 (see Note 14.44 (ii)). *) (** * Barrett modular reduction *) Section barrett_modular_reduction. Context (m b x k μ offset : Z) (m_pos : 0 < m) (base_pos : 0 < b) (k_good : m < b^k) (μ_good : μ = b^(2*k) / m) (* [/] is [Z.div], which is truncated *) (x_nonneg : 0 <= x) (offset_nonneg : 0 <= offset) (k_big_enough : offset <= k) (x_small : x < b^(2*k)) (m_small : 3 * m <= b^(k+offset)) (** We also need that [m] is large enough; [m] larger than [bᵏ⁻¹] works, but we ask for something more precise. *) (m_large : x mod b^(k-offset) <= m). Let q1 := x / b^(k-offset). Let q2 := q1 * μ. Let q3 := q2 / b^(k+offset). Let r1 := x mod b^(k+offset). Let r2 := (q3 * m) mod b^(k+offset). (** At this point, the HAC says "If [r < 0] then [r ← r + bᵏ⁺¹]". This is equivalent to reduction modulo [b^(k+offset)], as we prove below. The version involving modular reduction has the benefit of being cheaper to implement, and making the proofs simpler, so we primarily use that version. *) Let r_mod_3m := (r1 - r2) mod b^(k+offset). Let r_mod_3m_orig := let r := r1 - r2 in if r