@bitgo-beta/sdk-lib-mpc 8.2.1-alpha.42 → 8.2.1-alpha.43
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/CHANGELOG.md +32 -0
- package/dist/src/tss/ecdsa/index.d.ts +2 -5
- package/dist/src/tss/ecdsa/index.d.ts.map +1 -1
- package/dist/src/tss/ecdsa/index.js +4 -10
- package/dist/src/tss/ecdsa/{paillierProof.d.ts → paillierproof.d.ts} +1 -1
- package/dist/src/tss/ecdsa/{paillierProof.d.ts.map → paillierproof.d.ts.map} +1 -1
- package/dist/src/tss/ecdsa/{paillierProof.js → paillierproof.js} +1 -1
- package/dist/src/tss/ecdsa/{rangeProof.d.ts → rangeproof.d.ts} +1 -1
- package/dist/src/tss/ecdsa/{rangeProof.d.ts.map → rangeproof.d.ts.map} +1 -1
- package/dist/src/tss/ecdsa/{rangeProof.js → rangeproof.js} +1 -1
- package/dist/src/tss/ecdsa/types.d.ts +0 -52
- package/dist/src/tss/ecdsa/types.d.ts.map +1 -1
- package/dist/src/tss/ecdsa/types.js +3 -70
- package/dist/src/util.d.ts +0 -2
- package/dist/src/util.d.ts.map +1 -1
- package/dist/src/util.js +2 -45
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -3
- package/dist/src/tss/ecdsa/generatePaillierKey.d.ts +0 -6
- package/dist/src/tss/ecdsa/generatePaillierKey.d.ts.map +0 -1
- package/dist/src/tss/ecdsa/generatePaillierKey.js +0 -52
- package/dist/src/tss/ecdsa/noSmallFactorsProof.d.ts +0 -24
- package/dist/src/tss/ecdsa/noSmallFactorsProof.d.ts.map +0 -1
- package/dist/src/tss/ecdsa/noSmallFactorsProof.js +0 -159
- package/dist/src/tss/ecdsa/paillierBlumProof.d.ts +0 -16
- package/dist/src/tss/ecdsa/paillierBlumProof.d.ts.map +0 -1
- package/dist/src/tss/ecdsa/paillierBlumProof.js +0 -174
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.verify = exports.prove = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Implementation of No Small Factors ($\Pi^\text{fac}).
|
|
6
|
-
* https://eprint.iacr.org/2020/492.pdf Section B.4
|
|
7
|
-
*/
|
|
8
|
-
const crypto_1 = require("crypto");
|
|
9
|
-
const bigint_crypto_utils_1 = require("bigint-crypto-utils");
|
|
10
|
-
const bigint_mod_arith_1 = require("bigint-mod-arith");
|
|
11
|
-
const util_1 = require("../../util");
|
|
12
|
-
const ORDER = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
|
|
13
|
-
const ELL = BigInt(256);
|
|
14
|
-
const EPSILON = BigInt(BigInt(2) * ELL);
|
|
15
|
-
function hash(N, w, nonce) {
|
|
16
|
-
// NOTE: There's a bug in node type file for crypto that prevents us from using Hash.copy({ outputLength: ... })
|
|
17
|
-
// outputLength must be specified on the copy() for a shake256 hash to behave correctly.
|
|
18
|
-
// On the other hand, since it's very likely that the first hash will fall in the desired range, using
|
|
19
|
-
// Hash.copy() to save on repeated calling update(`${N}$${w}$`) may not be worth it.
|
|
20
|
-
return crypto_1.createHash('shake256', { outputLength: 1 + Math.floor((bigint_crypto_utils_1.bitLength(ORDER) + 7) / 8) })
|
|
21
|
-
.update(util_1.bigIntToBufferBE(N))
|
|
22
|
-
.update('$')
|
|
23
|
-
.update(util_1.bigIntToBufferBE(w))
|
|
24
|
-
.update('$')
|
|
25
|
-
.update(nonce)
|
|
26
|
-
.digest();
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Generate pseudo-random challenge value $e$ and associated $nonce$ for $(N, w)$.
|
|
30
|
-
* @param N - the prime number to verify is a product of two large primes.
|
|
31
|
-
* @param w - a random number with the same bitLength as N, that satisfies the Jacobi of w is -1 wrt N.
|
|
32
|
-
* @returns {nonce, e} - challenge value $e$ and associated $nonce$ that makes $e$ uniformly random from $(-order, order)$.
|
|
33
|
-
*/
|
|
34
|
-
function generateEforProve(N, w) {
|
|
35
|
-
let nonce, e, digest;
|
|
36
|
-
do {
|
|
37
|
-
nonce = crypto_1.randomBytes(33);
|
|
38
|
-
digest = hash(N, w, nonce);
|
|
39
|
-
e = util_1.bigIntFromBufferBE(digest.subarray(1));
|
|
40
|
-
} while (e >= ORDER);
|
|
41
|
-
if (digest[0] & 1) {
|
|
42
|
-
return { nonce, e: -e };
|
|
43
|
-
}
|
|
44
|
-
return { nonce, e };
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Generate pseudo-random challenge value $e$ for $(N, w)$ and associated $nonce$.
|
|
48
|
-
* @param N - the prime number to verify is a product of two large primes.
|
|
49
|
-
* @param w - a random number with the same bitLength as N, that satisfies the Jacobi of w is -1 wrt N.
|
|
50
|
-
* @param nonce - a random nonce.
|
|
51
|
-
* @returns {bigint} - challenge value $e$.
|
|
52
|
-
*/
|
|
53
|
-
function generateEforVerify(N, w, nonce) {
|
|
54
|
-
const digest = hash(N, w, nonce);
|
|
55
|
-
const e = util_1.bigIntFromBufferBE(digest.subarray(1));
|
|
56
|
-
if (digest[0] & 1) {
|
|
57
|
-
return -e;
|
|
58
|
-
}
|
|
59
|
-
return e;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Calculate the closest integer square root of $n$.
|
|
63
|
-
* @param n - the number to calculate the square root of.
|
|
64
|
-
* @returns {bigint} - $n$'s closest integer square root.
|
|
65
|
-
*/
|
|
66
|
-
function isqrt(n) {
|
|
67
|
-
if (n < BigInt(0)) {
|
|
68
|
-
throw new Error();
|
|
69
|
-
}
|
|
70
|
-
if (n < BigInt(2)) {
|
|
71
|
-
return n;
|
|
72
|
-
}
|
|
73
|
-
function newtonIteration(n, x0) {
|
|
74
|
-
const x1 = (n / x0 + x0) >> BigInt(1);
|
|
75
|
-
if (x0 === x1 || x0 === x1 - BigInt(1)) {
|
|
76
|
-
return x0;
|
|
77
|
-
}
|
|
78
|
-
return newtonIteration(n, x1);
|
|
79
|
-
}
|
|
80
|
-
return newtonIteration(n, BigInt(1));
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Prove that $n0$ has no small factors, where $n0$ is the product of two large primes.
|
|
84
|
-
* @param p - a large prime.
|
|
85
|
-
* @param q - a large prime.
|
|
86
|
-
* @param w - a random number with the same bitLength as $p * q$, that satisfies the Jacobi of w is -1 wrt $n0$.
|
|
87
|
-
* @param nHat - a safe bi-prime, such as that returned from rangeProof.generateNTilde.
|
|
88
|
-
* @param s - security parameters for $nHat$ such as the $h1$ value returned from rangeProof.generateNTilde.
|
|
89
|
-
* @param t - security parameters for $nHat$ such as the $h2$ value returned from rangeProof.generateNTilde.
|
|
90
|
-
* @returns proof that the product of $p * q$ has no small factors.
|
|
91
|
-
*/
|
|
92
|
-
function prove(p, q, w, nHat, s, t) {
|
|
93
|
-
const n0 = p * q;
|
|
94
|
-
const { nonce, e } = generateEforProve(n0, w);
|
|
95
|
-
const sqrtN0 = isqrt(n0);
|
|
96
|
-
const alpha = bigint_crypto_utils_1.randBetween(sqrtN0 << (ELL + EPSILON), -sqrtN0 << (ELL + EPSILON));
|
|
97
|
-
const beta = bigint_crypto_utils_1.randBetween(sqrtN0 << (ELL + EPSILON), -sqrtN0 << (ELL + EPSILON));
|
|
98
|
-
const rho = bigint_crypto_utils_1.randBetween((nHat * n0) << ELL, -(nHat * n0) << ELL);
|
|
99
|
-
// Commit to p.
|
|
100
|
-
const mu = bigint_crypto_utils_1.randBetween(nHat << ELL, -nHat << ELL);
|
|
101
|
-
const P = (bigint_mod_arith_1.modPow(s, p, nHat) * bigint_mod_arith_1.modPow(t, mu, nHat)) % nHat;
|
|
102
|
-
// Commit to q.
|
|
103
|
-
const nu = bigint_crypto_utils_1.randBetween(nHat << ELL, -nHat << ELL);
|
|
104
|
-
const Q = (bigint_mod_arith_1.modPow(s, q, nHat) * bigint_mod_arith_1.modPow(t, nu, nHat)) % nHat;
|
|
105
|
-
// Commit to alpha.
|
|
106
|
-
const x = bigint_crypto_utils_1.randBetween(nHat << (ELL + EPSILON), -nHat << (ELL + EPSILON));
|
|
107
|
-
const A = (bigint_mod_arith_1.modPow(s, alpha, nHat) * bigint_mod_arith_1.modPow(t, x, nHat)) % nHat;
|
|
108
|
-
// Commit to beta.
|
|
109
|
-
const y = bigint_crypto_utils_1.randBetween(nHat << (ELL + EPSILON), -nHat << (ELL + EPSILON));
|
|
110
|
-
const B = (bigint_mod_arith_1.modPow(s, beta, nHat) * bigint_mod_arith_1.modPow(t, y, nHat)) % nHat;
|
|
111
|
-
// Commit to Q and alpha.
|
|
112
|
-
const r = bigint_crypto_utils_1.randBetween((nHat * n0) << (ELL + EPSILON), -(nHat * n0) << (ELL + EPSILON));
|
|
113
|
-
const T = (bigint_mod_arith_1.modPow(Q, alpha, nHat) * bigint_mod_arith_1.modPow(t, r, nHat)) % nHat;
|
|
114
|
-
const rhoHat = rho - nu * p;
|
|
115
|
-
const z1 = alpha + e * p;
|
|
116
|
-
const z2 = beta + e * q;
|
|
117
|
-
const w1 = x + e * mu;
|
|
118
|
-
const w2 = y + e * nu;
|
|
119
|
-
const v = r + e * rhoHat;
|
|
120
|
-
return { P, Q, A, B, T, rho, z1, z2, w1, w2, v, nonce: util_1.bigIntFromBufferBE(nonce) };
|
|
121
|
-
}
|
|
122
|
-
exports.prove = prove;
|
|
123
|
-
/**
|
|
124
|
-
* Verify that $n0$ is not the product of any small factors.
|
|
125
|
-
* @param n0 - a modulus that is the product of $p$ and $q$.
|
|
126
|
-
* @param w - a random number with the same bitLength as $n0$, that satisfies the Jacobi of w is -1 wrt $n0$.
|
|
127
|
-
* @param nHat - a safe bi-prime, such as that returned from rangeProof.generateNTilde.
|
|
128
|
-
* @param s - security parameters for $nHat$ such as the $h1$ value returned from rangeProof.generateNTilde.
|
|
129
|
-
* @param t - security parameters for $nHat$ such as the $h2$ value returned from rangeProof.generateNTilde.
|
|
130
|
-
* @param proof - a proof generated by noSmallFactors.prove.
|
|
131
|
-
* @returns true if verification successful.
|
|
132
|
-
*/
|
|
133
|
-
function verify(n0, w, nHat, s, t, proof) {
|
|
134
|
-
const { P, Q, A, B, T, rho, z1, z2, w1, w2, v, nonce } = proof;
|
|
135
|
-
const e = generateEforVerify(n0, w, util_1.bigIntToBufferBE(nonce, 33));
|
|
136
|
-
if (e < -ORDER || e > ORDER) {
|
|
137
|
-
throw new Error('Could not verify no small factors proof');
|
|
138
|
-
}
|
|
139
|
-
const sqrtN0 = isqrt(n0);
|
|
140
|
-
const R = (bigint_mod_arith_1.modPow(s, n0, nHat) * bigint_mod_arith_1.modPow(t, rho, nHat)) % nHat;
|
|
141
|
-
if ((bigint_mod_arith_1.modPow(s, z1, nHat) * bigint_mod_arith_1.modPow(t, w1, nHat)) % nHat !== (A * bigint_mod_arith_1.modPow(P, e, nHat)) % nHat) {
|
|
142
|
-
throw new Error('Could not verify no small factors proof');
|
|
143
|
-
}
|
|
144
|
-
if ((bigint_mod_arith_1.modPow(s, z2, nHat) * bigint_mod_arith_1.modPow(t, w2, nHat)) % nHat !== (B * bigint_mod_arith_1.modPow(Q, e, nHat)) % nHat) {
|
|
145
|
-
throw new Error('Could not verify no small factors proof');
|
|
146
|
-
}
|
|
147
|
-
if ((bigint_mod_arith_1.modPow(Q, z1, nHat) * bigint_mod_arith_1.modPow(t, v, nHat)) % nHat !== (T * bigint_mod_arith_1.modPow(R, e, nHat)) % nHat) {
|
|
148
|
-
throw new Error('Could not verify no small factors proof');
|
|
149
|
-
}
|
|
150
|
-
if (z1 < -sqrtN0 << (ELL + EPSILON) || z1 > sqrtN0 << (ELL + EPSILON)) {
|
|
151
|
-
throw new Error('Could not verify no small factors proof');
|
|
152
|
-
}
|
|
153
|
-
if (z2 < -sqrtN0 << (ELL + EPSILON) || z2 > sqrtN0 << (ELL + EPSILON)) {
|
|
154
|
-
throw new Error('Could not verify no small factors proof');
|
|
155
|
-
}
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
exports.verify = verify;
|
|
159
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9TbWFsbEZhY3RvcnNQcm9vZi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy90c3MvZWNkc2Evbm9TbWFsbEZhY3RvcnNQcm9vZi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7O0dBR0c7QUFDSCxtQ0FBaUQ7QUFDakQsNkRBQTZEO0FBQzdELHVEQUEwQztBQUMxQyxxQ0FBa0U7QUFHbEUsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLG9FQUFvRSxDQUFDLENBQUM7QUFDM0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3hCLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7QUFFeEMsU0FBUyxJQUFJLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFBRSxLQUFhO0lBQy9DLGdIQUFnSDtJQUNoSCw4RkFBOEY7SUFDOUYsNEdBQTRHO0lBQzVHLDBGQUEwRjtJQUMxRixPQUFPLG1CQUFVLENBQUMsVUFBVSxFQUFFLEVBQUUsWUFBWSxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsK0JBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ3hGLE1BQU0sQ0FBQyx1QkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUMzQixNQUFNLENBQUMsR0FBRyxDQUFDO1NBQ1gsTUFBTSxDQUFDLHVCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzNCLE1BQU0sQ0FBQyxHQUFHLENBQUM7U0FDWCxNQUFNLENBQUMsS0FBSyxDQUFDO1NBQ2IsTUFBTSxFQUFFLENBQUM7QUFDZCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGlCQUFpQixDQUFDLENBQVMsRUFBRSxDQUFTO0lBQzdDLElBQUksS0FBYSxFQUFFLENBQVMsRUFBRSxNQUFjLENB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KipcbiAqIEltcGxlbWVudGF0aW9uIG9mIE5vIFNtYWxsIEZhY3RvcnMgKCRcXFBpXlxcdGV4dHtmYWN9KS5cbiAqIGh0dHBzOi8vZXByaW50LmlhY3Iub3JnLzIwMjAvNDkyLnBkZiBTZWN0aW9uIEIuNFxuICovXG5pbXBvcnQgeyBjcmVhdGVIYXNoLCByYW5kb21CeXRlcyB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBiaXRMZW5ndGgsIHJhbmRCZXR3ZWVuIH0gZnJvbSAnYmlnaW50LWNyeXB0by11dGlscyc7XG5pbXBvcnQgeyBtb2RQb3cgfSBmcm9tICdiaWdpbnQtbW9kLWFyaXRoJztcbmltcG9ydCB7IGJpZ0ludEZyb21CdWZmZXJCRSwgYmlnSW50VG9CdWZmZXJCRSB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgRGVzZXJpYWxpemVkTm9TbWFsbEZhY3RvcnNQcm9vZiB9IGZyb20gJy4vdHlwZXMnO1xuXG5jb25zdCBPUkRFUiA9IEJpZ0ludCgnMHhmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZWJhYWVkY2U2YWY0OGEwM2JiZmQyNWU4Y2QwMzY0MTQxJyk7XG5jb25zdCBFTEwgPSBCaWdJbnQoMjU2KTtcbmNvbnN0IEVQU0lMT04gPSBCaWdJbnQoQmlnSW50KDIpICogRUxMKTtcblxuZnVuY3Rpb24gaGFzaChOOiBiaWdpbnQsIHc6IGJpZ2ludCwgbm9uY2U6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gIC8vIE5PVEU6IFRoZXJlJ3MgYSBidWcgaW4gbm9kZSB0eXBlIGZpbGUgZm9yIGNyeXB0byB0aGF0IHByZXZlbnRzIHVzIGZyb20gdXNpbmcgSGFzaC5jb3B5KHsgb3V0cHV0TGVuZ3RoOiAuLi4gfSlcbiAgLy8gICAgICAgb3V0cHV0TGVuZ3RoIG11c3QgYmUgc3BlY2lmaWVkIG9uIHRoZSBjb3B5KCkgZm9yIGEgc2hha2UyNTYgaGFzaCB0byBiZWhhdmUgY29ycmVjdGx5LlxuICAvLyAgICAgICBPbiB0aGUgb3RoZXIgaGFuZCwgc2luY2UgaXQncyB2ZXJ5IGxpa2VseSB0aGF0IHRoZSBmaXJzdCBoYXNoIHdpbGwgZmFsbCBpbiB0aGUgZGVzaXJlZCByYW5nZSwgdXNpbmdcbiAgLy8gICAgICAgSGFzaC5jb3B5KCkgdG8gc2F2ZSBvbiByZXBlYXRlZCBjYWxsaW5nIHVwZGF0ZShgJHtOfSQke3d9JGApIG1heSBub3QgYmUgd29ydGggaXQuXG4gIHJldHVybiBjcmVhdGVIYXNoKCdzaGFrZTI1NicsIHsgb3V0cHV0TGVuZ3RoOiAxICsgTWF0aC5mbG9vcigoYml0TGVuZ3RoKE9SREVSKSArIDcpIC8gOCkgfSlcbiAgICAudXBkYXRlKGJpZ0ludFRvQnVmZmVyQkUoTikpXG4gICAgLnVwZGF0ZSgnJCcpXG4gICAgLnVwZGF0ZShiaWdJbnRUb0J1ZmZlckJFKHcpKVxuICAgIC51cGRhdGUoJyQnKVxuICAgIC51cGRhdGUobm9uY2UpXG4gICAgLmRpZ2VzdCgpO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIHBzZXVkby1yYW5kb20gY2hhbGxlbmdlIHZhbHVlICRlJCBhbmQgYXNzb2NpYXRlZCAkbm9uY2UkIGZvciAkKE4sIHcpJC5cbiAqIEBwYXJhbSBOIC0gdGhlIHByaW1lIG51bWJlciB0byB2ZXJpZnkgaXMgYSBwcm9kdWN0IG9mIHR3byBsYXJnZSBwcmltZXMuXG4gKiBAcGFyYW0gdyAtIGEgcmFuZG9tIG51bWJlciB3aXRoIHRoZSBzYW1lIGJpdExlbmd0aCBhcyBOLCB0aGF0IHNhdGlzZmllcyB0aGUgSmFjb2JpIG9mIHcgaXMgLTEgd3J0IE4uXG4gKiBAcmV0dXJucyB7bm9uY2UsIGV9IC0gY2hhbGxlbmdlIHZhbHVlICRlJCBhbmQgYXNzb2NpYXRlZCAkbm9uY2UkIHRoYXQgbWFrZXMgJGUkIHVuaWZvcm1seSByYW5kb20gZnJvbSAkKC1vcmRlciwgb3JkZXIpJC5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVFZm9yUHJvdmUoTjogYmlnaW50LCB3OiBiaWdpbnQpOiB7IG5vbmNlOiBCdWZmZXI7IGU6IGJpZ2ludCB9IHtcbiAgbGV0IG5vbmNlOiBCdWZmZXIsIGU6IGJpZ2ludCwgZGlnZXN0OiBCdWZmZXI7XG4gIGRvIHtcbiAgICBub25jZSA9IHJhbmRvbUJ5dGVzKDMzKTtcbiAgICBkaWdlc3QgPSBoYXNoKE4sIHcsIG5vbmNlKTtcbiAgICBlID0gYmlnSW50RnJvbUJ1ZmZlckJFKGRpZ2VzdC5zdWJhcnJheSgxKSk7XG4gIH0gd2hpbGUgKGUgPj0gT1JERVIpO1xuICBpZiAoZGlnZXN0WzBdICYgMSkge1xuICAgIHJldHVybiB7IG5vbmNlLCBlOiAtZSB9O1xuICB9XG4gIHJldHVybiB7IG5vbmNlLCBlIH07XG59XG5cbi8qKlxuICogR2VuZXJhdGUgcHNldWRvLXJhbmRvbSBjaGFsbGVuZ2UgdmFsdWUgJGUkIGZvciAkKE4sIHcpJCBhbmQgYXNzb2NpYXRlZCAkbm9uY2UkLlxuICogQHBhcmFtIE4gLSB0aGUgcHJpbWUgbnVtYmVyIHRvIHZlcmlmeSBpcyBhIHByb2R1Y3Qgb2YgdHdvIGxhcmdlIHByaW1lcy5cbiAqIEBwYXJhbSB3IC0gYSByYW5kb20gbnVtYmVyIHdpdGggdGhlIHNhbWUgYml0TGVuZ3RoIGFzIE4sIHRoYXQgc2F0aXNmaWVzIHRoZSBKYWNvYmkgb2YgdyBpcyAtMSB3cnQgTi5cbiAqIEBwYXJhbSBub25jZSAtIGEgcmFuZG9tIG5vbmNlLlxuICogQHJldHVybnMge2JpZ2ludH0gLSBjaGFsbGVuZ2UgdmFsdWUgJGUkLlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUVmb3JWZXJpZnkoTjogYmlnaW50LCB3OiBiaWdpbnQsIG5vbmNlOiBCdWZmZXIpOiBiaWdpbnQge1xuICBjb25zdCBkaWdlc3QgPSBoYXNoKE4sIHcsIG5vbmNlKTtcbiAgY29uc3QgZSA9IGJpZ0ludEZyb21CdWZmZXJCRShkaWdlc3Quc3ViYXJyYXkoMSkpO1xuICBpZiAoZGlnZXN0WzBdICYgMSkge1xuICAgIHJldHVybiAtZTtcbiAgfVxuICByZXR1cm4gZTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIGNsb3Nlc3QgaW50ZWdlciBzcXVhcmUgcm9vdCBvZiAkbiQuXG4gKiBAcGFyYW0gbiAtIHRoZSBudW1iZXIgdG8gY2FsY3VsYXRlIHRoZSBzcXVhcmUgcm9vdCBvZi5cbiAqIEByZXR1cm5zIHtiaWdpbnR9IC0gJG4kJ3MgY2xvc2VzdCBpbnRlZ2VyIHNxdWFyZSByb290LlxuICovXG5mdW5jdGlvbiBpc3FydChuOiBiaWdpbnQpOiBiaWdpbnQge1xuICBpZiAobiA8IEJpZ0ludCgwKSkge1xuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9XG4gIGlmIChuIDwgQmlnSW50KDIpKSB7XG4gICAgcmV0dXJuIG47XG4gIH1cbiAgZnVuY3Rpb24gbmV3dG9uSXRlcmF0aW9uKG46IGJpZ2ludCwgeDA6IGJpZ2ludCkge1xuICAgIGNvbnN0IHgxID0gKG4gLyB4MCArIHgwKSA+PiBCaWdJbnQoMSk7XG4gICAgaWYgKHgwID09PSB4MSB8fCB4MCA9PT0geDEgLSBCaWdJbnQoMSkpIHtcbiAgICAgIHJldHVybiB4MDtcbiAgICB9XG4gICAgcmV0dXJuIG5ld3Rvbkl0ZXJhdGlvbihuLCB4MSk7XG4gIH1cbiAgcmV0dXJuIG5ld3Rvbkl0ZXJhdGlvbihuLCBCaWdJbnQoMSkpO1xufVxuXG4vKipcbiAqIFByb3ZlIHRoYXQgJG4wJCBoYXMgbm8gc21hbGwgZmFjdG9ycywgd2hlcmUgJG4wJCBpcyB0aGUgcHJvZHVjdCBvZiB0d28gbGFyZ2UgcHJpbWVzLlxuICogQHBhcmFtIHAgLSBhIGxhcmdlIHByaW1lLlxuICogQHBhcmFtIHEgLSBhIGxhcmdlIHByaW1lLlxuICogQHBhcmFtIHcgLSBhIHJhbmRvbSBudW1iZXIgd2l0aCB0aGUgc2FtZSBiaXRMZW5ndGggYXMgJHAgKiBxJCwgdGhhdCBzYXRpc2ZpZXMgdGhlIEphY29iaSBvZiB3IGlzIC0xIHdydCAkbjAkLlxuICogQHBhcmFtIG5IYXQgLSBhIHNhZmUgYmktcHJpbWUsIHN1Y2ggYXMgdGhhdCByZXR1cm5lZCBmcm9tIHJhbmdlUHJvb2YuZ2VuZXJhdGVOVGlsZGUuXG4gKiBAcGFyYW0gcyAtIHNlY3VyaXR5IHBhcmFtZXRlcnMgZm9yICRuSGF0JCBzdWNoIGFzIHRoZSAkaDEkIHZhbHVlIHJldHVybmVkIGZyb20gcmFuZ2VQcm9vZi5nZW5lcmF0ZU5UaWxkZS5cbiAqIEBwYXJhbSB0IC0gc2VjdXJpdHkgcGFyYW1ldGVycyBmb3IgJG5IYXQkIHN1Y2ggYXMgdGhlICRoMiQgdmFsdWUgcmV0dXJuZWQgZnJvbSByYW5nZVByb29mLmdlbmVyYXRlTlRpbGRlLlxuICogQHJldHVybnMgcHJvb2YgdGhhdCB0aGUgcHJvZHVjdCBvZiAkcCAqIHEkIGhhcyBubyBzbWFsbCBmYWN0b3JzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvdmUoXG4gIHA6IGJpZ2ludCxcbiAgcTogYmlnaW50LFxuICB3OiBiaWdpbnQsXG4gIG5IYXQ6IGJpZ2ludCxcbiAgczogYmlnaW50LFxuICB0OiBiaWdpbnRcbik6IERlc2VyaWFsaXplZE5vU21hbGxGYWN0b3JzUHJvb2Yge1xuICBjb25zdCBuMCA9IHAgKiBxO1xuICBjb25zdCB7IG5vbmNlLCBlIH0gPSBnZW5lcmF0ZUVmb3JQcm92ZShuMCwgdyk7XG4gIGNvbnN0IHNxcnROMCA9IGlzcXJ0KG4wKTtcbiAgY29uc3QgYWxwaGEgPSByYW5kQmV0d2VlbihzcXJ0TjAgPDwgKEVMTCArIEVQU0lMT04pLCAtc3FydE4wIDw8IChFTEwgKyBFUFNJTE9OKSk7XG4gIGNvbnN0IGJldGEgPSByYW5kQmV0d2VlbihzcXJ0TjAgPDwgKEVMTCArIEVQU0lMT04pLCAtc3FydE4wIDw8IChFTEwgKyBFUFNJTE9OKSk7XG4gIGNvbnN0IHJobyA9IHJhbmRCZXR3ZWVuKChuSGF0ICogbjApIDw8IEVMTCwgLShuSGF0ICogbjApIDw8IEVMTCk7XG4gIC8vIENvbW1pdCB0byBwLlxuICBjb25zdCBtdSA9IHJhbmRCZXR3ZWVuKG5IYXQgPDwgRUxMLCAtbkhhdCA8PCBFTEwpO1xuICBjb25zdCBQID0gKG1vZFBvdyhzLCBwLCBuSGF0KSAqIG1vZFBvdyh0LCBtdSwgbkhhdCkpICUgbkhhdDtcbiAgLy8gQ29tbWl0IHRvIHEuXG4gIGNvbnN0IG51ID0gcmFuZEJldHdlZW4obkhhdCA8PCBFTEwsIC1uSGF0IDw8IEVMTCk7XG4gIGNvbnN0IFEgPSAobW9kUG93KHMsIHEsIG5IYXQpICogbW9kUG93KHQsIG51LCBuSGF0KSkgJSBuSGF0O1xuICAvLyBDb21taXQgdG8gYWxwaGEuXG4gIGNvbnN0IHggPSByYW5kQmV0d2VlbihuSGF0IDw8IChFTEwgKyBFUFNJTE9OKSwgLW5IYXQgPDwgKEVMTCArIEVQU0lMT04pKTtcbiAgY29uc3QgQSA9IChtb2RQb3cocywgYWxwaGEsIG5IYXQpICogbW9kUG93KHQsIHgsIG5IYXQpKSAlIG5IYXQ7XG4gIC8vIENvbW1pdCB0byBiZXRhLlxuICBjb25zdCB5ID0gcmFuZEJldHdlZW4obkhhdCA8PCAoRUxMICsgRVBTSUxPTiksIC1uSGF0IDw8IChFTEwgKyBFUFNJTE9OKSk7XG4gIGNvbnN0IEIgPSAobW9kUG93KHMsIGJldGEsIG5IYXQpICogbW9kUG93KHQsIHksIG5IYXQpKSAlIG5IYXQ7XG4gIC8vIENvbW1pdCB0byBRIGFuZCBhbHBoYS5cbiAgY29uc3QgciA9IHJhbmRCZXR3ZWVuKChuSGF0ICogbjApIDw8IChFTEwgKyBFUFNJTE9OKSwgLShuSGF0ICogbjApIDw8IChFTEwgKyBFUFNJTE9OKSk7XG4gIGNvbnN0IFQgPSAobW9kUG93KFEsIGFscGhhLCBuSGF0KSAqIG1vZFBvdyh0LCByLCBuSGF0KSkgJSBuSGF0O1xuXG4gIGNvbnN0IHJob0hhdCA9IHJobyAtIG51ICogcDtcbiAgY29uc3QgejEgPSBhbHBoYSArIGUgKiBwO1xuICBjb25zdCB6MiA9IGJldGEgKyBlICogcTtcbiAgY29uc3QgdzEgPSB4ICsgZSAqIG11O1xuICBjb25zdCB3MiA9IHkgKyBlICogbnU7XG4gIGNvbnN0IHYgPSByICsgZSAqIHJob0hhdDtcblxuICByZXR1cm4geyBQLCBRLCBBLCBCLCBULCByaG8sIHoxLCB6MiwgdzEsIHcyLCB2LCBub25jZTogYmlnSW50RnJvbUJ1ZmZlckJFKG5vbmNlKSB9O1xufVxuXG4vKipcbiAqIFZlcmlmeSB0aGF0ICRuMCQgaXMgbm90IHRoZSBwcm9kdWN0IG9mIGFueSBzbWFsbCBmYWN0b3JzLlxuICogQHBhcmFtIG4wIC0gYSBtb2R1bHVzIHRoYXQgaXMgdGhlIHByb2R1Y3Qgb2YgJHAkIGFuZCAkcSQuXG4gKiBAcGFyYW0gdyAtIGEgcmFuZG9tIG51bWJlciB3aXRoIHRoZSBzYW1lIGJpdExlbmd0aCBhcyAkbjAkLCB0aGF0IHNhdGlzZmllcyB0aGUgSmFjb2JpIG9mIHcgaXMgLTEgd3J0ICRuMCQuXG4gKiBAcGFyYW0gbkhhdCAtIGEgc2FmZSBiaS1wcmltZSwgc3VjaCBhcyB0aGF0IHJldHVybmVkIGZyb20gcmFuZ2VQcm9vZi5nZW5lcmF0ZU5UaWxkZS5cbiAqIEBwYXJhbSBzIC0gc2VjdXJpdHkgcGFyYW1ldGVycyBmb3IgJG5IYXQkIHN1Y2ggYXMgdGhlICRoMSQgdmFsdWUgcmV0dXJuZWQgZnJvbSByYW5nZVByb29mLmdlbmVyYXRlTlRpbGRlLlxuICogQHBhcmFtIHQgLSBzZWN1cml0eSBwYXJhbWV0ZXJzIGZvciAkbkhhdCQgc3VjaCBhcyB0aGUgJGgyJCB2YWx1ZSByZXR1cm5lZCBmcm9tIHJhbmdlUHJvb2YuZ2VuZXJhdGVOVGlsZGUuXG4gKiBAcGFyYW0gcHJvb2YgLSBhIHByb29mIGdlbmVyYXRlZCBieSBub1NtYWxsRmFjdG9ycy5wcm92ZS5cbiAqIEByZXR1cm5zIHRydWUgaWYgdmVyaWZpY2F0aW9uIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJpZnkoXG4gIG4wOiBiaWdpbnQsXG4gIHc6IGJpZ2ludCxcbiAgbkhhdDogYmlnaW50LFxuICBzOiBiaWdpbnQsXG4gIHQ6IGJpZ2ludCxcbiAgcHJvb2Y6IERlc2VyaWFsaXplZE5vU21hbGxGYWN0b3JzUHJvb2Zcbik6IGJvb2xlYW4ge1xuICBjb25zdCB7IFAsIFEsIEEsIEIsIFQsIHJobywgejEsIHoyLCB3MSwgdzIsIHYsIG5vbmNlIH0gPSBwcm9vZjtcbiAgY29uc3QgZSA9IGdlbmVyYXRlRWZvclZlcmlmeShuMCwgdywgYmlnSW50VG9CdWZmZXJCRShub25jZSwgMzMpKTtcbiAgaWYgKGUgPCAtT1JERVIgfHwgZSA+IE9SREVSKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgdmVyaWZ5IG5vIHNtYWxsIGZhY3RvcnMgcHJvb2YnKTtcbiAgfVxuICBjb25zdCBzcXJ0TjAgPSBpc3FydChuMCk7XG4gIGNvbnN0IFIgPSAobW9kUG93KHMsIG4wLCBuSGF0KSAqIG1vZFBvdyh0LCByaG8sIG5IYXQpKSAlIG5IYXQ7XG4gIGlmICgobW9kUG93KHMsIHoxLCBuSGF0KSAqIG1vZFBvdyh0LCB3MSwgbkhhdCkpICUgbkhhdCAhPT0gKEEgKiBtb2RQb3coUCwgZSwgbkhhdCkpICUgbkhhdCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IHZlcmlmeSBubyBzbWFsbCBmYWN0b3JzIHByb29mJyk7XG4gIH1cbiAgaWYgKChtb2RQb3cocywgejIsIG5IYXQpICogbW9kUG93KHQsIHcyLCBuSGF0KSkgJSBuSGF0ICE9PSAoQiAqIG1vZFBvdyhRLCBlLCBuSGF0KSkgJSBuSGF0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgdmVyaWZ5IG5vIHNtYWxsIGZhY3RvcnMgcHJvb2YnKTtcbiAgfVxuICBpZiAoKG1vZFBvdyhRLCB6MSwgbkhhdCkgKiBtb2RQb3codCwgdiwgbkhhdCkpICUgbkhhdCAhPT0gKFQgKiBtb2RQb3coUiwgZSwgbkhhdCkpICUgbkhhdCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IHZlcmlmeSBubyBzbWFsbCBmYWN0b3JzIHByb29mJyk7XG4gIH1cbiAgaWYgKHoxIDwgLXNxcnROMCA8PCAoRUxMICsgRVBTSUxPTikgfHwgejEgPiBzcXJ0TjAgPDwgKEVMTCArIEVQU0lMT04pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgdmVyaWZ5IG5vIHNtYWxsIGZhY3RvcnMgcHJvb2YnKTtcbiAgfVxuICBpZiAoejIgPCAtc3FydE4wIDw8IChFTEwgKyBFUFNJTE9OKSB8fCB6MiA+IHNxcnROMCA8PCAoRUxMICsgRVBTSUxPTikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCB2ZXJpZnkgbm8gc21hbGwgZmFjdG9ycyBwcm9vZicpO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuIl19
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { DeserializedPaillierBlumProof } from './types';
|
|
2
|
-
/**
|
|
3
|
-
* Prove that a modulus (p*q) is the product of two large safe primes (p and q).
|
|
4
|
-
* @param {bigint} p The larger prime factor of the modulus
|
|
5
|
-
* @param {bigint} q The smaller prime factor of the modulus.
|
|
6
|
-
* @returns {DeserializedPaillierBlumProof} The proof that the modulus is the product of two large primes.
|
|
7
|
-
*/
|
|
8
|
-
export declare function prove(p: bigint, q: bigint): Promise<DeserializedPaillierBlumProof>;
|
|
9
|
-
/**
|
|
10
|
-
* Verify that N is the product of two large primes.
|
|
11
|
-
* @param {bigint} N The prime number being verified.
|
|
12
|
-
* @param {DeserializedPaillierBlumProof} The proof to verify N is a product of two large primes.
|
|
13
|
-
* @returns {boolean} True if N is a product of two large primes, and false otherwise.
|
|
14
|
-
*/
|
|
15
|
-
export declare function verify(N: bigint, { w, ab, x, z }: DeserializedPaillierBlumProof): Promise<boolean>;
|
|
16
|
-
//# sourceMappingURL=paillierBlumProof.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paillierBlumProof.d.ts","sourceRoot":"","sources":["../../../../src/tss/ecdsa/paillierBlumProof.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AA4ExD;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,6BAA6B,CAAC,CA+CxF;AAED;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,6BAA6B,GAAG,OAAO,CAAC,OAAO,CAAC,CAsCxG"}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.verify = exports.prove = void 0;
|
|
4
|
-
const crypto_1 = require("crypto");
|
|
5
|
-
const bigint_crypto_utils_1 = require("bigint-crypto-utils");
|
|
6
|
-
const bigint_mod_arith_1 = require("bigint-mod-arith");
|
|
7
|
-
const util_1 = require("../../util");
|
|
8
|
-
// Security parameter.
|
|
9
|
-
const m = 80;
|
|
10
|
-
/**
|
|
11
|
-
* Generate psuedo-random quadratic residue for (N, w, i).
|
|
12
|
-
* @param N - the prime number to verify is a product of two large primes.
|
|
13
|
-
* @param w - a random number with the same bitLength as N, that satisfies the Jacobi of w is -1 wrt N.
|
|
14
|
-
* @returns {bigint[]} - set of challenges for N
|
|
15
|
-
*/
|
|
16
|
-
function generateY(N, w) {
|
|
17
|
-
const NBuf = util_1.bigIntToBufferBE(N);
|
|
18
|
-
const wBuf = util_1.bigIntToBufferBE(w, NBuf.length);
|
|
19
|
-
let counter = 0;
|
|
20
|
-
return Array(m)
|
|
21
|
-
.fill(null)
|
|
22
|
-
.map((_, i) => {
|
|
23
|
-
while (true) {
|
|
24
|
-
const counterBuf = Buffer.alloc(4);
|
|
25
|
-
counterBuf.writeUInt32BE(counter++);
|
|
26
|
-
const y = util_1.bigIntFromBufferBE(crypto_1.createHash('shake256', { outputLength: NBuf.length })
|
|
27
|
-
.update(counterBuf)
|
|
28
|
-
.update('$')
|
|
29
|
-
.update(NBuf)
|
|
30
|
-
.update('$')
|
|
31
|
-
.update(wBuf)
|
|
32
|
-
.update('$')
|
|
33
|
-
.digest());
|
|
34
|
-
if (y > BigInt(0) && y < N && bigint_mod_arith_1.gcd(y, N) === BigInt(1)) {
|
|
35
|
-
return y;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
// https://en.wikipedia.org/wiki/Jacobi_symbol#Implementation_in_C++
|
|
41
|
-
function jacobi(a, n) {
|
|
42
|
-
// a/n is represented as (a,n)
|
|
43
|
-
if (n <= BigInt(0)) {
|
|
44
|
-
throw new Error('n must greater than 0');
|
|
45
|
-
}
|
|
46
|
-
if (n % BigInt(2) !== BigInt(1)) {
|
|
47
|
-
throw new Error('n must be odd');
|
|
48
|
-
}
|
|
49
|
-
// step 1
|
|
50
|
-
a = a % n;
|
|
51
|
-
let t = BigInt(1);
|
|
52
|
-
let r;
|
|
53
|
-
// step 3
|
|
54
|
-
while (a !== BigInt(0)) {
|
|
55
|
-
// step 2
|
|
56
|
-
while (a % BigInt(2) === BigInt(0)) {
|
|
57
|
-
a /= BigInt(2);
|
|
58
|
-
r = n % BigInt(8);
|
|
59
|
-
if (r === BigInt(3) || r === BigInt(5)) {
|
|
60
|
-
t = -t;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// step 4
|
|
64
|
-
r = n;
|
|
65
|
-
n = a;
|
|
66
|
-
a = r;
|
|
67
|
-
if (a % BigInt(4) === BigInt(3) && n % BigInt(4) === BigInt(3)) {
|
|
68
|
-
t = -t;
|
|
69
|
-
}
|
|
70
|
-
a = a % n;
|
|
71
|
-
}
|
|
72
|
-
if (n === BigInt(1)) {
|
|
73
|
-
return t;
|
|
74
|
-
}
|
|
75
|
-
return BigInt(0);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Prove that a modulus (p*q) is the product of two large safe primes (p and q).
|
|
79
|
-
* @param {bigint} p The larger prime factor of the modulus
|
|
80
|
-
* @param {bigint} q The smaller prime factor of the modulus.
|
|
81
|
-
* @returns {DeserializedPaillierBlumProof} The proof that the modulus is the product of two large primes.
|
|
82
|
-
*/
|
|
83
|
-
async function prove(p, q) {
|
|
84
|
-
// Prover selects random w with Jacobi symbol 1 wrt N.
|
|
85
|
-
const N = p * q;
|
|
86
|
-
const l = (p - BigInt(1)) * (q - BigInt(1));
|
|
87
|
-
const d = bigint_mod_arith_1.modInv(N, l);
|
|
88
|
-
let w;
|
|
89
|
-
while (true) {
|
|
90
|
-
w = util_1.bigIntFromBufferBE(Buffer.from(await bigint_crypto_utils_1.randBits(bigint_crypto_utils_1.bitLength(N))));
|
|
91
|
-
if (jacobi(w, N) === BigInt(-1)) {
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// This is calculating the inverse of the function y^4 mod N,
|
|
96
|
-
// i.e.y ^ (1 / 4), where N = pq is a blum integer using HOC - Fact 2.160
|
|
97
|
-
// from cacr.uwaterloo.ca / hac / about / chap2.pdf
|
|
98
|
-
// Prover generates a_i, b_i, and y_i.
|
|
99
|
-
const y = generateY(N, w);
|
|
100
|
-
// Prover calculates z_i = y_i ^ d mod N
|
|
101
|
-
const z = y.map((y_i) => bigint_mod_arith_1.modPow(y_i, d, N));
|
|
102
|
-
// Prover calculates x_i = y_i ^ 1/4 mod N using [HOC - Fact 2.160]
|
|
103
|
-
const e = ((l + BigInt(4)) / BigInt(8)) ** BigInt(2);
|
|
104
|
-
const ab = Array(m).fill(null);
|
|
105
|
-
const x = await Promise.all(y.map(async (y_i, i) => {
|
|
106
|
-
// Select random a_i, b_i so that y_i' = (-1)^{a_i} * w^{b_i} * y is
|
|
107
|
-
// quadratic residue of N using [HOC - Fact 2.137].
|
|
108
|
-
let ab_i, t;
|
|
109
|
-
for (ab_i = 0; ab_i < 4; ab_i++) {
|
|
110
|
-
t = y_i;
|
|
111
|
-
if (ab_i & 2) {
|
|
112
|
-
t = -t;
|
|
113
|
-
}
|
|
114
|
-
if (ab_i & 1) {
|
|
115
|
-
t *= w;
|
|
116
|
-
}
|
|
117
|
-
if (bigint_mod_arith_1.modPow(t, (p - BigInt(1)) / BigInt(2), p) === BigInt(1) &&
|
|
118
|
-
bigint_mod_arith_1.modPow(t, (q - BigInt(1)) / BigInt(2), q) === BigInt(1)) {
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
ab[i] = ab_i;
|
|
123
|
-
return bigint_mod_arith_1.modPow(t, e, N);
|
|
124
|
-
}));
|
|
125
|
-
return { w, ab, x, z };
|
|
126
|
-
}
|
|
127
|
-
exports.prove = prove;
|
|
128
|
-
/**
|
|
129
|
-
* Verify that N is the product of two large primes.
|
|
130
|
-
* @param {bigint} N The prime number being verified.
|
|
131
|
-
* @param {DeserializedPaillierBlumProof} The proof to verify N is a product of two large primes.
|
|
132
|
-
* @returns {boolean} True if N is a product of two large primes, and false otherwise.
|
|
133
|
-
*/
|
|
134
|
-
async function verify(N, { w, ab, x, z }) {
|
|
135
|
-
// Verifier checks N > 1.
|
|
136
|
-
if (N <= 1) {
|
|
137
|
-
throw new Error('N must be greater than 1');
|
|
138
|
-
}
|
|
139
|
-
// Verifier checks N is odd.
|
|
140
|
-
if (N % BigInt(2) !== BigInt(1)) {
|
|
141
|
-
throw new Error('N must be an odd number');
|
|
142
|
-
}
|
|
143
|
-
// Verifier checks N is not prime.
|
|
144
|
-
if (await bigint_crypto_utils_1.isProbablyPrime(N, 24)) {
|
|
145
|
-
throw new Error('N must be a composite number');
|
|
146
|
-
}
|
|
147
|
-
// Verifier checks that the Jacobi symbol for w is 1 wrt N.
|
|
148
|
-
if (jacobi(w, N) !== BigInt(-1)) {
|
|
149
|
-
throw new Error('Jacobi symbol of w must be -1 wrt to N');
|
|
150
|
-
}
|
|
151
|
-
// Verifier generates a_i, b_i, y_i.
|
|
152
|
-
const y = generateY(N, w);
|
|
153
|
-
for (let i = 0; i < m; i++) {
|
|
154
|
-
// Verifier checks z_i ^ N mod N == y_i.
|
|
155
|
-
if (bigint_mod_arith_1.modPow(z[i], N, N) !== y[i]) {
|
|
156
|
-
throw new Error(`Paillier verification of z[${i}] failed`);
|
|
157
|
-
}
|
|
158
|
-
// Verifier checks x_i ^ 4 mod N == (-1)^a * w^b * y_i.
|
|
159
|
-
let y_i = y[i];
|
|
160
|
-
if (ab[i] & 2) {
|
|
161
|
-
y_i = -y_i;
|
|
162
|
-
}
|
|
163
|
-
if (ab[i] & 1) {
|
|
164
|
-
y_i *= w;
|
|
165
|
-
}
|
|
166
|
-
y_i = bigint_mod_arith_1.modPow(y_i, 1, N);
|
|
167
|
-
if (bigint_mod_arith_1.modPow(x[i], 4, N) !== y_i) {
|
|
168
|
-
throw new Error(`Paillier verification of x[${i}] failed`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
exports.verify = verify;
|
|
174
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFpbGxpZXJCbHVtUHJvb2YuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdHNzL2VjZHNhL3BhaWxsaWVyQmx1bVByb29mLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUFvQztBQUNwQyw2REFBMkU7QUFDM0UsdURBQXVEO0FBQ3ZELHFDQUFrRTtBQUdsRSxzQkFBc0I7QUFDdEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBRWI7Ozs7O0dBS0c7QUFDSCxTQUFTLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNyQixNQUFNLElBQUksR0FBRyx1QkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqQyxNQUFNLElBQUksR0FBRyx1QkFBZ0IsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlDLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztJQUNoQixPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDWixJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ1YsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ1osT0FBTyxJQUFJLEVBQUU7WUFDWCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLFVBQVUsQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNwQyxNQUFNLENBQUMsR0FBRyx5QkFBa0IsQ0FDMUIsbUJBQVUsQ0FBQyxVQUFVLEVBQUUsRUFBRSxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2lCQUNsRCxNQUFNLENBQUMsVUFBVSxDQUFDO2lCQUNsQixNQUFNLENBQUMsR0FBRyxDQUFDO2lCQUNYLE1BQU0sQ0FBQyxJQUFJLENBQUM7aUJBQ1osTUFBTSxDQUFDLEdBQUcsQ0FBQztpQkFDWCxNQUFNLENBQUMsSUFBSSxDQUFDO2lCQUNaLE1BQU0sQ0FB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QzVEO0tBQ0Y7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUF0Q0Qsd0JBc0NDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBiaXRMZW5ndGgsIHJhbmRCaXRzLCBpc1Byb2JhYmx5UHJpbWUgfSBmcm9tICdiaWdpbnQtY3J5cHRvLXV0aWxzJztcbmltcG9ydCB7IGdjZCwgbW9kSW52LCBtb2RQb3cgfSBmcm9tICdiaWdpbnQtbW9kLWFyaXRoJztcbmltcG9ydCB7IGJpZ0ludEZyb21CdWZmZXJCRSwgYmlnSW50VG9CdWZmZXJCRSB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHsgRGVzZXJpYWxpemVkUGFpbGxpZXJCbHVtUHJvb2YgfSBmcm9tICcuL3R5cGVzJztcblxuLy8gU2VjdXJpdHkgcGFyYW1ldGVyLlxuY29uc3QgbSA9IDgwO1xuXG4vKipcbiAqIEdlbmVyYXRlIHBzdWVkby1yYW5kb20gcXVhZHJhdGljIHJlc2lkdWUgZm9yIChOLCB3LCBpKS5cbiAqIEBwYXJhbSBOIC0gdGhlIHByaW1lIG51bWJlciB0byB2ZXJpZnkgaXMgYSBwcm9kdWN0IG9mIHR3byBsYXJnZSBwcmltZXMuXG4gKiBAcGFyYW0gdyAtIGEgcmFuZG9tIG51bWJlciB3aXRoIHRoZSBzYW1lIGJpdExlbmd0aCBhcyBOLCB0aGF0IHNhdGlzZmllcyB0aGUgSmFjb2JpIG9mIHcgaXMgLTEgd3J0IE4uXG4gKiBAcmV0dXJucyB7YmlnaW50W119IC0gc2V0IG9mIGNoYWxsZW5nZXMgZm9yIE5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVZKE4sIHcpOiBiaWdpbnRbXSB7XG4gIGNvbnN0IE5CdWYgPSBiaWdJbnRUb0J1ZmZlckJFKE4pO1xuICBjb25zdCB3QnVmID0gYmlnSW50VG9CdWZmZXJCRSh3LCBOQnVmLmxlbmd0aCk7XG4gIGxldCBjb3VudGVyID0gMDtcbiAgcmV0dXJuIEFycmF5KG0pXG4gICAgLmZpbGwobnVsbClcbiAgICAubWFwKChfLCBpKSA9PiB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBjb25zdCBjb3VudGVyQnVmID0gQnVmZmVyLmFsbG9jKDQpO1xuICAgICAgICBjb3VudGVyQnVmLndyaXRlVUludDMyQkUoY291bnRlcisrKTtcbiAgICAgICAgY29uc3QgeSA9IGJpZ0ludEZyb21CdWZmZXJCRShcbiAgICAgICAgICBjcmVhdGVIYXNoKCdzaGFrZTI1NicsIHsgb3V0cHV0TGVuZ3RoOiBOQnVmLmxlbmd0aCB9KVxuICAgICAgICAgICAgLnVwZGF0ZShjb3VudGVyQnVmKVxuICAgICAgICAgICAgLnVwZGF0ZSgnJCcpXG4gICAgICAgICAgICAudXBkYXRlKE5CdWYpXG4gICAgICAgICAgICAudXBkYXRlKCckJylcbiAgICAgICAgICAgIC51cGRhdGUod0J1ZilcbiAgICAgICAgICAgIC51cGRhdGUoJyQnKVxuICAgICAgICAgICAgLmRpZ2VzdCgpXG4gICAgICAgICk7XG4gICAgICAgIGlmICh5ID4gQmlnSW50KDApICYmIHkgPCBOICYmIGdjZCh5LCBOKSA9PT0gQmlnSW50KDEpKSB7XG4gICAgICAgICAgcmV0dXJuIHk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbn1cblxuLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSmFjb2JpX3N5bWJvbCNJbXBsZW1lbnRhdGlvbl9pbl9DKytcbmZ1bmN0aW9uIGphY29iaShhLCBuKTogYmlnaW50IHtcbiAgLy8gYS9uIGlzIHJlcHJlc2VudGVkIGFzIChhLG4pXG4gIGlmIChuIDw9IEJpZ0ludCgwKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbiBtdXN0IGdyZWF0ZXIgdGhhbiAwJyk7XG4gIH1cbiAgaWYgKG4gJSBCaWdJbnQoMikgIT09IEJpZ0ludCgxKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbiBtdXN0IGJlIG9kZCcpO1xuICB9XG4gIC8vIHN0ZXAgMVxuICBhID0gYSAlIG47XG4gIGxldCB0ID0gQmlnSW50KDEpO1xuICBsZXQgcjtcbiAgLy8gc3RlcCAzXG4gIHdoaWxlIChhICE9PSBCaWdJbnQoMCkpIHtcbiAgICAvLyBzdGVwIDJcbiAgICB3aGlsZSAoYSAlIEJpZ0ludCgyKSA9PT0gQmlnSW50KDApKSB7XG4gICAgICBhIC89IEJpZ0ludCgyKTtcbiAgICAgIHIgPSBuICUgQmlnSW50KDgpO1xuICAgICAgaWYgKHIgPT09IEJpZ0ludCgzKSB8fCByID09PSBCaWdJbnQoNSkpIHtcbiAgICAgICAgdCA9IC10O1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBzdGVwIDRcbiAgICByID0gbjtcbiAgICBuID0gYTtcbiAgICBhID0gcjtcbiAgICBpZiAoYSAlIEJpZ0ludCg0KSA9PT0gQmlnSW50KDMpICYmIG4gJSBCaWdJbnQoNCkgPT09IEJpZ0ludCgzKSkge1xuICAgICAgdCA9IC10O1xuICAgIH1cbiAgICBhID0gYSAlIG47XG4gIH1cbiAgaWYgKG4gPT09IEJpZ0ludCgxKSkge1xuICAgIHJldHVybiB0O1xuICB9XG4gIHJldHVybiBCaWdJbnQoMCk7XG59XG5cbi8qKlxuICogUHJvdmUgdGhhdCBhIG1vZHVsdXMgKHAqcSkgaXMgdGhlIHByb2R1Y3Qgb2YgdHdvIGxhcmdlIHNhZmUgcHJpbWVzIChwIGFuZCBxKS5cbiAqIEBwYXJhbSB7YmlnaW50fSBwIFRoZSBsYXJnZXIgcHJpbWUgZmFjdG9yIG9mIHRoZSBtb2R1bHVzXG4gKiBAcGFyYW0ge2JpZ2ludH0gcSBUaGUgc21hbGxlciBwcmltZSBmYWN0b3Igb2YgdGhlIG1vZHVsdXMuXG4gKiBAcmV0dXJucyB7RGVzZXJpYWxpemVkUGFpbGxpZXJCbHVtUHJvb2Z9IFRoZSBwcm9vZiB0aGF0IHRoZSBtb2R1bHVzIGlzIHRoZSBwcm9kdWN0IG9mIHR3byBsYXJnZSBwcmltZXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm92ZShwOiBiaWdpbnQsIHE6IGJpZ2ludCk6IFByb21pc2U8RGVzZXJpYWxpemVkUGFpbGxpZXJCbHVtUHJvb2Y+IHtcbiAgLy8gUHJvdmVyIHNlbGVjdHMgcmFuZG9tIHcgd2l0aCBKYWNvYmkgc3ltYm9sIDEgd3J0IE4uXG4gIGNvbnN0IE4gPSBwICogcTtcbiAgY29uc3QgbCA9IChwIC0gQmlnSW50KDEpKSAqIChxIC0gQmlnSW50KDEpKTtcbiAgY29uc3QgZCA9IG1vZEludihOLCBsKTtcbiAgbGV0IHc7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgdyA9IGJpZ0ludEZyb21CdWZmZXJCRShCdWZmZXIuZnJvbShhd2FpdCByYW5kQml0cyhiaXRMZW5ndGgoTikpKSk7XG4gICAgaWYgKGphY29iaSh3LCBOKSA9PT0gQmlnSW50KC0xKSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIC8vIFRoaXMgaXMgY2FsY3VsYXRpbmcgdGhlIGludmVyc2Ugb2YgdGhlIGZ1bmN0aW9uIHleNCBtb2QgTixcbiAgLy8gaS5lLnkgXiAoMSAvIDQpLCB3aGVyZSBOID0gcHEgaXMgYSBibHVtIGludGVnZXIgdXNpbmcgSE9DIC0gRmFjdCAyLjE2MFxuICAvLyBmcm9tIGNhY3IudXdhdGVybG9vLmNhIC8gaGFjIC8gYWJvdXQgLyBjaGFwMi5wZGZcbiAgLy8gUHJvdmVyIGdlbmVyYXRlcyBhX2ksIGJfaSwgYW5kIHlfaS5cbiAgY29uc3QgeSA9IGdlbmVyYXRlWShOLCB3KTtcbiAgLy8gUHJvdmVyIGNhbGN1bGF0ZXMgel9pID0geV9pIF4gZCBtb2QgTlxuICBjb25zdCB6ID0geS5tYXAoKHlfaSkgPT4gbW9kUG93KHlfaSwgZCwgTikpO1xuICAvLyBQcm92ZXIgY2FsY3VsYXRlcyB4X2kgPSB5X2kgXiAxLzQgbW9kIE4gdXNpbmcgW0hPQyAtIEZhY3QgMi4xNjBdXG4gIGNvbnN0IGUgPSAoKGwgKyBCaWdJbnQoNCkpIC8gQmlnSW50KDgpKSAqKiBCaWdJbnQoMik7XG4gIGNvbnN0IGFiID0gQXJyYXkobSkuZmlsbChudWxsKTtcbiAgY29uc3QgeCA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgIHkubWFwKGFzeW5jICh5X2ksIGkpID0+IHtcbiAgICAgIC8vIFNlbGVjdCByYW5kb20gYV9pLCBiX2kgc28gdGhhdCB5X2knID0gKC0xKV57YV9pfSAqIHdee2JfaX0gKiB5IGlzXG4gICAgICAvLyBxdWFkcmF0aWMgcmVzaWR1ZSBvZiBOIHVzaW5nIFtIT0MgLSBGYWN0IDIuMTM3XS5cbiAgICAgIGxldCBhYl9pLCB0O1xuICAgICAgZm9yIChhYl9pID0gMDsgYWJfaSA8IDQ7IGFiX2krKykge1xuICAgICAgICB0ID0geV9pO1xuICAgICAgICBpZiAoYWJfaSAmIDIpIHtcbiAgICAgICAgICB0ID0gLXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFiX2kgJiAxKSB7XG4gICAgICAgICAgdCAqPSB3O1xuICAgICAgICB9XG4gICAgICAgIGlmIChcbiAgICAgICAgICBtb2RQb3codCwgKHAgLSBCaWdJbnQoMSkpIC8gQmlnSW50KDIpLCBwKSA9PT0gQmlnSW50KDEpICYmXG4gICAgICAgICAgbW9kUG93KHQsIChxIC0gQmlnSW50KDEpKSAvIEJpZ0ludCgyKSwgcSkgPT09IEJpZ0ludCgxKVxuICAgICAgICApIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYWJbaV0gPSBhYl9pO1xuICAgICAgcmV0dXJuIG1vZFBvdyh0LCBlLCBOKTtcbiAgICB9KVxuICApO1xuICByZXR1cm4geyB3LCBhYiwgeCwgeiB9O1xufVxuXG4vKipcbiAqIFZlcmlmeSB0aGF0IE4gaXMgdGhlIHByb2R1Y3Qgb2YgdHdvIGxhcmdlIHByaW1lcy5cbiAqIEBwYXJhbSB7YmlnaW50fSBOIFRoZSBwcmltZSBudW1iZXIgYmVpbmcgdmVyaWZpZWQuXG4gKiBAcGFyYW0ge0Rlc2VyaWFsaXplZFBhaWxsaWVyQmx1bVByb29mfSBUaGUgcHJvb2YgdG8gdmVyaWZ5IE4gaXMgYSBwcm9kdWN0IG9mIHR3byBsYXJnZSBwcmltZXMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBOIGlzIGEgcHJvZHVjdCBvZiB0d28gbGFyZ2UgcHJpbWVzLCBhbmQgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5KE46IGJpZ2ludCwgeyB3LCBhYiwgeCwgeiB9OiBEZXNlcmlhbGl6ZWRQYWlsbGllckJsdW1Qcm9vZik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAvLyBWZXJpZmllciBjaGVja3MgTiA+IDEuXG4gIGlmIChOIDw9IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ04gbXVzdCBiZSBncmVhdGVyIHRoYW4gMScpO1xuICB9XG4gIC8vIFZlcmlmaWVyIGNoZWNrcyBOIGlzIG9kZC5cbiAgaWYgKE4gJSBCaWdJbnQoMikgIT09IEJpZ0ludCgxKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignTiBtdXN0IGJlIGFuIG9kZCBudW1iZXInKTtcbiAgfVxuICAvLyBWZXJpZmllciBjaGVja3MgTiBpcyBub3QgcHJpbWUuXG4gIGlmIChhd2FpdCBpc1Byb2JhYmx5UHJpbWUoTiwgMjQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdOIG11c3QgYmUgYSBjb21wb3NpdGUgbnVtYmVyJyk7XG4gIH1cbiAgLy8gVmVyaWZpZXIgY2hlY2tzIHRoYXQgdGhlIEphY29iaSBzeW1ib2wgZm9yIHcgaXMgMSB3cnQgTi5cbiAgaWYgKGphY29iaSh3LCBOKSAhPT0gQmlnSW50KC0xKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSmFjb2JpIHN5bWJvbCBvZiB3IG11c3QgYmUgLTEgd3J0IHRvIE4nKTtcbiAgfVxuICAvLyBWZXJpZmllciBnZW5lcmF0ZXMgYV9pLCBiX2ksIHlfaS5cbiAgY29uc3QgeSA9IGdlbmVyYXRlWShOLCB3KTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBtOyBpKyspIHtcbiAgICAvLyBWZXJpZmllciBjaGVja3Mgel9pIF4gTiBtb2QgTiA9PSB5X2kuXG4gICAgaWYgKG1vZFBvdyh6W2ldLCBOLCBOKSAhPT0geVtpXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYWlsbGllciB2ZXJpZmljYXRpb24gb2Ygelske2l9XSBmYWlsZWRgKTtcbiAgICB9XG4gICAgLy8gVmVyaWZpZXIgY2hlY2tzIHhfaSBeIDQgbW9kIE4gPT0gKC0xKV5hICogd15iICogeV9pLlxuICAgIGxldCB5X2kgPSB5W2ldO1xuICAgIGlmIChhYltpXSAmIDIpIHtcbiAgICAgIHlfaSA9IC15X2k7XG4gICAgfVxuICAgIGlmIChhYltpXSAmIDEpIHtcbiAgICAgIHlfaSAqPSB3O1xuICAgIH1cbiAgICB5X2kgPSBtb2RQb3coeV9pLCAxLCBOKTtcbiAgICBpZiAobW9kUG93KHhbaV0sIDQsIE4pICE9PSB5X2kpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUGFpbGxpZXIgdmVyaWZpY2F0aW9uIG9mIHhbJHtpfV0gZmFpbGVkYCk7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuIl19
|