UNPKG

@cloudflare/zkp-ecdsa

Version:

zkp-ecdsa: A Typescript Implementation of ZKAttest

198 lines 5.09 kB
export function verifyPosRange(a, n) { if (!(BigInt(0) <= a && a < n)) { throw new Error('a not in range'); } return true; } export function bitLen(n) { return n.toString(2).length; } export function byteLen(n) { return Math.ceil(bitLen(n) / 8); } export function isOdd(n) { return n % BigInt(2) === BigInt(1); } export function isEven(n) { return n % BigInt(2) === BigInt(0); } export function posMod(n, p) { let r = n % p; if (r < BigInt(0)) { r = (r + p) % p; } return r; } export function expMod(n, e, p) { if (e < BigInt(0)) { throw new Error('neg expo'); } let r = BigInt(1), q = n, k = e; while (k > BigInt(0)) { if (isOdd(k)) { r = (r * q) % p; } q = (q * q) % p; k = k / BigInt(2); } return r; } export function isNonNegative(n, p) { const pMinus1div2 = (p - BigInt(1)) >> BigInt(1); return 0 <= n && n <= pMinus1div2; } export function absolute(n, p) { return isNonNegative(n, p) ? n : posMod(-n, p); } export function isSquare(n, p) { const q = (p - BigInt(1)) >> BigInt(1); return expMod(n, q, p) === BigInt(1); } export function invSqrtMod(n, p) { const q = (p + BigInt(1)) >> BigInt(2); return expMod(invEuclid(n, p), q, p); } export function invMod(n, p) { return invEuclid(n, p); } function extendedEuclid(X, Y) { let a = BigInt(1), b = BigInt(0), c = BigInt(0), d = BigInt(1), x = X, y = Y, t = BigInt(0); while (y != BigInt(0)) { const q = x / y; a = a - c * q; b = b - d * q; x = x - q * y; t = x; x = y; y = t; t = a; a = c; c = t; t = b; b = d; d = t; } return { g: x, a: a, b: b, }; } export function invEuclid(t, N) { const res = extendedEuclid(t, N); let inv = res.a; if (inv < 0) { inv += N; } return inv; } export function toBytes(n, len) { const maxBig = BigInt(1) << (BigInt(8) * BigInt(len)); if (!(len > 0 && BigInt(0) <= n && n < maxBig)) { throw new Error("number doesn't fit in array"); } const ret = new Uint8Array(len); let t = n; for (let i = 0; i < len; i++) { const b = t & BigInt(255); ret[len - 1 - i] = parseInt(b.toString()); t >>= BigInt(8); } return ret; } export async function hashNums(nums) { const numNums = nums.length, data = [], enc = new TextEncoder(); let totBytes = 0; for (let i = 0; i < numNums; i++) { const numBytes = enc.encode(nums[i].toString()); totBytes += numBytes.byteLength; data.push(numBytes); } const tbh = new Uint8Array(totBytes + 4 * numNums); let index = 0; for (let i = 0; i < numNums; i++) { tbh[index++] = (data[i].byteLength >> 24) & 0xff; tbh[index++] = (data[i].byteLength >> 16) & 0xff; tbh[index++] = (data[i].byteLength >> 8) & 0xff; tbh[index++] = data[i].byteLength & 0xff; tbh.set(data[i], index); index += data[i].byteLength; } const hash = await crypto.subtle.digest('SHA-256', tbh); return fromBytes(new Uint8Array(hash.slice(0, 10))); } export function fromBytes(a) { let k = BigInt(0); for (const ai of a) { k <<= BigInt(8); k |= BigInt(ai); } return k; } export function rnd(n) { const buffer = new Uint8Array(byteLen(n)); while (true) { crypto.getRandomValues(buffer); const ret = fromBytes(buffer); if (ret < n) { return ret; } } } export function rndRange(min, max) { return rnd(max - min + BigInt(1)) + min; } export function isPrime(n, iterations = 7) { if (n === BigInt(2) || n === BigInt(3)) { return true; } if (isEven(n) || n < BigInt(2)) { return false; } const nminusone = n - BigInt(1); let s = 0, d = nminusone; while (isEven(d)) { d >>= BigInt(1); s++; } let k = iterations; WitnessLoop: do { const base = rnd(n - BigInt(3)) + BigInt(2); let x = expMod(base, d, n); if (x === BigInt(1) || x === n - BigInt(1)) { continue; } for (let i = s - 1; i >= 0; i--) { x = x ** BigInt(2) % n; if (x === BigInt(1)) { return false; } if (x === n - BigInt(1)) { continue WitnessLoop; } } return false; } while ((k -= 1)); return true; } export const serdeBigInt = { isRequired: true, serializer: function (v) { let s = '0x'; if (v < BigInt(0)) { v = -v; s = '-' + s; } return s + v.toString(16); }, deserializer: function (v) { if (!v) { throw new Error(`the field ${this.key} is required`); } if (v.charAt(0) === '-') { return -BigInt(v.slice(1)); } return BigInt(v); }, }; //# sourceMappingURL=big.js.map