@umbra-privacy/sdk 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -25
- package/dist/{addresses-Brzgurv_.d.ts → addresses-B7HybtbJ.d.ts} +2 -1
- package/dist/{addresses-D_0YAS6B.d.cts → addresses-CTVY1oi7.d.cts} +2 -1
- package/dist/arcium-BXXlryfe.d.cts +20 -0
- package/dist/arcium-BXXlryfe.d.ts +20 -0
- package/dist/chunk-3LS5P32X.cjs +10892 -0
- package/dist/chunk-3LS5P32X.cjs.map +1 -0
- package/dist/chunk-4RHXVBNI.js +203 -0
- package/dist/chunk-4RHXVBNI.js.map +1 -0
- package/dist/chunk-4TZVXB5G.js +324 -0
- package/dist/chunk-4TZVXB5G.js.map +1 -0
- package/dist/chunk-5GUSMQ74.cjs +549 -0
- package/dist/chunk-5GUSMQ74.cjs.map +1 -0
- package/dist/chunk-5KPQXPQM.js +36 -0
- package/dist/chunk-5KPQXPQM.js.map +1 -0
- package/dist/chunk-AXD7LXYY.cjs +405 -0
- package/dist/chunk-AXD7LXYY.cjs.map +1 -0
- package/dist/{chunk-HOEXDXRC.cjs → chunk-BL6WXLPV.cjs} +32 -360
- package/dist/chunk-BL6WXLPV.cjs.map +1 -0
- package/dist/chunk-CFFLOE7D.cjs +598 -0
- package/dist/chunk-CFFLOE7D.cjs.map +1 -0
- package/dist/{chunk-BM7N6N7E.js → chunk-CFTW5WNG.js} +3 -325
- package/dist/chunk-CFTW5WNG.js.map +1 -0
- package/dist/chunk-DD2WCK4C.js +327 -0
- package/dist/chunk-DD2WCK4C.js.map +1 -0
- package/dist/chunk-DMPMQ74B.cjs +246 -0
- package/dist/chunk-DMPMQ74B.cjs.map +1 -0
- package/dist/{chunk-2Q75CQQJ.js → chunk-EEKF4553.js} +2 -2
- package/dist/chunk-EEKF4553.js.map +1 -0
- package/dist/chunk-ENVYYEM4.cjs +113 -0
- package/dist/chunk-ENVYYEM4.cjs.map +1 -0
- package/dist/chunk-FQX6ZYGJ.js +500 -0
- package/dist/chunk-FQX6ZYGJ.js.map +1 -0
- package/dist/chunk-FSK2ICMB.cjs +39 -0
- package/dist/chunk-FSK2ICMB.cjs.map +1 -0
- package/dist/chunk-FZYWLQAF.cjs +355 -0
- package/dist/chunk-FZYWLQAF.cjs.map +1 -0
- package/dist/chunk-GP26R377.js +436 -0
- package/dist/chunk-GP26R377.js.map +1 -0
- package/dist/chunk-HA5FLM63.js +393 -0
- package/dist/chunk-HA5FLM63.js.map +1 -0
- package/dist/chunk-INJ73LXQ.js +1107 -0
- package/dist/chunk-INJ73LXQ.js.map +1 -0
- package/dist/chunk-KMRROOME.js +10750 -0
- package/dist/chunk-KMRROOME.js.map +1 -0
- package/dist/{chunk-MDFSBU5W.cjs → chunk-LTCKPTZC.cjs} +2 -351
- package/dist/chunk-LTCKPTZC.cjs.map +1 -0
- package/dist/chunk-MKNCBUFA.js +564 -0
- package/dist/chunk-MKNCBUFA.js.map +1 -0
- package/dist/chunk-NKVMSABR.cjs +207 -0
- package/dist/chunk-NKVMSABR.cjs.map +1 -0
- package/dist/chunk-OFDWNWCL.js +70 -0
- package/dist/chunk-OFDWNWCL.js.map +1 -0
- package/dist/chunk-QJAUUYZU.cjs +331 -0
- package/dist/chunk-QJAUUYZU.cjs.map +1 -0
- package/dist/chunk-TLR7A64G.js +103 -0
- package/dist/chunk-TLR7A64G.js.map +1 -0
- package/dist/{chunk-MVKTV3FT.cjs → chunk-TQQZGNOI.cjs} +2 -2
- package/dist/chunk-TQQZGNOI.cjs.map +1 -0
- package/dist/chunk-UOFYS6M3.js +219 -0
- package/dist/chunk-UOFYS6M3.js.map +1 -0
- package/dist/chunk-UXMQI6B7.js +2406 -0
- package/dist/chunk-UXMQI6B7.js.map +1 -0
- package/dist/chunk-WN75ORDT.js +571 -0
- package/dist/chunk-WN75ORDT.js.map +1 -0
- package/dist/chunk-Y55PYKXH.cjs +595 -0
- package/dist/chunk-Y55PYKXH.cjs.map +1 -0
- package/dist/chunk-YEZBTYCP.cjs +77 -0
- package/dist/chunk-YEZBTYCP.cjs.map +1 -0
- package/dist/chunk-ZQOIYCGA.cjs +1126 -0
- package/dist/chunk-ZQOIYCGA.cjs.map +1 -0
- package/dist/chunk-ZY3TSHMJ.cjs +2665 -0
- package/dist/chunk-ZY3TSHMJ.cjs.map +1 -0
- package/dist/client-DkVBHMWb.d.cts +2613 -0
- package/dist/client-V4AF6Bz9.d.ts +2613 -0
- package/dist/common/pda/index.cjs +145 -0
- package/dist/common/pda/index.cjs.map +1 -0
- package/dist/common/pda/index.d.cts +1250 -0
- package/dist/common/pda/index.d.ts +1250 -0
- package/dist/common/pda/index.js +8 -0
- package/dist/common/pda/index.js.map +1 -0
- package/dist/constants/index.cjs +38 -164
- package/dist/constants/index.cjs.map +1 -1
- package/dist/constants/index.d.cts +8 -425
- package/dist/constants/index.d.ts +8 -425
- package/dist/constants/index.js +15 -124
- package/dist/constants/index.js.map +1 -1
- package/dist/crypto/index.cjs +583 -0
- package/dist/crypto/index.cjs.map +1 -0
- package/dist/crypto/index.d.cts +6731 -0
- package/dist/crypto/index.d.ts +6731 -0
- package/dist/crypto/index.js +14 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/{cryptography-BTGC72u-.d.ts → cryptography-BFSJcvi6.d.ts} +3 -2465
- package/dist/{cryptography-BTGC72u-.d.cts → cryptography-D6tPDh-Y.d.cts} +3 -2465
- package/dist/errors/index.cjs +64 -54
- package/dist/errors/index.d.cts +7 -797
- package/dist/errors/index.d.ts +7 -797
- package/dist/errors/index.js +3 -1
- package/dist/errors-B9EoPeWV.d.cts +593 -0
- package/dist/errors-B9EoPeWV.d.ts +593 -0
- package/dist/errors-DAIrstEL.d.cts +300 -0
- package/dist/errors-DPNMfyh0.d.ts +300 -0
- package/dist/index-BG0yjL7C.d.cts +6006 -0
- package/dist/index-ByynoyBO.d.ts +6006 -0
- package/dist/index.cjs +5133 -16116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1031 -7685
- package/dist/index.d.ts +1031 -7685
- package/dist/index.js +3228 -14905
- package/dist/index.js.map +1 -1
- package/dist/interfaces/index.d.cts +14 -6
- package/dist/interfaces/index.d.ts +14 -6
- package/dist/interfaces-43cReBcS.d.cts +3346 -0
- package/dist/interfaces-B8xKNl_6.d.ts +997 -0
- package/dist/interfaces-D2NO6kDD.d.cts +997 -0
- package/dist/interfaces-z_xYJlgV.d.ts +3346 -0
- package/dist/math/index.cjs +115 -0
- package/dist/math/index.cjs.map +1 -0
- package/dist/math/index.d.cts +1327 -0
- package/dist/math/index.d.ts +1327 -0
- package/dist/math/index.js +10 -0
- package/dist/math/index.js.map +1 -0
- package/dist/networks-RMd3abPE.d.ts +44 -0
- package/dist/networks-yAoO8peQ.d.cts +44 -0
- package/dist/relayer-NRRMSMNB.js +4 -0
- package/dist/relayer-NRRMSMNB.js.map +1 -0
- package/dist/relayer-RJHEIXJG.cjs +21 -0
- package/dist/relayer-RJHEIXJG.cjs.map +1 -0
- package/dist/solana/index.cjs +56 -0
- package/dist/solana/index.cjs.map +1 -0
- package/dist/solana/index.d.cts +105 -0
- package/dist/solana/index.d.ts +105 -0
- package/dist/solana/index.js +7 -0
- package/dist/solana/index.js.map +1 -0
- package/dist/{index-CLj_zWSD.d.ts → temporal-BbRaEPoO.d.ts} +1 -1
- package/dist/{index-CX6_pIRS.d.cts → temporal-oUj7iCaq.d.cts} +1 -1
- package/dist/transaction-forwarder-5mAMTjw6.d.ts +1155 -0
- package/dist/transaction-forwarder-C6gMUG7a.d.cts +1155 -0
- package/dist/types/index.cjs +232 -231
- package/dist/types/index.d.cts +15 -1485
- package/dist/types/index.d.ts +15 -1485
- package/dist/types/index.js +2 -1
- package/dist/types-BohhvPth.d.cts +87 -0
- package/dist/types-CW0oTT0j.d.ts +87 -0
- package/dist/types-C_V_CaKK.d.cts +2468 -0
- package/dist/types-C_V_CaKK.d.ts +2468 -0
- package/dist/types-Ca7frykr.d.ts +793 -0
- package/dist/types-CuKeoI19.d.cts +1296 -0
- package/dist/types-CxfTIpN9.d.ts +1052 -0
- package/dist/{types-n-sHFcgr.d.ts → types-D1jDUjfN.d.ts} +2 -2
- package/dist/types-DKEDUlH9.d.ts +1296 -0
- package/dist/types-EKuIfxTz.d.cts +1052 -0
- package/dist/{types-BBuELtY8.d.cts → types-IMGYmlv-.d.cts} +2 -2
- package/dist/types-PwNLi_2k.d.cts +793 -0
- package/dist/utils/index.cjs +823 -525
- package/dist/utils/index.d.cts +1711 -4021
- package/dist/utils/index.d.ts +1711 -4021
- package/dist/utils/index.js +9 -3
- package/dist/{versions-D9PqsEvj.d.cts → versions-BRlR36EA.d.cts} +1 -0
- package/dist/{versions-D9PqsEvj.d.ts → versions-BRlR36EA.d.ts} +1 -0
- package/package.json +79 -18
- package/dist/chunk-2Q75CQQJ.js.map +0 -1
- package/dist/chunk-BM7N6N7E.js.map +0 -1
- package/dist/chunk-GXKSUB2U.cjs +0 -4416
- package/dist/chunk-GXKSUB2U.cjs.map +0 -1
- package/dist/chunk-HOEXDXRC.cjs.map +0 -1
- package/dist/chunk-MDFSBU5W.cjs.map +0 -1
- package/dist/chunk-MQY7HDIA.js +0 -600
- package/dist/chunk-MQY7HDIA.js.map +0 -1
- package/dist/chunk-MVKTV3FT.cjs.map +0 -1
- package/dist/chunk-PG2J6V6Y.js +0 -4094
- package/dist/chunk-PG2J6V6Y.js.map +0 -1
- package/dist/chunk-VEGLTTYQ.cjs +0 -621
- package/dist/chunk-VEGLTTYQ.cjs.map +0 -1
- package/dist/chunk-WVHQ46DD.js +0 -758
- package/dist/chunk-WVHQ46DD.js.map +0 -1
- package/dist/index-B9pDY73x.d.ts +0 -12933
- package/dist/index-D33yo0qB.d.cts +0 -12933
- package/dist/networks-C-orpSFW.d.ts +0 -65
- package/dist/networks-FxYERGD1.d.cts +0 -65
|
@@ -0,0 +1,1327 @@
|
|
|
1
|
+
import { c as ModuloAddFunction, M as ModuloInvFunction, j as ModuloMulFunction, k as ModuloNegFunction, b as ModuloSubFunction, U as U512BasedBn254FieldElementSamplerFunction, l as U512BasedBn254FieldElementSamplerDeps, a as U512BasedCurve25519FieldElementSamplerFunction, e as Curve25519ModuloAddFunction, f as Curve25519ModuloInvFunction, g as Curve25519ModuloMulFunction, h as Curve25519ModuloPowFunction, i as Curve25519ModuloSubFunction, m as U512BasedCurve25519FieldElementSamplerDeps } from '../interfaces-D2NO6kDD.cjs';
|
|
2
|
+
import { B as Bn254FieldElement } from '../types-BohhvPth.cjs';
|
|
3
|
+
import { a as Base85Limb } from '../types-PwNLi_2k.cjs';
|
|
4
|
+
import '../types-C_V_CaKK.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* BN254 Field Operations Module
|
|
8
|
+
*
|
|
9
|
+
* This module provides higher-level arithmetic operations over the BN254 scalar
|
|
10
|
+
* field F_r, including modular exponentiation, multiplicative inverse computation,
|
|
11
|
+
* and the basic field operations (add, subtract, multiply). These functions build
|
|
12
|
+
* on the branded type system defined in `types.ts` and are intended for use in
|
|
13
|
+
* cryptographic protocols such as Groth16 proof generation, Fiat-Shamir challenges,
|
|
14
|
+
* and ZK circuit witness computation.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* ## BN254 and the Scalar Field
|
|
18
|
+
*
|
|
19
|
+
* The BN254 curve (also known as alt_bn128 or bn256) is a pairing-friendly
|
|
20
|
+
* elliptic curve whose scalar field has prime order:
|
|
21
|
+
* ```
|
|
22
|
+
* r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
|
|
23
|
+
* ```
|
|
24
|
+
* All operations in this module reduce their results modulo `r`, ensuring that
|
|
25
|
+
* outputs are always valid field elements in the range `[0, r-1]`.
|
|
26
|
+
*
|
|
27
|
+
* ## Performance Characteristics
|
|
28
|
+
*
|
|
29
|
+
* - `bn254Add`, `bn254Sub`, `bn254Mul`: O(1) — single BigInt operation + reduction
|
|
30
|
+
* - `bn254ModuloPow`: O(log exp) squarings and multiplications via square-and-multiply
|
|
31
|
+
* - `computeBn254ModularInverse`: O(log p) — Fermat exponentiation with p-2 as exponent
|
|
32
|
+
* - `computeBn254LimbwiseSumInverse`: O(log p) — three additions followed by inversion
|
|
33
|
+
*
|
|
34
|
+
* ## Security Note
|
|
35
|
+
*
|
|
36
|
+
* The inverse functions use Fermat's Little Theorem (`a^(p-2) mod p`) rather than
|
|
37
|
+
* the Extended Euclidean Algorithm. This choice trades a small performance overhead
|
|
38
|
+
* for a simpler, more auditable implementation. The underlying `modulePow` helper
|
|
39
|
+
* is intentionally non-constant-time (uses the `bigint` `%` operator internally);
|
|
40
|
+
* for constant-time arithmetic, use the functions in `field-arithmetic.ts`.
|
|
41
|
+
*
|
|
42
|
+
* @see {@link ./field-arithmetic} Constant-time field arithmetic
|
|
43
|
+
* @see {@link ./types} BN254 field element types and validation
|
|
44
|
+
*
|
|
45
|
+
* @packageDocumentation
|
|
46
|
+
* @module math/bn254/operations
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Computes the multiplicative inverse of a BN254 field element using
|
|
51
|
+
* Fermat's Little Theorem.
|
|
52
|
+
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* ## Mathematical Background
|
|
55
|
+
*
|
|
56
|
+
* For a prime field F_p, every non-zero element `a` has a unique multiplicative
|
|
57
|
+
* inverse `a^(-1)` satisfying:
|
|
58
|
+
* ```
|
|
59
|
+
* a * a^(-1) ≡ 1 (mod p)
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* By Fermat's Little Theorem, for prime `p` and `a != 0 (mod p)`:
|
|
63
|
+
* ```
|
|
64
|
+
* a^(p-1) ≡ 1 (mod p)
|
|
65
|
+
* ```
|
|
66
|
+
* Multiplying both sides by `a^(-1)`:
|
|
67
|
+
* ```
|
|
68
|
+
* a^(p-2) ≡ a^(-1) (mod p)
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* This function evaluates `a^(p-2) mod p` via the square-and-multiply algorithm
|
|
72
|
+
* in O(log p) field multiplications (approximately 254 squarings for BN254).
|
|
73
|
+
*
|
|
74
|
+
* ## Input Normalization
|
|
75
|
+
*
|
|
76
|
+
* The input is first normalized to its canonical representative in `[0, p-1]`
|
|
77
|
+
* via double reduction. If the normalized value is `0n`, there is no inverse and
|
|
78
|
+
* a `CryptographyError` is thrown.
|
|
79
|
+
*
|
|
80
|
+
* ## Complexity
|
|
81
|
+
*
|
|
82
|
+
* O(log p) ≈ O(254) field multiplications (squarings and multiplications via
|
|
83
|
+
* the square-and-multiply algorithm on a 254-bit exponent `p-2`).
|
|
84
|
+
*
|
|
85
|
+
* @param value - The BN254 field element to invert. Must be non-zero in the field.
|
|
86
|
+
* @returns The multiplicative inverse of `value` in `[1, BN254_FIELD_PRIME - 1]`.
|
|
87
|
+
*
|
|
88
|
+
* @throws {CryptographyError} If `value` is congruent to zero modulo the field prime,
|
|
89
|
+
* because zero has no multiplicative inverse in any field.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* import {
|
|
94
|
+
* computeBn254ModularInverse,
|
|
95
|
+
* bn254Mul,
|
|
96
|
+
* BN254_FIELD_PRIME,
|
|
97
|
+
* } from "@umbra/sdk";
|
|
98
|
+
* import { assertBn254FieldElement } from "@umbra/sdk";
|
|
99
|
+
*
|
|
100
|
+
* const a = 12345n;
|
|
101
|
+
* assertBn254FieldElement(a, "a");
|
|
102
|
+
*
|
|
103
|
+
* const aInv = computeBn254ModularInverse(a);
|
|
104
|
+
*
|
|
105
|
+
* // Verify: a * a^(-1) = 1 (mod p)
|
|
106
|
+
* const product = bn254Mul(a, aInv);
|
|
107
|
+
* console.log(product === 1n); // true
|
|
108
|
+
*
|
|
109
|
+
* // Division by a: b / a = b * a^(-1) mod p
|
|
110
|
+
* const b = 99999n;
|
|
111
|
+
* assertBn254FieldElement(b, "b");
|
|
112
|
+
* const quotient = bn254Mul(b, aInv); // b / a mod p
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @see {@link bn254ModuloPow} For general modular exponentiation in the BN254 field
|
|
116
|
+
* @see {@link computeBn254LimbwiseSumInverse} For the inverse of a Base85 limb sum
|
|
117
|
+
*
|
|
118
|
+
* @public
|
|
119
|
+
*/
|
|
120
|
+
declare function computeBn254ModularInverse(value: Bn254FieldElement): Bn254FieldElement;
|
|
121
|
+
/**
|
|
122
|
+
* Computes the multiplicative inverse of the sum of three Base85 limbs in the
|
|
123
|
+
* BN254 scalar field.
|
|
124
|
+
*
|
|
125
|
+
* @remarks
|
|
126
|
+
* ## Context: Base85 Limb Representation
|
|
127
|
+
*
|
|
128
|
+
* In ZK circuits that use the Circom/Groth16 toolchain, 255-bit field element
|
|
129
|
+
* inputs are commonly represented as three 85-bit limbs (sometimes called
|
|
130
|
+
* "Base85 limbs") to allow efficient constraint generation. Each limb holds
|
|
131
|
+
* a 85-bit chunk of the full value:
|
|
132
|
+
* ```
|
|
133
|
+
* full_value = limbs[0] + limbs[1] * 2^85 + limbs[2] * 2^170
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* ## Circuit Non-Zero Validation
|
|
137
|
+
*
|
|
138
|
+
* Proving that a value is non-zero in a ZK circuit requires the circuit to
|
|
139
|
+
* supply the multiplicative inverse of that value as an auxiliary witness.
|
|
140
|
+
* When the value is represented in limbwise form, the circuit sometimes needs
|
|
141
|
+
* the inverse of the *sum of the limbs* rather than the inverse of the
|
|
142
|
+
* reconstructed value. This function computes exactly that:
|
|
143
|
+
* ```
|
|
144
|
+
* sum = (limbs[0] + limbs[1] + limbs[2]) mod p
|
|
145
|
+
* result = sum^(-1) mod p
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* ## Why Limbwise Sum Instead of Reconstructed Value?
|
|
149
|
+
*
|
|
150
|
+
* The sum `limbs[0] + limbs[1] + limbs[2]` is a cheaper operation in
|
|
151
|
+
* the circuit compared to the full positional reconstruction
|
|
152
|
+
* `limbs[0] + limbs[1]*2^85 + limbs[2]*2^170`. The sum-based non-zero check
|
|
153
|
+
* works because if all three limbs are zero, their sum is also zero; otherwise
|
|
154
|
+
* the sum is guaranteed to be non-zero (given the limb range constraints enforced
|
|
155
|
+
* by the circuit).
|
|
156
|
+
*
|
|
157
|
+
* @param limbs - A tuple of three `Base85Limb` values: `[low, middle, high]`.
|
|
158
|
+
* Each limb must be in the range `[0, 2^85 - 1]`.
|
|
159
|
+
* @returns The multiplicative inverse of `(limbs[0] + limbs[1] + limbs[2]) mod p`
|
|
160
|
+
* as a `Bn254FieldElement` in the range `[1, BN254_FIELD_PRIME - 1]`.
|
|
161
|
+
*
|
|
162
|
+
* @throws {CryptographyError} If the sum of all three limbs is congruent to zero
|
|
163
|
+
* modulo the BN254 field prime, meaning no inverse exists.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* import {
|
|
168
|
+
* computeBn254LimbwiseSumInverse,
|
|
169
|
+
* BN254_FIELD_PRIME,
|
|
170
|
+
* } from "@umbra/sdk";
|
|
171
|
+
* import { assertBase85Limb } from "@umbra/sdk";
|
|
172
|
+
*
|
|
173
|
+
* const low = 0x1234n;
|
|
174
|
+
* const mid = 0x5678n;
|
|
175
|
+
* const high = 0x9ABCn;
|
|
176
|
+
* assertBase85Limb(low, "low");
|
|
177
|
+
* assertBase85Limb(mid, "mid");
|
|
178
|
+
* assertBase85Limb(high, "high");
|
|
179
|
+
*
|
|
180
|
+
* const inverse = computeBn254LimbwiseSumInverse([low, mid, high]);
|
|
181
|
+
*
|
|
182
|
+
* // Verify: (low + mid + high) * inverse ≡ 1 (mod p)
|
|
183
|
+
* const sum = (low + mid + high) % BN254_FIELD_PRIME;
|
|
184
|
+
* const check = (sum * inverse) % BN254_FIELD_PRIME;
|
|
185
|
+
* console.log(check === 1n); // true
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* @see {@link computeBn254ModularInverse} For inverting a single field element
|
|
189
|
+
* @see {@link Base85Limb} The branded limb type from `crypto/poseidon/types`
|
|
190
|
+
*
|
|
191
|
+
* @public
|
|
192
|
+
*/
|
|
193
|
+
declare function computeBn254LimbwiseSumInverse(limbs: [Base85Limb, Base85Limb, Base85Limb]): Bn254FieldElement;
|
|
194
|
+
/**
|
|
195
|
+
* Computes modular exponentiation in the BN254 scalar field: `base^exp mod p`.
|
|
196
|
+
*
|
|
197
|
+
* @remarks
|
|
198
|
+
* This is a type-safe wrapper around the internal `modulePow` helper that
|
|
199
|
+
* constrains both the input and output to the BN254 scalar field. It delegates
|
|
200
|
+
* to the square-and-multiply algorithm with O(log exp) multiplications.
|
|
201
|
+
*
|
|
202
|
+
* ## Typical Use Cases
|
|
203
|
+
*
|
|
204
|
+
* - Computing powers of a Fiat-Shamir challenge scalar
|
|
205
|
+
* - Evaluating polynomial commitments at a challenge point
|
|
206
|
+
* - Batch inversion via exponentiation (less efficient than Extended GCD but simpler)
|
|
207
|
+
*
|
|
208
|
+
* ## Exponent Sign
|
|
209
|
+
*
|
|
210
|
+
* The exponent must be a non-negative `bigint`. Negative exponents are not supported;
|
|
211
|
+
* use `computeBn254ModularInverse` for `base^(-1)` and compose with `bn254ModuloPow`
|
|
212
|
+
* for general negative powers.
|
|
213
|
+
*
|
|
214
|
+
* @param base - The base field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
215
|
+
* @param exp - The non-negative integer exponent (a plain `bigint`, not necessarily in the field).
|
|
216
|
+
* @returns `base^exp mod BN254_FIELD_PRIME` as a `Bn254FieldElement`.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* import { bn254ModuloPow, assertBn254FieldElement } from "@umbra/sdk";
|
|
221
|
+
*
|
|
222
|
+
* const challenge = 999n;
|
|
223
|
+
* assertBn254FieldElement(challenge, "challenge");
|
|
224
|
+
*
|
|
225
|
+
* // Compute challenge^3 mod p (evaluating a cubic polynomial coefficient)
|
|
226
|
+
* const cubed = bn254ModuloPow(challenge, 3n);
|
|
227
|
+
*
|
|
228
|
+
* // Compute challenge^0 = 1 (identity)
|
|
229
|
+
* const identity = bn254ModuloPow(challenge, 0n);
|
|
230
|
+
* console.log(identity === 1n); // true
|
|
231
|
+
* ```
|
|
232
|
+
*
|
|
233
|
+
* @see {@link computeBn254ModularInverse} For the special case exp = -1
|
|
234
|
+
* @see {@link bn254Mul} For a single multiplication
|
|
235
|
+
*
|
|
236
|
+
* @public
|
|
237
|
+
*/
|
|
238
|
+
declare function bn254ModuloPow(base: Bn254FieldElement, exp: bigint): Bn254FieldElement;
|
|
239
|
+
/**
|
|
240
|
+
* Computes the sum of two BN254 scalar field elements modulo the field prime.
|
|
241
|
+
*
|
|
242
|
+
* @remarks
|
|
243
|
+
* ## Formula
|
|
244
|
+
*
|
|
245
|
+
* ```
|
|
246
|
+
* result = (a + b) mod BN254_FIELD_PRIME
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
249
|
+
* Because both `a` and `b` are in `[0, p-1]`, their sum is in `[0, 2p-2]`,
|
|
250
|
+
* which requires at most one modular reduction step. This is implemented directly
|
|
251
|
+
* via JavaScript's `%` operator on `bigint`.
|
|
252
|
+
*
|
|
253
|
+
* ## Overflow Behavior
|
|
254
|
+
*
|
|
255
|
+
* JavaScript `bigint` arithmetic is arbitrary precision, so there is no risk of
|
|
256
|
+
* overflow. The modular reduction always yields a result in `[0, p-1]`.
|
|
257
|
+
*
|
|
258
|
+
* @param a - First summand, a valid BN254 field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
259
|
+
* @param b - Second summand, a valid BN254 field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
260
|
+
* @returns `(a + b) mod BN254_FIELD_PRIME` as a `Bn254FieldElement`.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* import { bn254Add, assertBn254FieldElement, BN254_FIELD_PRIME } from "@umbra/sdk";
|
|
265
|
+
*
|
|
266
|
+
* const a = 10n;
|
|
267
|
+
* const b = 20n;
|
|
268
|
+
* assertBn254FieldElement(a, "a");
|
|
269
|
+
* assertBn254FieldElement(b, "b");
|
|
270
|
+
*
|
|
271
|
+
* const sum = bn254Add(a, b);
|
|
272
|
+
* console.log(sum === 30n); // true
|
|
273
|
+
*
|
|
274
|
+
* // Demonstrates wraparound at the field boundary
|
|
275
|
+
* const nearPrime = BN254_FIELD_PRIME - 1n;
|
|
276
|
+
* assertBn254FieldElement(nearPrime, "nearPrime");
|
|
277
|
+
* const wrapped = bn254Add(nearPrime, b);
|
|
278
|
+
* // (p - 1 + 20) mod p = 19
|
|
279
|
+
* console.log(wrapped === 19n); // true
|
|
280
|
+
* ```
|
|
281
|
+
*
|
|
282
|
+
* @see {@link bn254Sub} For modular subtraction
|
|
283
|
+
* @see {@link bn254Mul} For modular multiplication
|
|
284
|
+
*
|
|
285
|
+
* @public
|
|
286
|
+
*/
|
|
287
|
+
declare function bn254Add(a: Bn254FieldElement, b: Bn254FieldElement): Bn254FieldElement;
|
|
288
|
+
/**
|
|
289
|
+
* Computes the difference of two BN254 scalar field elements modulo the field prime.
|
|
290
|
+
*
|
|
291
|
+
* @remarks
|
|
292
|
+
* ## Formula
|
|
293
|
+
*
|
|
294
|
+
* ```
|
|
295
|
+
* result = (a - b) mod BN254_FIELD_PRIME
|
|
296
|
+
* ```
|
|
297
|
+
*
|
|
298
|
+
* Because `a - b` can be negative when `b > a`, the result is obtained by
|
|
299
|
+
* adding the prime before taking the modulo to ensure canonicalization into
|
|
300
|
+
* `[0, p-1]`:
|
|
301
|
+
* ```
|
|
302
|
+
* diff = a - b
|
|
303
|
+
* result = ((diff % p) + p) % p
|
|
304
|
+
* ```
|
|
305
|
+
*
|
|
306
|
+
* This pattern handles both the case where `a >= b` (no wrap-around needed)
|
|
307
|
+
* and the case where `a < b` (wrap-around by adding `p`).
|
|
308
|
+
*
|
|
309
|
+
* @param a - Minuend, a valid BN254 field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
310
|
+
* @param b - Subtrahend, a valid BN254 field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
311
|
+
* @returns `(a - b) mod BN254_FIELD_PRIME` as a `Bn254FieldElement` in `[0, p-1]`.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* import { bn254Sub, assertBn254FieldElement, BN254_FIELD_PRIME } from "@umbra/sdk";
|
|
316
|
+
*
|
|
317
|
+
* const a = 30n;
|
|
318
|
+
* const b = 10n;
|
|
319
|
+
* assertBn254FieldElement(a, "a");
|
|
320
|
+
* assertBn254FieldElement(b, "b");
|
|
321
|
+
*
|
|
322
|
+
* const diff = bn254Sub(a, b);
|
|
323
|
+
* console.log(diff === 20n); // true
|
|
324
|
+
*
|
|
325
|
+
* // Underflow wraps around the field prime
|
|
326
|
+
* const small = 5n;
|
|
327
|
+
* assertBn254FieldElement(small, "small");
|
|
328
|
+
* const wrapped = bn254Sub(small, b);
|
|
329
|
+
* // (5 - 10 + p) mod p = p - 5
|
|
330
|
+
* console.log(wrapped === BN254_FIELD_PRIME - 5n); // true
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* @see {@link bn254Add} For modular addition
|
|
334
|
+
* @see {@link bn254Mul} For modular multiplication
|
|
335
|
+
*
|
|
336
|
+
* @public
|
|
337
|
+
*/
|
|
338
|
+
declare function bn254Sub(a: Bn254FieldElement, b: Bn254FieldElement): Bn254FieldElement;
|
|
339
|
+
/**
|
|
340
|
+
* Computes the product of two BN254 scalar field elements modulo the field prime.
|
|
341
|
+
*
|
|
342
|
+
* @remarks
|
|
343
|
+
* ## Formula
|
|
344
|
+
*
|
|
345
|
+
* ```
|
|
346
|
+
* result = (a * b) mod BN254_FIELD_PRIME
|
|
347
|
+
* ```
|
|
348
|
+
*
|
|
349
|
+
* Because both `a` and `b` are approximately 254-bit values, their product is
|
|
350
|
+
* approximately 508 bits before reduction. JavaScript's `bigint` type handles
|
|
351
|
+
* arbitrary precision arithmetic natively, so no overflow occurs. The result
|
|
352
|
+
* is reduced to `[0, p-1]` via a single `%` operation.
|
|
353
|
+
*
|
|
354
|
+
* ## Performance Note
|
|
355
|
+
*
|
|
356
|
+
* This function uses JavaScript's built-in `bigint` multiplication, which is not
|
|
357
|
+
* constant-time. For cryptographic contexts where timing side-channels are a
|
|
358
|
+
* concern (e.g., secret-key operations), use `bn254ModuloMul` from
|
|
359
|
+
* `field-arithmetic.ts` which uses constant-time Montgomery multiplication.
|
|
360
|
+
*
|
|
361
|
+
* @param a - First factor, a valid BN254 field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
362
|
+
* @param b - Second factor, a valid BN254 field element in `[0, BN254_FIELD_PRIME - 1]`.
|
|
363
|
+
* @returns `(a * b) mod BN254_FIELD_PRIME` as a `Bn254FieldElement`.
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```typescript
|
|
367
|
+
* import { bn254Mul, assertBn254FieldElement, BN254_FIELD_PRIME } from "@umbra/sdk";
|
|
368
|
+
*
|
|
369
|
+
* const a = 7n;
|
|
370
|
+
* const b = 8n;
|
|
371
|
+
* assertBn254FieldElement(a, "a");
|
|
372
|
+
* assertBn254FieldElement(b, "b");
|
|
373
|
+
*
|
|
374
|
+
* const product = bn254Mul(a, b);
|
|
375
|
+
* console.log(product === 56n); // true
|
|
376
|
+
*
|
|
377
|
+
* // Product of two large field elements wraps around
|
|
378
|
+
* const large = BN254_FIELD_PRIME - 1n;
|
|
379
|
+
* assertBn254FieldElement(large, "large");
|
|
380
|
+
* const result = bn254Mul(large, 2n as unknown as typeof large);
|
|
381
|
+
* // (p - 1) * 2 mod p = p - 2
|
|
382
|
+
* console.log(result === BN254_FIELD_PRIME - 2n); // true
|
|
383
|
+
* ```
|
|
384
|
+
*
|
|
385
|
+
* @see {@link bn254Add} For modular addition
|
|
386
|
+
* @see {@link bn254Sub} For modular subtraction
|
|
387
|
+
* @see {@link computeBn254ModularInverse} For multiplicative inverse (division)
|
|
388
|
+
*
|
|
389
|
+
* @public
|
|
390
|
+
*/
|
|
391
|
+
declare function bn254Mul(a: Bn254FieldElement, b: Bn254FieldElement): Bn254FieldElement;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* BN254 Field Arithmetic — Constant-Time Montgomery Implementation
|
|
395
|
+
*
|
|
396
|
+
* This module provides the core constant-time modular arithmetic operations for
|
|
397
|
+
* the BN254 (alt_bn128) scalar prime field F_r. It is the cryptographic foundation
|
|
398
|
+
* of the BN254 math layer and implements all five field operations:
|
|
399
|
+
*
|
|
400
|
+
* - Addition: `(a + b) mod p`
|
|
401
|
+
* - Subtraction: `(a - b) mod p`
|
|
402
|
+
* - Multiplication: `(a * b) mod p` (via Montgomery multiplication)
|
|
403
|
+
* - Negation: `-a mod p`
|
|
404
|
+
* - Multiplicative inverse: `a^(-1) mod p` (via Fermat + Montgomery exponentiation)
|
|
405
|
+
*
|
|
406
|
+
* Additionally, it exports getter functions that return stable cached instances of
|
|
407
|
+
* each operation, and a utility for computing the modular inverse of a Base85 limb sum.
|
|
408
|
+
*
|
|
409
|
+
* @remarks
|
|
410
|
+
* ## BN254 Scalar Field
|
|
411
|
+
*
|
|
412
|
+
* The BN254 elliptic curve (also called alt_bn128 in the Ethereum context) has a
|
|
413
|
+
* cyclic group of prime order:
|
|
414
|
+
* ```
|
|
415
|
+
* p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
|
|
416
|
+
* = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
417
|
+
* ```
|
|
418
|
+
* This prime has approximately 254 significant bits. Every arithmetic operation in
|
|
419
|
+
* Circom circuits, Groth16 proofs, and Poseidon hashes works modulo `p`.
|
|
420
|
+
*
|
|
421
|
+
* ## Constant-Time Design
|
|
422
|
+
*
|
|
423
|
+
* These implementations target *constant-operation-count* behavior, which is the
|
|
424
|
+
* achievable standard in JavaScript:
|
|
425
|
+
* - No data-dependent branching on secret values
|
|
426
|
+
* - All 4 limbs are always processed uniformly
|
|
427
|
+
* - Conditional selection uses bitwise masking (`ctSelect`)
|
|
428
|
+
* - Montgomery multiplication processes all iterations unconditionally
|
|
429
|
+
*
|
|
430
|
+
* True hardware-level constant time (immune to microarchitectural attacks such as
|
|
431
|
+
* cache-timing, branch prediction, and power analysis) is not achievable in JavaScript
|
|
432
|
+
* due to the JIT compiler and BigInt internals. However, this implementation avoids
|
|
433
|
+
* the most obvious timing leaks.
|
|
434
|
+
*
|
|
435
|
+
* ## 4-Limb (64-bit) Representation
|
|
436
|
+
*
|
|
437
|
+
* Values are stored as `[limb0, limb1, limb2, limb3]` in little-endian order:
|
|
438
|
+
* - `limb0`: bits 0–63 (least significant)
|
|
439
|
+
* - `limb1`: bits 64–127
|
|
440
|
+
* - `limb2`: bits 128–191
|
|
441
|
+
* - `limb3`: bits 192–255 (most significant)
|
|
442
|
+
*
|
|
443
|
+
* The reconstruction formula is:
|
|
444
|
+
* ```
|
|
445
|
+
* value = limb0 + limb1 * 2^64 + limb2 * 2^128 + limb3 * 2^192
|
|
446
|
+
* ```
|
|
447
|
+
*
|
|
448
|
+
* ## Montgomery Multiplication
|
|
449
|
+
*
|
|
450
|
+
* Multiplication uses the CIOS (Coarsely Integrated Operand Scanning) variant of
|
|
451
|
+
* Montgomery multiplication. Working in "Montgomery domain" (where each value `a`
|
|
452
|
+
* is stored as `aR mod p` for `R = 2^256`) allows the inner multiplication-and-reduction
|
|
453
|
+
* loop to avoid a full division by `p`. Instead, it uses a precomputed constant
|
|
454
|
+
* `p' = -p^(-1) mod 2^64` to make each output limb divisible by `2^64`, enabling
|
|
455
|
+
* a right-shift instead of a division.
|
|
456
|
+
*
|
|
457
|
+
* @see {@link ./types} BN254 field element types and validation
|
|
458
|
+
* @see {@link ./operations} Higher-level field operations (non-constant-time)
|
|
459
|
+
* @see {@link ./interfaces} Function type interfaces implemented here
|
|
460
|
+
* @see {@link ./field-element-sampler} Sampler that depends on this module
|
|
461
|
+
*
|
|
462
|
+
* @packageDocumentation
|
|
463
|
+
* @module math/bn254/field-arithmetic
|
|
464
|
+
*/
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Returns a stable, cached reference to the BN254 constant-time modular addition function.
|
|
468
|
+
*
|
|
469
|
+
* @remarks
|
|
470
|
+
* This getter exists to enable patterns where a function reference is stored once
|
|
471
|
+
* and passed around by reference (e.g., stored in a closure, passed as a dependency,
|
|
472
|
+
* or compared by identity). Every call returns the same `ModuloAddFunction` instance,
|
|
473
|
+
* avoiding unnecessary object allocation.
|
|
474
|
+
*
|
|
475
|
+
* Internally uses nullish coalescing assignment (`??=`) for lazy initialization:
|
|
476
|
+
* the cached value is set on the first call and reused on all subsequent calls.
|
|
477
|
+
*
|
|
478
|
+
* @returns The singleton `bn254ModuloAdd` function instance.
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```typescript
|
|
482
|
+
* import { getBn254ModularAdder } from "@umbra/sdk";
|
|
483
|
+
*
|
|
484
|
+
* const modAdd = getBn254ModularAdder();
|
|
485
|
+
*
|
|
486
|
+
* // Use as a named function
|
|
487
|
+
* const sum = modAdd(10n, 20n); // 30n
|
|
488
|
+
*
|
|
489
|
+
* // Same instance on every call — useful for referential equality checks
|
|
490
|
+
* const modAdd2 = getBn254ModularAdder();
|
|
491
|
+
* console.log(modAdd === modAdd2); // true
|
|
492
|
+
*
|
|
493
|
+
* // Pass as a dependency
|
|
494
|
+
* const sampler = getBn254FieldElementSampler({ modAdd });
|
|
495
|
+
* ```
|
|
496
|
+
*
|
|
497
|
+
* @see {@link bn254ModuloAdd} The underlying function
|
|
498
|
+
*
|
|
499
|
+
* @public
|
|
500
|
+
*/
|
|
501
|
+
declare function getBn254ModularAdder(): ModuloAddFunction;
|
|
502
|
+
/**
|
|
503
|
+
* Returns a stable, cached reference to the BN254 constant-time modular subtraction function.
|
|
504
|
+
*
|
|
505
|
+
* @remarks
|
|
506
|
+
* Uses the same lazy-initialization pattern as `getBn254ModularAdder`. Returns the
|
|
507
|
+
* same `bn254ModuloSub` instance on every call, enabling referential equality checks
|
|
508
|
+
* and efficient dependency injection.
|
|
509
|
+
*
|
|
510
|
+
* @returns The singleton `bn254ModuloSub` function instance.
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* ```typescript
|
|
514
|
+
* import { getBn254ModularSubtractor } from "@umbra/sdk";
|
|
515
|
+
*
|
|
516
|
+
* const modSub = getBn254ModularSubtractor();
|
|
517
|
+
* const diff = modSub(30n, 10n); // 20n
|
|
518
|
+
*
|
|
519
|
+
* // Referential equality guaranteed
|
|
520
|
+
* const modSub2 = getBn254ModularSubtractor();
|
|
521
|
+
* console.log(modSub === modSub2); // true
|
|
522
|
+
* ```
|
|
523
|
+
*
|
|
524
|
+
* @see {@link bn254ModuloSub} The underlying function
|
|
525
|
+
*
|
|
526
|
+
* @public
|
|
527
|
+
*/
|
|
528
|
+
declare function getBn254ModularSubtractor(): ModuloSubFunction;
|
|
529
|
+
/**
|
|
530
|
+
* Returns a stable, cached reference to the BN254 constant-time modular multiplication function.
|
|
531
|
+
*
|
|
532
|
+
* @remarks
|
|
533
|
+
* Uses the same lazy-initialization pattern as `getBn254ModularAdder`. Returns the
|
|
534
|
+
* same `bn254ModuloMul` instance on every call. The underlying function uses
|
|
535
|
+
* Montgomery multiplication internally.
|
|
536
|
+
*
|
|
537
|
+
* @returns The singleton `bn254ModuloMul` function instance.
|
|
538
|
+
*
|
|
539
|
+
* @example
|
|
540
|
+
* ```typescript
|
|
541
|
+
* import { getBn254ModularMultiplier } from "@umbra/sdk";
|
|
542
|
+
*
|
|
543
|
+
* const modMul = getBn254ModularMultiplier();
|
|
544
|
+
* const product = modMul(7n, 8n); // 56n
|
|
545
|
+
*
|
|
546
|
+
* // Referential equality guaranteed
|
|
547
|
+
* const modMul2 = getBn254ModularMultiplier();
|
|
548
|
+
* console.log(modMul === modMul2); // true
|
|
549
|
+
*
|
|
550
|
+
* // Pass as a dependency to the sampler
|
|
551
|
+
* const sampler = getBn254FieldElementSampler({ modMul });
|
|
552
|
+
* ```
|
|
553
|
+
*
|
|
554
|
+
* @see {@link bn254ModuloMul} The underlying Montgomery multiplication function
|
|
555
|
+
*
|
|
556
|
+
* @public
|
|
557
|
+
*/
|
|
558
|
+
declare function getBn254ModularMultiplier(): ModuloMulFunction;
|
|
559
|
+
/**
|
|
560
|
+
* Returns a stable, cached reference to the BN254 constant-time modular negation function.
|
|
561
|
+
*
|
|
562
|
+
* @remarks
|
|
563
|
+
* Uses the same lazy-initialization pattern as `getBn254ModularAdder`. Returns the
|
|
564
|
+
* same `bn254ModuloNeg` instance on every call.
|
|
565
|
+
*
|
|
566
|
+
* @returns The singleton `bn254ModuloNeg` function instance.
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* ```typescript
|
|
570
|
+
* import { getBn254ModularNegator, getBn254ModularAdder } from "@umbra/sdk";
|
|
571
|
+
*
|
|
572
|
+
* const modNeg = getBn254ModularNegator();
|
|
573
|
+
* const negated = modNeg(10n); // BN254_FIELD_PRIME - 10n
|
|
574
|
+
*
|
|
575
|
+
* // Verify: 10 + (-10) = 0
|
|
576
|
+
* const modAdd = getBn254ModularAdder();
|
|
577
|
+
* console.log(modAdd(10n, negated) === 0n); // true
|
|
578
|
+
*
|
|
579
|
+
* // Referential equality guaranteed
|
|
580
|
+
* const modNeg2 = getBn254ModularNegator();
|
|
581
|
+
* console.log(modNeg === modNeg2); // true
|
|
582
|
+
* ```
|
|
583
|
+
*
|
|
584
|
+
* @see {@link bn254ModuloNeg} The underlying function
|
|
585
|
+
*
|
|
586
|
+
* @public
|
|
587
|
+
*/
|
|
588
|
+
declare function getBn254ModularNegator(): ModuloNegFunction;
|
|
589
|
+
/**
|
|
590
|
+
* Returns a stable, cached reference to the BN254 modular multiplicative inverse function.
|
|
591
|
+
*
|
|
592
|
+
* @remarks
|
|
593
|
+
* Uses the same lazy-initialization pattern as `getBn254ModularAdder`. Returns the
|
|
594
|
+
* same `bn254ModuloInv` instance on every call. Note that `bn254ModuloInv` uses
|
|
595
|
+
* Fermat's Little Theorem with Montgomery exponentiation — it is significantly
|
|
596
|
+
* more expensive than addition, subtraction, or a single multiplication.
|
|
597
|
+
*
|
|
598
|
+
* @returns The singleton `bn254ModuloInv` function instance.
|
|
599
|
+
*
|
|
600
|
+
* @example
|
|
601
|
+
* ```typescript
|
|
602
|
+
* import { getBn254ModularInverter, getBn254ModularMultiplier } from "@umbra/sdk";
|
|
603
|
+
*
|
|
604
|
+
* const modInv = getBn254ModularInverter();
|
|
605
|
+
* const inverse = modInv(7n);
|
|
606
|
+
*
|
|
607
|
+
* // Verify: 7 * 7^(-1) = 1
|
|
608
|
+
* const modMul = getBn254ModularMultiplier();
|
|
609
|
+
* console.log(modMul(7n, inverse) === 1n); // true
|
|
610
|
+
*
|
|
611
|
+
* // Referential equality guaranteed
|
|
612
|
+
* const modInv2 = getBn254ModularInverter();
|
|
613
|
+
* console.log(modInv === modInv2); // true
|
|
614
|
+
* ```
|
|
615
|
+
*
|
|
616
|
+
* @see {@link bn254ModuloInv} The underlying Fermat-based inversion function
|
|
617
|
+
*
|
|
618
|
+
* @public
|
|
619
|
+
*/
|
|
620
|
+
declare function getBn254ModularInverter(): ModuloInvFunction;
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* BN254 Field Element Sampler Implementation
|
|
624
|
+
*
|
|
625
|
+
* This module provides a constant-time implementation for sampling BN254 scalar
|
|
626
|
+
* field elements from 512-bit big-endian byte arrays. The primary use case is
|
|
627
|
+
* deriving field elements from hash outputs (e.g., SHA-512, Keccak-512) or from
|
|
628
|
+
* concatenated CSPRNG outputs, as required by Fiat-Shamir transformations and
|
|
629
|
+
* key derivation in ZK proof systems.
|
|
630
|
+
*
|
|
631
|
+
* @remarks
|
|
632
|
+
* ## Why 512 Bits?
|
|
633
|
+
*
|
|
634
|
+
* The BN254 scalar field prime `p` is approximately `2^254`. If a 256-bit
|
|
635
|
+
* random value were mapped directly into the field via `value mod p`, there would
|
|
636
|
+
* be a statistical bias: the values in `[0, 2^256 mod p - 1]` would appear with
|
|
637
|
+
* probability `2/(floor(2^256 / p) + 1)`, while higher values appear with
|
|
638
|
+
* probability `1/(floor(2^256 / p) + 1)`. This bias is approximately `2^(-127)`,
|
|
639
|
+
* which is borderline for cryptographic applications.
|
|
640
|
+
*
|
|
641
|
+
* Using a 512-bit input reduces the maximum bias to approximately `2^(-254)`,
|
|
642
|
+
* which is cryptographically negligible for any practical security level.
|
|
643
|
+
*
|
|
644
|
+
* ## Algorithm
|
|
645
|
+
*
|
|
646
|
+
* Given a 512-bit big-endian input `h`, the module:
|
|
647
|
+
* 1. Splits `h` into two 256-bit halves (`high = h[0..31]`, `low = h[32..63]`)
|
|
648
|
+
* 2. Reduces both halves to `[0, p)` using constant-time trial subtraction (`reduce256`)
|
|
649
|
+
* 3. Computes `result = (high * R + low) mod p` where `R = 2^256 mod p`
|
|
650
|
+
* (the Montgomery constant for converting from 512-bit to field element)
|
|
651
|
+
*
|
|
652
|
+
* This is equivalent to interpreting the 512-bit value as an integer and reducing
|
|
653
|
+
* it modulo `p` in a constant-time manner.
|
|
654
|
+
*
|
|
655
|
+
* ## Constant-Time Guarantees
|
|
656
|
+
*
|
|
657
|
+
* All internal operations are constant-operation-count:
|
|
658
|
+
* - `ctSelect`: bitwise masking instead of branching
|
|
659
|
+
* - `bigintToLimbs` / `limbsToBigint`: fixed 4-limb operations
|
|
660
|
+
* - `conditionalSubtractP`: always subtracts and always selects (via mask)
|
|
661
|
+
* - `reduce256`: exactly 5 conditional subtractions, no early exit
|
|
662
|
+
*
|
|
663
|
+
* True hardware-level constant time cannot be guaranteed in JavaScript due to JIT
|
|
664
|
+
* compilation and BigInt internals, but the implementation avoids all data-dependent
|
|
665
|
+
* control flow.
|
|
666
|
+
*
|
|
667
|
+
* @see {@link ./interfaces.U512BasedBn254FieldElementSamplerFunction} Interface type
|
|
668
|
+
* @see {@link ./interfaces.U512BasedBn254FieldElementSamplerDeps} Dependency injection type
|
|
669
|
+
* @see {@link ./field-arithmetic} The constant-time modular arithmetic layer
|
|
670
|
+
*
|
|
671
|
+
* @packageDocumentation
|
|
672
|
+
* @module math/bn254/field-element-sampler
|
|
673
|
+
*/
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Creates a factory-configured U512-based BN254 field element sampler.
|
|
677
|
+
*
|
|
678
|
+
* Returns a closure that accepts a 64-byte big-endian byte array (`U512BeBytes`)
|
|
679
|
+
* and produces a uniformly distributed element of the BN254 scalar field.
|
|
680
|
+
*
|
|
681
|
+
* @param deps - Optional dependency injection for custom modular arithmetic.
|
|
682
|
+
* When omitted, uses the production constant-time implementations from
|
|
683
|
+
* `field-arithmetic.ts` (`bn254ModuloAdd` and `bn254ModuloMul`).
|
|
684
|
+
* @returns A `U512BasedBn254FieldElementSamplerFunction` closure bound to the
|
|
685
|
+
* provided (or default) arithmetic functions.
|
|
686
|
+
*
|
|
687
|
+
* @remarks
|
|
688
|
+
* ## Algorithm
|
|
689
|
+
*
|
|
690
|
+
* The returned sampler function, when invoked with a 64-byte input `h`:
|
|
691
|
+
*
|
|
692
|
+
* 1. **Split**: reads `high = h[0..31]` and `low = h[32..63]` as big-endian integers.
|
|
693
|
+
* 2. **Reduce**: calls `reduce256(high)` and `reduce256(low)` to bring both halves
|
|
694
|
+
* into `[0, p-1]` using constant-time trial subtraction.
|
|
695
|
+
* 3. **Combine**: computes `result = modMul(highReduced, R) + modAdd(lowReduced)`
|
|
696
|
+
* — i.e., `(high * R + low) mod p` — where `R = 2^256 mod p`.
|
|
697
|
+
*
|
|
698
|
+
* This is mathematically equivalent to:
|
|
699
|
+
* ```
|
|
700
|
+
* result = (h interpreted as a 512-bit big-endian integer) mod p
|
|
701
|
+
* ```
|
|
702
|
+
*
|
|
703
|
+
* ## Dependency Injection
|
|
704
|
+
*
|
|
705
|
+
* The `opts.modAdd` and `opts.modMul` overrides are applied to the final combine
|
|
706
|
+
* step (step 3). The `reduce256` step always uses the internal constant-time
|
|
707
|
+
* `conditionalSubtractP` regardless of injection. This design ensures that
|
|
708
|
+
* tests can substitute the combine arithmetic while keeping the reduction step
|
|
709
|
+
* deterministic.
|
|
710
|
+
*
|
|
711
|
+
* @example
|
|
712
|
+
* ```typescript
|
|
713
|
+
* import { getBn254FieldElementSampler } from "@umbra/sdk";
|
|
714
|
+
*
|
|
715
|
+
* // Default constant-time arithmetic
|
|
716
|
+
* const sampler = getBn254FieldElementSampler();
|
|
717
|
+
* const fieldElement = sampler(someU512Input);
|
|
718
|
+
*
|
|
719
|
+
* // Custom arithmetic for testing
|
|
720
|
+
* const testSampler = getBn254FieldElementSampler({
|
|
721
|
+
* modAdd: (a, b) => (a + b) % BN254_FIELD_PRIME,
|
|
722
|
+
* modMul: (a, b) => (a * b) % BN254_FIELD_PRIME,
|
|
723
|
+
* });
|
|
724
|
+
* ```
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* ```typescript
|
|
728
|
+
* // Deriving a field element from two concatenated SHA-256 hashes
|
|
729
|
+
* const hash1 = sha256(someData); // 32 bytes
|
|
730
|
+
* const hash2 = sha256(someOtherData); // 32 bytes
|
|
731
|
+
* const combined = new Uint8Array(64);
|
|
732
|
+
* combined.set(hash1, 0);
|
|
733
|
+
* combined.set(hash2, 32);
|
|
734
|
+
* assertU512BeBytes(combined);
|
|
735
|
+
*
|
|
736
|
+
* const sampler = getBn254FieldElementSampler();
|
|
737
|
+
* const fieldElement = sampler(combined);
|
|
738
|
+
* // fieldElement is a well-distributed BN254 field element derived from the hashes
|
|
739
|
+
* ```
|
|
740
|
+
*
|
|
741
|
+
* @see {@link bn254FieldElementSampler} Pre-instantiated default sampler
|
|
742
|
+
* @see {@link U512BasedBn254FieldElementSamplerDeps} Dependency injection interface
|
|
743
|
+
* @see {@link U512BasedBn254FieldElementSamplerFunction} The returned function type
|
|
744
|
+
*
|
|
745
|
+
* @public
|
|
746
|
+
*/
|
|
747
|
+
declare function getBn254FieldElementSampler(deps?: U512BasedBn254FieldElementSamplerDeps): U512BasedBn254FieldElementSamplerFunction;
|
|
748
|
+
/**
|
|
749
|
+
* The pre-instantiated default U512-based BN254 field element sampler.
|
|
750
|
+
*
|
|
751
|
+
* This is a convenience export of `getBn254FieldElementSampler()` with
|
|
752
|
+
* no arguments — using the default constant-time `bn254ModuloAdd` and
|
|
753
|
+
* `bn254ModuloMul` implementations from `field-arithmetic.ts`.
|
|
754
|
+
*
|
|
755
|
+
* @remarks
|
|
756
|
+
* Use this export directly when you do not need to inject custom arithmetic.
|
|
757
|
+
* It avoids the overhead of calling the factory function on every use.
|
|
758
|
+
*
|
|
759
|
+
* The sampler is stateless (it is a pure function of its input), so sharing this
|
|
760
|
+
* instance across multiple call sites is safe.
|
|
761
|
+
*
|
|
762
|
+
* @example
|
|
763
|
+
* ```typescript
|
|
764
|
+
* import { bn254FieldElementSampler } from "@umbra/sdk";
|
|
765
|
+
*
|
|
766
|
+
* // Produce a field element from a 64-byte CSPRNG output
|
|
767
|
+
* const randomBytes = crypto.getRandomValues(new Uint8Array(64));
|
|
768
|
+
* assertU512BeBytes(randomBytes);
|
|
769
|
+
* const fieldElement = bn254FieldElementSampler(randomBytes);
|
|
770
|
+
* // fieldElement is a uniformly distributed BN254 scalar field element
|
|
771
|
+
* ```
|
|
772
|
+
*
|
|
773
|
+
* @see {@link getBn254FieldElementSampler} The factory for custom configurations
|
|
774
|
+
* @see {@link U512BasedBn254FieldElementSamplerFunction} The function type
|
|
775
|
+
*
|
|
776
|
+
* @public
|
|
777
|
+
*/
|
|
778
|
+
declare const bn254FieldElementSampler: U512BasedBn254FieldElementSamplerFunction;
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Curve25519 Base Field Arithmetic — Concrete Implementation
|
|
782
|
+
*
|
|
783
|
+
* This module provides the constant-operation-count implementations of all
|
|
784
|
+
* modular arithmetic operations over the Curve25519 prime field GF(p), where:
|
|
785
|
+
* ```
|
|
786
|
+
* p = 2^255 - 19
|
|
787
|
+
* = 57896044618658097711785492504343953926634992332820282019728792003956564819949
|
|
788
|
+
* ```
|
|
789
|
+
*
|
|
790
|
+
* ## Role in the SDK
|
|
791
|
+
*
|
|
792
|
+
* This module is the lowest-level arithmetic layer in the SDK's cryptographic
|
|
793
|
+
* stack. Its exported functions are consumed by:
|
|
794
|
+
*
|
|
795
|
+
* - **`crypto/rescue-cipher/`** — the Rescue-XLIX block cipher used inside
|
|
796
|
+
* Arcium MPC computations for symmetric encryption of Umbra confidential
|
|
797
|
+
* token account balances.
|
|
798
|
+
* - **`math/curve25519/interfaces`** — the function-type contracts that the
|
|
799
|
+
* exported symbols satisfy.
|
|
800
|
+
* - Dependency-injection consumers that call
|
|
801
|
+
* `getCurve25519FieldElementSampler` with custom arithmetic.
|
|
802
|
+
*
|
|
803
|
+
* X25519 key-exchange itself (used for Umbra encrypted token account key
|
|
804
|
+
* registration) does not call this module directly — its scalar multiplication
|
|
805
|
+
* is handled by `@noble/curves` — but the field prime is the same.
|
|
806
|
+
*
|
|
807
|
+
* ## Algorithm Overview
|
|
808
|
+
*
|
|
809
|
+
* ### Addition / Subtraction
|
|
810
|
+
*
|
|
811
|
+
* Both operations are implemented at the 4-limb level using carry/borrow
|
|
812
|
+
* propagation, followed by a **constant-time conditional correction**:
|
|
813
|
+
*
|
|
814
|
+
* - **Addition**: compute `t = a + b`; if `t ≥ p` then return `t - p`, else `t`.
|
|
815
|
+
* The conditional is resolved by a bitwise mask derived from the carry and
|
|
816
|
+
* borrow, never an `if` statement.
|
|
817
|
+
* - **Subtraction**: compute `d = a - b`; if a borrow occurred (a < b), add `p`
|
|
818
|
+
* back. The borrow bit is propagated as a mask applied to `P_LIMBS`.
|
|
819
|
+
*
|
|
820
|
+
* ### Multiplication
|
|
821
|
+
*
|
|
822
|
+
* Uses JavaScript's native `BigInt` multiplication (`a * b`) followed by
|
|
823
|
+
* a single `% p` reduction. While this is not a limb-level schoolbook
|
|
824
|
+
* implementation, `BigInt` intermediate values of ≤ 510 bits keep the
|
|
825
|
+
* per-call work uniform. Montgomery form is not used because the constant
|
|
826
|
+
* conversion overhead is not amortised over the small number of multiplications
|
|
827
|
+
* per Rescue-XLIX round.
|
|
828
|
+
*
|
|
829
|
+
* ### Inversion
|
|
830
|
+
*
|
|
831
|
+
* Uses Fermat's Little Theorem: `a^(-1) ≡ a^(p-2) (mod p)`. This delegates to
|
|
832
|
+
* the square-and-multiply exponentiation function with a fixed exponent of
|
|
833
|
+
* p - 2 ≈ 2^255, costing ≈ 255 squarings and ~128 multiplications.
|
|
834
|
+
*
|
|
835
|
+
* ### Exponentiation
|
|
836
|
+
*
|
|
837
|
+
* Binary (square-and-multiply) exponentiation via `moduleExpLimbs`. The loop
|
|
838
|
+
* visits each bit of the exponent from LSB to MSB; the branch on the current
|
|
839
|
+
* bit (`exp & 1n`) operates on the **exponent**, not secret field data, so it
|
|
840
|
+
* does not constitute a secret-dependent branch.
|
|
841
|
+
*
|
|
842
|
+
* ## Security Considerations
|
|
843
|
+
*
|
|
844
|
+
* True hardware-level constant time cannot be guaranteed in JavaScript because
|
|
845
|
+
* the V8/SpiderMonkey JIT, branch predictors, and GC can all introduce
|
|
846
|
+
* data-dependent timing variation. These implementations are
|
|
847
|
+
* **constant-operation-count**: they always execute the same sequence of BigInt
|
|
848
|
+
* operations regardless of the input values. This is the accepted standard for
|
|
849
|
+
* JavaScript cryptographic libraries (e.g., `@noble/curves`).
|
|
850
|
+
*
|
|
851
|
+
* Secret-dependent branching is avoided by:
|
|
852
|
+
* - Using `ctSelect` (bitwise mask) for all conditional value choices.
|
|
853
|
+
* - Processing all 4 limbs in every loop iteration regardless of value.
|
|
854
|
+
* - Applying `P_LIMBS` correction via masking rather than a conditional add.
|
|
855
|
+
*
|
|
856
|
+
* ## Limb Representation
|
|
857
|
+
*
|
|
858
|
+
* All internal computation decomposes field elements into four 64-bit limbs
|
|
859
|
+
* stored in little-endian order `[limb0, limb1, limb2, limb3]`:
|
|
860
|
+
* ```
|
|
861
|
+
* value = limb0 + limb1×2^64 + limb2×2^128 + limb3×2^192
|
|
862
|
+
* ```
|
|
863
|
+
* - `limb0` — bits 0-63 (least significant)
|
|
864
|
+
* - `limb1` — bits 64-127
|
|
865
|
+
* - `limb2` — bits 128-191
|
|
866
|
+
* - `limb3` — bits 192-255 (most significant; high bit always 0 for valid elements)
|
|
867
|
+
*
|
|
868
|
+
* The 4-limb split keeps individual BigInt values at a uniform 64-bit size,
|
|
869
|
+
* making per-limb arithmetic cost independent of the field element's magnitude.
|
|
870
|
+
*
|
|
871
|
+
* @module implementation/mathematics/curve25519-field-arithmetic
|
|
872
|
+
* @packageDocumentation
|
|
873
|
+
*/
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Constant-operation-count modular addition for the Curve25519 base field.
|
|
877
|
+
*
|
|
878
|
+
* @remarks
|
|
879
|
+
* Computes the canonical field sum:
|
|
880
|
+
* ```
|
|
881
|
+
* result ≡ a + b (mod p), p = 2^255 - 19
|
|
882
|
+
* ```
|
|
883
|
+
*
|
|
884
|
+
* Implementation delegates to {@link addModuleLimbs} which performs the
|
|
885
|
+
* addition and conditional reduction entirely with bitwise masking — no
|
|
886
|
+
* data-dependent branches on `a` or `b`.
|
|
887
|
+
*
|
|
888
|
+
* This function satisfies {@link Curve25519ModuloAddFunction}.
|
|
889
|
+
*
|
|
890
|
+
* @param a - First field element. Must be in canonical range [0, p-1].
|
|
891
|
+
* @param b - Second field element. Must be in canonical range [0, p-1].
|
|
892
|
+
* @returns `(a + b) mod p` in canonical range [0, p-1].
|
|
893
|
+
*
|
|
894
|
+
* @example
|
|
895
|
+
* ```typescript
|
|
896
|
+
* import { curve25519ModuloAdd, CURVE25519_FIELD_PRIME } from "@umbra-privacy/sdk";
|
|
897
|
+
*
|
|
898
|
+
* // Basic addition
|
|
899
|
+
* const sum = curve25519ModuloAdd(10n, 20n);
|
|
900
|
+
* console.log(sum); // 30n
|
|
901
|
+
*
|
|
902
|
+
* // Wrap-around: p-1 + 1 = 0
|
|
903
|
+
* const wrap = curve25519ModuloAdd(CURVE25519_FIELD_PRIME - 1n, 1n);
|
|
904
|
+
* console.log(wrap); // 0n
|
|
905
|
+
* ```
|
|
906
|
+
*
|
|
907
|
+
* @see {@link curve25519ModuloSub} — complementary subtraction
|
|
908
|
+
* @see {@link getCurve25519ModularAddFunction} — returns a cached reference to this function
|
|
909
|
+
*
|
|
910
|
+
* @public
|
|
911
|
+
*/
|
|
912
|
+
declare const curve25519ModuloAdd: Curve25519ModuloAddFunction;
|
|
913
|
+
/**
|
|
914
|
+
* Constant-operation-count modular subtraction for the Curve25519 base field.
|
|
915
|
+
*
|
|
916
|
+
* @remarks
|
|
917
|
+
* Computes the canonical field difference:
|
|
918
|
+
* ```
|
|
919
|
+
* result ≡ a - b (mod p), p = 2^255 - 19
|
|
920
|
+
* ```
|
|
921
|
+
*
|
|
922
|
+
* When a < b the result wraps around: `a - b + p`, which is still in [0, p-1].
|
|
923
|
+
* Implementation delegates to {@link subModuleLimbs}, which adds p back via
|
|
924
|
+
* a borrow-derived bitmask rather than a conditional branch.
|
|
925
|
+
*
|
|
926
|
+
* This function satisfies {@link Curve25519ModuloSubFunction}.
|
|
927
|
+
*
|
|
928
|
+
* @param a - Minuend. Must be in canonical range [0, p-1].
|
|
929
|
+
* @param b - Subtrahend. Must be in canonical range [0, p-1].
|
|
930
|
+
* @returns `(a - b) mod p` in canonical range [0, p-1].
|
|
931
|
+
*
|
|
932
|
+
* @example
|
|
933
|
+
* ```typescript
|
|
934
|
+
* import { curve25519ModuloSub, CURVE25519_FIELD_PRIME } from "@umbra-privacy/sdk";
|
|
935
|
+
*
|
|
936
|
+
* // Normal subtraction
|
|
937
|
+
* const diff = curve25519ModuloSub(30n, 10n);
|
|
938
|
+
* console.log(diff); // 20n
|
|
939
|
+
*
|
|
940
|
+
* // Wrap-around: 0 - 1 = p - 1
|
|
941
|
+
* const wrap = curve25519ModuloSub(0n, 1n);
|
|
942
|
+
* console.log(wrap === CURVE25519_FIELD_PRIME - 1n); // true
|
|
943
|
+
* ```
|
|
944
|
+
*
|
|
945
|
+
* @see {@link curve25519ModuloAdd} — complementary addition
|
|
946
|
+
* @see {@link getCurve25519ModularSubFunction} — returns a cached reference to this function
|
|
947
|
+
*
|
|
948
|
+
* @public
|
|
949
|
+
*/
|
|
950
|
+
declare const curve25519ModuloSub: Curve25519ModuloSubFunction;
|
|
951
|
+
/**
|
|
952
|
+
* Modular multiplication for the Curve25519 base field.
|
|
953
|
+
*
|
|
954
|
+
* @remarks
|
|
955
|
+
* Computes the canonical field product:
|
|
956
|
+
* ```
|
|
957
|
+
* result ≡ a × b (mod p), p = 2^255 - 19
|
|
958
|
+
* ```
|
|
959
|
+
*
|
|
960
|
+
* Implementation converts both operands to full-precision `BigInt`, multiplies
|
|
961
|
+
* natively (producing a ≤ 510-bit intermediate), then reduces with `% p`.
|
|
962
|
+
* See {@link mulModuleLimbs} for rationale on why Montgomery form is not used.
|
|
963
|
+
*
|
|
964
|
+
* This function satisfies {@link Curve25519ModuloMulFunction}.
|
|
965
|
+
*
|
|
966
|
+
* @param a - First factor. Must be in canonical range [0, p-1].
|
|
967
|
+
* @param b - Second factor. Must be in canonical range [0, p-1].
|
|
968
|
+
* @returns `(a × b) mod p` in canonical range [0, p-1].
|
|
969
|
+
*
|
|
970
|
+
* @example
|
|
971
|
+
* ```typescript
|
|
972
|
+
* import { curve25519ModuloMul, CURVE25519_FIELD_PRIME } from "@umbra-privacy/sdk";
|
|
973
|
+
*
|
|
974
|
+
* // Basic multiplication
|
|
975
|
+
* const product = curve25519ModuloMul(7n, 8n);
|
|
976
|
+
* console.log(product); // 56n
|
|
977
|
+
*
|
|
978
|
+
* // Large value reduces modulo p
|
|
979
|
+
* const large = curve25519ModuloMul(CURVE25519_FIELD_PRIME - 1n, 2n);
|
|
980
|
+
* // (p-1) × 2 = 2p - 2 ≡ p - 2 (mod p)
|
|
981
|
+
* console.log(large === CURVE25519_FIELD_PRIME - 2n); // true
|
|
982
|
+
* ```
|
|
983
|
+
*
|
|
984
|
+
* @see {@link curve25519ModuloInv} — uses this function for inversion via Fermat's theorem
|
|
985
|
+
* @see {@link getCurve25519ModularMulFunction} — returns a cached reference to this function
|
|
986
|
+
*
|
|
987
|
+
* @public
|
|
988
|
+
*/
|
|
989
|
+
declare const curve25519ModuloMul: Curve25519ModuloMulFunction;
|
|
990
|
+
/**
|
|
991
|
+
* Modular multiplicative inverse for the Curve25519 base field.
|
|
992
|
+
*
|
|
993
|
+
* @remarks
|
|
994
|
+
* Computes the unique inverse such that:
|
|
995
|
+
* ```
|
|
996
|
+
* a × result ≡ 1 (mod p), p = 2^255 - 19
|
|
997
|
+
* ```
|
|
998
|
+
*
|
|
999
|
+
* ## Algorithm — Fermat's Little Theorem
|
|
1000
|
+
*
|
|
1001
|
+
* Because p is prime, Fermat's Little Theorem guarantees:
|
|
1002
|
+
* ```
|
|
1003
|
+
* a^(p-1) ≡ 1 (mod p) for all a ≠ 0
|
|
1004
|
+
* ```
|
|
1005
|
+
* Therefore:
|
|
1006
|
+
* ```
|
|
1007
|
+
* a^(-1) ≡ a^(p-2) (mod p)
|
|
1008
|
+
* ```
|
|
1009
|
+
*
|
|
1010
|
+
* The exponent p - 2 is a fixed protocol constant, so the square-and-multiply
|
|
1011
|
+
* loop in {@link moduleExpLimbs} does not branch on secret data.
|
|
1012
|
+
*
|
|
1013
|
+
* **Cost**: ≈ 255 squarings + ≈ 128 multiplications. For applications that call
|
|
1014
|
+
* inversion in a tight loop, a batch-inversion algorithm (Montgomery's trick)
|
|
1015
|
+
* can reduce the cost to 1 inversion + 3(n-1) multiplications for n elements.
|
|
1016
|
+
*
|
|
1017
|
+
* This function satisfies {@link Curve25519ModuloInvFunction}.
|
|
1018
|
+
*
|
|
1019
|
+
* @param a - The field element to invert. Must be in range [1, p-1].
|
|
1020
|
+
* Passing `0n` is a programming error — zero has no multiplicative inverse.
|
|
1021
|
+
* @returns The unique inverse `a^(-1) mod p` in range [1, p-1].
|
|
1022
|
+
* @throws {Error} If `a === 0n`. The error message is
|
|
1023
|
+
* `"Cannot compute modular inverse of zero"`.
|
|
1024
|
+
*
|
|
1025
|
+
* @example
|
|
1026
|
+
* ```typescript
|
|
1027
|
+
* import { curve25519ModuloInv, curve25519ModuloMul } from "@umbra-privacy/sdk";
|
|
1028
|
+
*
|
|
1029
|
+
* const a = 7n;
|
|
1030
|
+
* const invA = curve25519ModuloInv(a);
|
|
1031
|
+
*
|
|
1032
|
+
* // Verification: a × a^{-1} ≡ 1 (mod p)
|
|
1033
|
+
* const product = curve25519ModuloMul(a, invA);
|
|
1034
|
+
* console.log(product === 1n); // true
|
|
1035
|
+
*
|
|
1036
|
+
* // Throws for zero
|
|
1037
|
+
* try {
|
|
1038
|
+
* curve25519ModuloInv(0n);
|
|
1039
|
+
* } catch (e) {
|
|
1040
|
+
* console.log((e as Error).message); // "Cannot compute modular inverse of zero"
|
|
1041
|
+
* }
|
|
1042
|
+
* ```
|
|
1043
|
+
*
|
|
1044
|
+
* @see {@link curve25519ModuloPow} — the underlying exponentiation used internally
|
|
1045
|
+
* @see {@link getCurve25519ModularInvFunction} — returns a cached reference to this function
|
|
1046
|
+
*
|
|
1047
|
+
* @public
|
|
1048
|
+
*/
|
|
1049
|
+
declare const curve25519ModuloInv: Curve25519ModuloInvFunction;
|
|
1050
|
+
/**
|
|
1051
|
+
* Modular exponentiation for the Curve25519 base field.
|
|
1052
|
+
*
|
|
1053
|
+
* @remarks
|
|
1054
|
+
* Computes the field power:
|
|
1055
|
+
* ```
|
|
1056
|
+
* result ≡ base^exp (mod p), p = 2^255 - 19
|
|
1057
|
+
* ```
|
|
1058
|
+
*
|
|
1059
|
+
* Uses binary (square-and-multiply) exponentiation via {@link moduleExpLimbs}.
|
|
1060
|
+
* The special case `exp === 0n` is handled explicitly: `base^0 = 1` for all
|
|
1061
|
+
* `base`, including `base = 0`.
|
|
1062
|
+
*
|
|
1063
|
+
* This function satisfies {@link Curve25519ModuloPowFunction}.
|
|
1064
|
+
*
|
|
1065
|
+
* @param base - The base. Must be in canonical range [0, p-1].
|
|
1066
|
+
* @param exp - A non-negative `bigint` exponent.
|
|
1067
|
+
* @returns `base^exp mod p` in canonical range [0, p-1].
|
|
1068
|
+
*
|
|
1069
|
+
* @example
|
|
1070
|
+
* ```typescript
|
|
1071
|
+
* import { curve25519ModuloPow, CURVE25519_FIELD_PRIME } from "@umbra-privacy/sdk";
|
|
1072
|
+
*
|
|
1073
|
+
* // Small exponent
|
|
1074
|
+
* const r1 = curve25519ModuloPow(2n, 10n);
|
|
1075
|
+
* console.log(r1); // 1024n
|
|
1076
|
+
*
|
|
1077
|
+
* // Zero exponent: always 1
|
|
1078
|
+
* const r2 = curve25519ModuloPow(12345n, 0n);
|
|
1079
|
+
* console.log(r2); // 1n
|
|
1080
|
+
*
|
|
1081
|
+
* // Fermat's Little Theorem: a^(p-1) ≡ 1 for a ≠ 0
|
|
1082
|
+
* const r3 = curve25519ModuloPow(42n, CURVE25519_FIELD_PRIME - 1n);
|
|
1083
|
+
* console.log(r3); // 1n
|
|
1084
|
+
* ```
|
|
1085
|
+
*
|
|
1086
|
+
* @see {@link curve25519ModuloInv} — uses this with exponent p-2
|
|
1087
|
+
* @see {@link getCurve25519ModularPowFunction} — returns a cached reference to this function
|
|
1088
|
+
*
|
|
1089
|
+
* @public
|
|
1090
|
+
*/
|
|
1091
|
+
declare const curve25519ModuloPow: Curve25519ModuloPowFunction;
|
|
1092
|
+
/**
|
|
1093
|
+
* Returns a lazily cached reference to the Curve25519 modular addition function.
|
|
1094
|
+
*
|
|
1095
|
+
* @remarks
|
|
1096
|
+
* On the first call, stores `curve25519ModuloAdd` in the module-level cache
|
|
1097
|
+
* variable and returns it. Subsequent calls return the cached reference
|
|
1098
|
+
* without re-assignment. This pattern avoids redundant function object
|
|
1099
|
+
* allocation when the getter is called in a hot path.
|
|
1100
|
+
*
|
|
1101
|
+
* The returned function is identical to calling {@link curve25519ModuloAdd}
|
|
1102
|
+
* directly; the getter is provided for dependency-injection consumers that
|
|
1103
|
+
* accept a `Curve25519ModuloAddFunction` from a provider rather than
|
|
1104
|
+
* importing the concrete implementation.
|
|
1105
|
+
*
|
|
1106
|
+
* @returns The singleton `curve25519ModuloAdd` function.
|
|
1107
|
+
*
|
|
1108
|
+
* @example
|
|
1109
|
+
* ```typescript
|
|
1110
|
+
* import { getCurve25519ModularAddFunction } from "@umbra-privacy/sdk";
|
|
1111
|
+
*
|
|
1112
|
+
* const modAdd = getCurve25519ModularAddFunction();
|
|
1113
|
+
* const sum = modAdd(10n, 20n); // 30n
|
|
1114
|
+
* ```
|
|
1115
|
+
*
|
|
1116
|
+
* @see {@link curve25519ModuloAdd} — the underlying constant-time implementation
|
|
1117
|
+
*
|
|
1118
|
+
* @public
|
|
1119
|
+
*/
|
|
1120
|
+
declare function getCurve25519ModularAddFunction(): Curve25519ModuloAddFunction;
|
|
1121
|
+
/**
|
|
1122
|
+
* Returns a lazily cached reference to the Curve25519 modular subtraction function.
|
|
1123
|
+
*
|
|
1124
|
+
* @remarks
|
|
1125
|
+
* Follows the same lazy-caching pattern as {@link getCurve25519ModularAddFunction}.
|
|
1126
|
+
* The returned function is identical to calling {@link curve25519ModuloSub} directly.
|
|
1127
|
+
*
|
|
1128
|
+
* @returns The singleton `curve25519ModuloSub` function.
|
|
1129
|
+
*
|
|
1130
|
+
* @example
|
|
1131
|
+
* ```typescript
|
|
1132
|
+
* import { getCurve25519ModularSubFunction } from "@umbra-privacy/sdk";
|
|
1133
|
+
*
|
|
1134
|
+
* const modSub = getCurve25519ModularSubFunction();
|
|
1135
|
+
* const diff = modSub(30n, 10n); // 20n
|
|
1136
|
+
* ```
|
|
1137
|
+
*
|
|
1138
|
+
* @see {@link curve25519ModuloSub} — the underlying constant-time implementation
|
|
1139
|
+
*
|
|
1140
|
+
* @public
|
|
1141
|
+
*/
|
|
1142
|
+
declare function getCurve25519ModularSubFunction(): Curve25519ModuloSubFunction;
|
|
1143
|
+
/**
|
|
1144
|
+
* Returns a lazily cached reference to the Curve25519 modular multiplication function.
|
|
1145
|
+
*
|
|
1146
|
+
* @remarks
|
|
1147
|
+
* Follows the same lazy-caching pattern as {@link getCurve25519ModularAddFunction}.
|
|
1148
|
+
* The returned function is identical to calling {@link curve25519ModuloMul} directly.
|
|
1149
|
+
*
|
|
1150
|
+
* @returns The singleton `curve25519ModuloMul` function.
|
|
1151
|
+
*
|
|
1152
|
+
* @example
|
|
1153
|
+
* ```typescript
|
|
1154
|
+
* import { getCurve25519ModularMulFunction } from "@umbra-privacy/sdk";
|
|
1155
|
+
*
|
|
1156
|
+
* const modMul = getCurve25519ModularMulFunction();
|
|
1157
|
+
* const product = modMul(7n, 8n); // 56n
|
|
1158
|
+
* ```
|
|
1159
|
+
*
|
|
1160
|
+
* @see {@link curve25519ModuloMul} — the underlying implementation
|
|
1161
|
+
*
|
|
1162
|
+
* @public
|
|
1163
|
+
*/
|
|
1164
|
+
declare function getCurve25519ModularMulFunction(): Curve25519ModuloMulFunction;
|
|
1165
|
+
/**
|
|
1166
|
+
* Returns a lazily cached reference to the Curve25519 modular inverse function.
|
|
1167
|
+
*
|
|
1168
|
+
* @remarks
|
|
1169
|
+
* Follows the same lazy-caching pattern as {@link getCurve25519ModularAddFunction}.
|
|
1170
|
+
* The returned function is identical to calling {@link curve25519ModuloInv} directly.
|
|
1171
|
+
*
|
|
1172
|
+
* @returns The singleton `curve25519ModuloInv` function.
|
|
1173
|
+
*
|
|
1174
|
+
* @example
|
|
1175
|
+
* ```typescript
|
|
1176
|
+
* import { getCurve25519ModularInvFunction } from "@umbra-privacy/sdk";
|
|
1177
|
+
*
|
|
1178
|
+
* const modInv = getCurve25519ModularInvFunction();
|
|
1179
|
+
* const inverse = modInv(7n);
|
|
1180
|
+
* // modInv(7n) * 7n ≡ 1 (mod p)
|
|
1181
|
+
* ```
|
|
1182
|
+
*
|
|
1183
|
+
* @see {@link curve25519ModuloInv} — the underlying Fermat's theorem implementation
|
|
1184
|
+
*
|
|
1185
|
+
* @public
|
|
1186
|
+
*/
|
|
1187
|
+
declare function getCurve25519ModularInvFunction(): Curve25519ModuloInvFunction;
|
|
1188
|
+
/**
|
|
1189
|
+
* Returns a lazily cached reference to the Curve25519 modular exponentiation function.
|
|
1190
|
+
*
|
|
1191
|
+
* @remarks
|
|
1192
|
+
* Follows the same lazy-caching pattern as {@link getCurve25519ModularAddFunction}.
|
|
1193
|
+
* The returned function is identical to calling {@link curve25519ModuloPow} directly.
|
|
1194
|
+
*
|
|
1195
|
+
* @returns The singleton `curve25519ModuloPow` function.
|
|
1196
|
+
*
|
|
1197
|
+
* @example
|
|
1198
|
+
* ```typescript
|
|
1199
|
+
* import { getCurve25519ModularPowFunction } from "@umbra-privacy/sdk";
|
|
1200
|
+
*
|
|
1201
|
+
* const modPow = getCurve25519ModularPowFunction();
|
|
1202
|
+
* const result = modPow(2n, 10n); // 1024n
|
|
1203
|
+
* ```
|
|
1204
|
+
*
|
|
1205
|
+
* @see {@link curve25519ModuloPow} — the underlying square-and-multiply implementation
|
|
1206
|
+
*
|
|
1207
|
+
* @public
|
|
1208
|
+
*/
|
|
1209
|
+
declare function getCurve25519ModularPowFunction(): Curve25519ModuloPowFunction;
|
|
1210
|
+
/**
|
|
1211
|
+
* Factory that creates a sampler converting 512-bit big-endian byte arrays to
|
|
1212
|
+
* uniformly distributed Curve25519 field elements.
|
|
1213
|
+
*
|
|
1214
|
+
* @remarks
|
|
1215
|
+
* ## Purpose
|
|
1216
|
+
*
|
|
1217
|
+
* Hash-to-field algorithms produce 512-bit outputs to avoid statistical bias
|
|
1218
|
+
* when mapping into the 255-bit field. This factory encapsulates the standard
|
|
1219
|
+
* two-half combination technique (see below), returning a closure that can be
|
|
1220
|
+
* used repeatedly.
|
|
1221
|
+
*
|
|
1222
|
+
* ## Algorithm
|
|
1223
|
+
*
|
|
1224
|
+
* Given a 64-byte big-endian input array:
|
|
1225
|
+
*
|
|
1226
|
+
* 1. **Split** into two 256-bit halves:
|
|
1227
|
+
* - `high = input[0..31]` (most significant)
|
|
1228
|
+
* - `low = input[32..63]` (least significant)
|
|
1229
|
+
*
|
|
1230
|
+
* 2. **Reduce** each half into [0, p) via constant-time trial subtraction
|
|
1231
|
+
* (`reduce256Curve25519`).
|
|
1232
|
+
*
|
|
1233
|
+
* 3. **Combine** using the precomputed constant R = 2^256 mod p = 38:
|
|
1234
|
+
* ```
|
|
1235
|
+
* result = (highReduced × R + lowReduced) mod p
|
|
1236
|
+
* ```
|
|
1237
|
+
*
|
|
1238
|
+
* ## Customization via `deps`
|
|
1239
|
+
*
|
|
1240
|
+
* The `modAdd` and `modMul` slots in `deps` allow replacing the default
|
|
1241
|
+
* constant-time implementations with alternatives. Common use cases:
|
|
1242
|
+
* - Inject test stubs to exercise the combination logic in isolation.
|
|
1243
|
+
* - Use a faster non-constant-time implementation for offline tooling.
|
|
1244
|
+
*
|
|
1245
|
+
* ## Uniformity
|
|
1246
|
+
*
|
|
1247
|
+
* The bias of the result is bounded by p / 2^512 < 2^-257, which is
|
|
1248
|
+
* negligible for all practical cryptographic purposes.
|
|
1249
|
+
*
|
|
1250
|
+
* @param deps - Optional overrides for modular arithmetic. If omitted, uses
|
|
1251
|
+
* the default constant-time SDK implementations.
|
|
1252
|
+
* @returns A closure `(input: U512BeBytes) => Curve25519FieldElement`.
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* ```typescript
|
|
1256
|
+
* import { getCurve25519FieldElementSampler } from "@umbra-privacy/sdk";
|
|
1257
|
+
*
|
|
1258
|
+
* // Default: uses SDK constant-time arithmetic
|
|
1259
|
+
* const sampler = getCurve25519FieldElementSampler();
|
|
1260
|
+
*
|
|
1261
|
+
* const input = crypto.getRandomValues(new Uint8Array(64)) as U512BeBytes;
|
|
1262
|
+
* const element = sampler(input);
|
|
1263
|
+
* // element is a valid Curve25519FieldElement in [0, p-1]
|
|
1264
|
+
*
|
|
1265
|
+
* // With custom multiplication for testing
|
|
1266
|
+
* const testSampler = getCurve25519FieldElementSampler({
|
|
1267
|
+
* modMul: (a, b) => (a * b) % ((1n << 255n) - 19n),
|
|
1268
|
+
* });
|
|
1269
|
+
* ```
|
|
1270
|
+
*
|
|
1271
|
+
* @see {@link curve25519FieldElementSampler} — pre-built default instance
|
|
1272
|
+
* @see {@link U512BasedCurve25519FieldElementSamplerDeps} — the dependency injection bag
|
|
1273
|
+
* @see {@link U512BasedCurve25519FieldElementSamplerFunction} — the returned function's type
|
|
1274
|
+
*
|
|
1275
|
+
* @public
|
|
1276
|
+
*/
|
|
1277
|
+
declare function getCurve25519FieldElementSampler(deps?: U512BasedCurve25519FieldElementSamplerDeps): U512BasedCurve25519FieldElementSamplerFunction;
|
|
1278
|
+
/**
|
|
1279
|
+
* Pre-instantiated U512-to-field-element sampler using the default
|
|
1280
|
+
* constant-time Curve25519 field arithmetic.
|
|
1281
|
+
*
|
|
1282
|
+
* @remarks
|
|
1283
|
+
* This is a convenience export for callers that do not need to inject custom
|
|
1284
|
+
* arithmetic. It is equivalent to calling:
|
|
1285
|
+
* ```typescript
|
|
1286
|
+
* getCurve25519FieldElementSampler()
|
|
1287
|
+
* ```
|
|
1288
|
+
* but avoids the factory call overhead for the common case.
|
|
1289
|
+
*
|
|
1290
|
+
* ## Typical Usage Pattern
|
|
1291
|
+
*
|
|
1292
|
+
* Hash-to-field: pass the 512-bit output of a wide hash (SHA-512, BLAKE2b-512,
|
|
1293
|
+
* HKDF output, etc.) directly to this sampler to obtain a uniformly distributed
|
|
1294
|
+
* field element:
|
|
1295
|
+
* ```
|
|
1296
|
+
* fieldElement = sampler(sha512(domainSeparator || message))
|
|
1297
|
+
* ```
|
|
1298
|
+
*
|
|
1299
|
+
* This pattern is used internally in the Umbra SDK wherever a scalar must be
|
|
1300
|
+
* derived deterministically from a secret without bias.
|
|
1301
|
+
*
|
|
1302
|
+
* @param input - A 64-byte big-endian byte array (`U512BeBytes`).
|
|
1303
|
+
* @returns A `Curve25519FieldElement` in the canonical range [0, p-1].
|
|
1304
|
+
*
|
|
1305
|
+
* @example
|
|
1306
|
+
* ```typescript
|
|
1307
|
+
* import { curve25519FieldElementSampler } from "@umbra-privacy/sdk";
|
|
1308
|
+
*
|
|
1309
|
+
* // All-zero input → deterministic result (== 0n)
|
|
1310
|
+
* const zeroInput = new Uint8Array(64) as U512BeBytes;
|
|
1311
|
+
* const element = curve25519FieldElementSampler(zeroInput);
|
|
1312
|
+
* console.log(element); // 0n
|
|
1313
|
+
*
|
|
1314
|
+
* // Random 64-byte input from a CSPRNG
|
|
1315
|
+
* const randomInput = crypto.getRandomValues(new Uint8Array(64)) as U512BeBytes;
|
|
1316
|
+
* const randomElement = curve25519FieldElementSampler(randomInput);
|
|
1317
|
+
* // randomElement is uniformly distributed in [0, p-1]
|
|
1318
|
+
* ```
|
|
1319
|
+
*
|
|
1320
|
+
* @see {@link getCurve25519FieldElementSampler} — factory for custom arithmetic
|
|
1321
|
+
* @see {@link U512BasedCurve25519FieldElementSamplerFunction} — the function type
|
|
1322
|
+
*
|
|
1323
|
+
* @public
|
|
1324
|
+
*/
|
|
1325
|
+
declare const curve25519FieldElementSampler: U512BasedCurve25519FieldElementSamplerFunction;
|
|
1326
|
+
|
|
1327
|
+
export { bn254Add, bn254FieldElementSampler, bn254ModuloPow, bn254Mul, bn254Sub, computeBn254LimbwiseSumInverse, computeBn254ModularInverse, curve25519FieldElementSampler, curve25519ModuloAdd, curve25519ModuloInv, curve25519ModuloMul, curve25519ModuloPow, curve25519ModuloSub, getBn254FieldElementSampler, getBn254ModularAdder, getBn254ModularInverter, getBn254ModularMultiplier, getBn254ModularNegator, getBn254ModularSubtractor, getCurve25519FieldElementSampler, getCurve25519ModularAddFunction, getCurve25519ModularInvFunction, getCurve25519ModularMulFunction, getCurve25519ModularPowFunction, getCurve25519ModularSubFunction };
|