reputrans 0.1.0

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.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/circuits/composite/target/composite.json +1 -0
  4. package/circuits/field_disclosure/target/field_disclosure.json +1 -0
  5. package/circuits/map_to_curve/target/map_to_curve.json +1 -0
  6. package/circuits/poseidon_compat/target/poseidon_compat.json +1 -0
  7. package/circuits/range_proof/target/range_proof.json +1 -0
  8. package/circuits/set_membership/target/set_membership.json +1 -0
  9. package/circuits/signature_verify/target/signature_verify.json +1 -0
  10. package/dist/cli/src/auto-detect.d.ts +9 -0
  11. package/dist/cli/src/auto-detect.d.ts.map +1 -0
  12. package/dist/cli/src/auto-detect.js +21 -0
  13. package/dist/cli/src/auto-detect.js.map +1 -0
  14. package/dist/cli/src/commands/inspect.d.ts +6 -0
  15. package/dist/cli/src/commands/inspect.d.ts.map +1 -0
  16. package/dist/cli/src/commands/inspect.js +43 -0
  17. package/dist/cli/src/commands/inspect.js.map +1 -0
  18. package/dist/cli/src/commands/issue.d.ts +8 -0
  19. package/dist/cli/src/commands/issue.d.ts.map +1 -0
  20. package/dist/cli/src/commands/issue.js +107 -0
  21. package/dist/cli/src/commands/issue.js.map +1 -0
  22. package/dist/cli/src/commands/keygen.d.ts +7 -0
  23. package/dist/cli/src/commands/keygen.d.ts.map +1 -0
  24. package/dist/cli/src/commands/keygen.js +39 -0
  25. package/dist/cli/src/commands/keygen.js.map +1 -0
  26. package/dist/cli/src/commands/prove.d.ts +9 -0
  27. package/dist/cli/src/commands/prove.d.ts.map +1 -0
  28. package/dist/cli/src/commands/prove.js +139 -0
  29. package/dist/cli/src/commands/prove.js.map +1 -0
  30. package/dist/cli/src/commands/verify.d.ts +6 -0
  31. package/dist/cli/src/commands/verify.d.ts.map +1 -0
  32. package/dist/cli/src/commands/verify.js +63 -0
  33. package/dist/cli/src/commands/verify.js.map +1 -0
  34. package/dist/cli/src/index.d.ts +3 -0
  35. package/dist/cli/src/index.d.ts.map +1 -0
  36. package/dist/cli/src/index.js +45 -0
  37. package/dist/cli/src/index.js.map +1 -0
  38. package/dist/sdk/src/circuit-loader.d.ts +19 -0
  39. package/dist/sdk/src/circuit-loader.d.ts.map +1 -0
  40. package/dist/sdk/src/circuit-loader.js +65 -0
  41. package/dist/sdk/src/circuit-loader.js.map +1 -0
  42. package/dist/sdk/src/eddsa.d.ts +63 -0
  43. package/dist/sdk/src/eddsa.d.ts.map +1 -0
  44. package/dist/sdk/src/eddsa.js +177 -0
  45. package/dist/sdk/src/eddsa.js.map +1 -0
  46. package/dist/sdk/src/encoder.d.ts +49 -0
  47. package/dist/sdk/src/encoder.d.ts.map +1 -0
  48. package/dist/sdk/src/encoder.js +117 -0
  49. package/dist/sdk/src/encoder.js.map +1 -0
  50. package/dist/sdk/src/identity.d.ts +69 -0
  51. package/dist/sdk/src/identity.d.ts.map +1 -0
  52. package/dist/sdk/src/identity.js +110 -0
  53. package/dist/sdk/src/identity.js.map +1 -0
  54. package/dist/sdk/src/index.d.ts +18 -0
  55. package/dist/sdk/src/index.d.ts.map +1 -0
  56. package/dist/sdk/src/index.js +18 -0
  57. package/dist/sdk/src/index.js.map +1 -0
  58. package/dist/sdk/src/poseidon.d.ts +33 -0
  59. package/dist/sdk/src/poseidon.d.ts.map +1 -0
  60. package/dist/sdk/src/poseidon.js +59 -0
  61. package/dist/sdk/src/poseidon.js.map +1 -0
  62. package/dist/sdk/src/proof-request.d.ts +58 -0
  63. package/dist/sdk/src/proof-request.d.ts.map +1 -0
  64. package/dist/sdk/src/proof-request.js +68 -0
  65. package/dist/sdk/src/proof-request.js.map +1 -0
  66. package/dist/sdk/src/prover.d.ts +38 -0
  67. package/dist/sdk/src/prover.d.ts.map +1 -0
  68. package/dist/sdk/src/prover.js +108 -0
  69. package/dist/sdk/src/prover.js.map +1 -0
  70. package/dist/sdk/src/vc-parser.d.ts +50 -0
  71. package/dist/sdk/src/vc-parser.d.ts.map +1 -0
  72. package/dist/sdk/src/vc-parser.js +96 -0
  73. package/dist/sdk/src/vc-parser.js.map +1 -0
  74. package/dist/sdk/src/verifier.d.ts +19 -0
  75. package/dist/sdk/src/verifier.d.ts.map +1 -0
  76. package/dist/sdk/src/verifier.js +31 -0
  77. package/dist/sdk/src/verifier.js.map +1 -0
  78. package/dist/verifier/src/did-resolver.d.ts +36 -0
  79. package/dist/verifier/src/did-resolver.d.ts.map +1 -0
  80. package/dist/verifier/src/did-resolver.js +179 -0
  81. package/dist/verifier/src/did-resolver.js.map +1 -0
  82. package/dist/verifier/src/index.d.ts +2 -0
  83. package/dist/verifier/src/index.d.ts.map +1 -0
  84. package/dist/verifier/src/index.js +9 -0
  85. package/dist/verifier/src/index.js.map +1 -0
  86. package/dist/verifier/src/server.d.ts +6 -0
  87. package/dist/verifier/src/server.d.ts.map +1 -0
  88. package/dist/verifier/src/server.js +75 -0
  89. package/dist/verifier/src/server.js.map +1 -0
  90. package/dist/verifier/src/verify.d.ts +20 -0
  91. package/dist/verifier/src/verify.d.ts.map +1 -0
  92. package/dist/verifier/src/verify.js +97 -0
  93. package/dist/verifier/src/verify.js.map +1 -0
  94. package/package.json +41 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Circuit artifact loader for REPUTRANS.
3
+ *
4
+ * Loads compiled Noir ACIR artifacts from the filesystem.
5
+ * Works in Node.js only (uses fs). For browser usage, load
6
+ * the JSON via fetch and pass directly to createProver/createVerifier.
7
+ */
8
+ import { readFile } from 'fs/promises';
9
+ import { resolve, join, dirname } from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ import { accessSync } from 'fs';
12
+ /** Resolve package root from this file's location (works in both source and dist). */
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+ /**
16
+ * Walk up from this file to find the package root (directory containing package.json).
17
+ * In source: sdk/src/ -> 2 levels up
18
+ * In dist: dist/sdk/src/ -> 3 levels up
19
+ */
20
+ function findPackageRoot() {
21
+ let dir = __dirname;
22
+ for (let i = 0; i < 5; i++) {
23
+ try {
24
+ accessSync(join(dir, 'package.json'));
25
+ return dir;
26
+ }
27
+ catch {
28
+ dir = dirname(dir);
29
+ }
30
+ }
31
+ return resolve(__dirname, '..', '..');
32
+ }
33
+ const DEFAULT_CIRCUITS_DIR = join(findPackageRoot(), 'circuits');
34
+ /**
35
+ * Load a compiled circuit artifact by name.
36
+ *
37
+ * @param name - Circuit name (must match the directory and JSON filename)
38
+ * @param circuitsDir - Override the circuits directory path. Defaults to
39
+ * the monorepo's circuits/ directory relative to this file, or the
40
+ * REPUTRANS_CIRCUITS_DIR environment variable.
41
+ */
42
+ export async function loadCircuit(name, circuitsDir) {
43
+ // Sanitize circuit name to prevent path traversal
44
+ if (!/^[a-z_]+$/.test(name)) {
45
+ throw new Error(`Invalid circuit name: "${name}" (must match /^[a-z_]+$/)`);
46
+ }
47
+ const dir = circuitsDir ?? process.env.REPUTRANS_CIRCUITS_DIR ?? DEFAULT_CIRCUITS_DIR;
48
+ const artifactPath = join(dir, name, 'target', `${name}.json`);
49
+ const resolved = resolve(artifactPath);
50
+ let raw;
51
+ try {
52
+ raw = await readFile(resolved, 'utf-8');
53
+ }
54
+ catch (err) {
55
+ throw new Error(`Failed to load circuit artifact at ${resolved}: ${err.message}. ` +
56
+ `Ensure circuits are compiled via 'nargo compile' in WSL.`);
57
+ }
58
+ const parsed = JSON.parse(raw);
59
+ // Validate it looks like a compiled circuit
60
+ if (!parsed.bytecode || !parsed.abi) {
61
+ throw new Error(`Invalid circuit artifact at ${resolved}: missing 'bytecode' or 'abi' field`);
62
+ }
63
+ return parsed;
64
+ }
65
+ //# sourceMappingURL=circuit-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-loader.js","sourceRoot":"","sources":["../../../sdk/src/circuit-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAU,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAGhC,sFAAsF;AACtF,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;GAIG;AACH,SAAS,eAAe;IACtB,IAAI,GAAG,GAAG,SAAS,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;YACtC,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,UAAU,CAAC,CAAC;AAWjE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAA0B,EAC1B,WAAoB;IAEpB,kDAAkD;IAClD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,4BAA4B,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,GAAG,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,oBAAoB,CAAC;IACtF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAEvC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,sCAAsC,QAAQ,KAAK,GAAG,CAAC,OAAO,IAAI;YAClE,0DAA0D,CAC3D,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,4CAA4C;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,+BAA+B,QAAQ,qCAAqC,CAC7E,CAAC;IACJ,CAAC;IAED,OAAO,MAAyB,CAAC;AACnC,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * EdDSA signing and verification on Baby Jubjub (BN254 embedded curve)
3
+ * using the CORRECT Poseidon hash (poseidon-lite, matching Noir's stdlib).
4
+ *
5
+ * This replaces the hackathon code that incorrectly used bb.poseidon2Hash().
6
+ *
7
+ * EdDSA scheme (matching Noir's eddsa_poseidon_verify):
8
+ * Sign: h = poseidon5(R8.x, R8.y, A.x, A.y, msg), S = r + h * sk mod l
9
+ * Verify: h = poseidon5(R8.x, R8.y, A.x, A.y, msg), S * G == R8 + h * A
10
+ *
11
+ * Curve: Baby Jubjub (twisted Edwards, embedded in BN254)
12
+ * a = 168700, d = 168696
13
+ * Subgroup order l = 2736030358979909402780800718157159386076813972158567259200215660948447373041
14
+ */
15
+ declare const BJJ: {
16
+ readonly a: 168700n;
17
+ readonly d: 168696n;
18
+ readonly l: 2736030358979909402780800718157159386076813972158567259200215660948447373041n;
19
+ readonly p: 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
20
+ readonly Gx: 5299619240641551281634865583518297030282874472190772894086521144482721001553n;
21
+ readonly Gy: 16950150798460657717958625567821834550301663161624707787222815936182638968203n;
22
+ };
23
+ export interface Point {
24
+ x: bigint;
25
+ y: bigint;
26
+ }
27
+ export interface EdDSASignature {
28
+ r8: Point;
29
+ s: bigint;
30
+ }
31
+ declare const IDENTITY: Point;
32
+ declare function mod(a: bigint, m: bigint): bigint;
33
+ declare function pointAdd(p1: Point, p2: Point): Point;
34
+ declare function scalarMul(pt: Point, scalar: bigint): Point;
35
+ declare const G: Point;
36
+ /**
37
+ * Compute public key from private key: A = sk * G
38
+ */
39
+ export declare function getPublicKey(privateKey: bigint): Point;
40
+ /**
41
+ * Sign a message using EdDSA on Baby Jubjub with Poseidon hash.
42
+ *
43
+ * This produces signatures compatible with Noir's eddsa_poseidon_verify:
44
+ * h = poseidon5(R8.x, R8.y, A.x, A.y, msg)
45
+ * S = r + h * sk (mod l)
46
+ *
47
+ * @param privateKey - scalar in [1, l-1]
48
+ * @param msg - field element (the message to sign)
49
+ * @returns EdDSA signature {r8, s} and the public key
50
+ */
51
+ export declare function sign(privateKey: bigint, msg: bigint): {
52
+ signature: EdDSASignature;
53
+ publicKey: Point;
54
+ };
55
+ /**
56
+ * Verify an EdDSA signature (mirrors Noir's eddsa_poseidon_verify).
57
+ *
58
+ * h = poseidon5(R8.x, R8.y, A.x, A.y, msg)
59
+ * Check: S * G == R8 + h * A
60
+ */
61
+ export declare function verify(publicKey: Point, msg: bigint, signature: EdDSASignature): boolean;
62
+ export { BJJ, G, IDENTITY, scalarMul, pointAdd, mod };
63
+ //# sourceMappingURL=eddsa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eddsa.d.ts","sourceRoot":"","sources":["../../../sdk/src/eddsa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,QAAA,MAAM,GAAG;;;;;;;CAUC,CAAC;AAEX,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,KAAK,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,QAAA,MAAM,QAAQ,EAAE,KAAwB,CAAC;AAIzC,iBAAS,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzC;AAgCD,iBAAS,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,KAAK,CAe7C;AAED,iBAAS,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAWnD;AAED,QAAA,MAAM,CAAC,EAAE,KAAgC,CAAC;AAqC1C;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAEtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAClB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,GACV;IAAE,SAAS,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,KAAK,CAAA;CAAE,CAuBjD;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,SAAS,EAAE,KAAK,EAChB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,cAAc,GACxB,OAAO,CAYT;AAGD,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * EdDSA signing and verification on Baby Jubjub (BN254 embedded curve)
3
+ * using the CORRECT Poseidon hash (poseidon-lite, matching Noir's stdlib).
4
+ *
5
+ * This replaces the hackathon code that incorrectly used bb.poseidon2Hash().
6
+ *
7
+ * EdDSA scheme (matching Noir's eddsa_poseidon_verify):
8
+ * Sign: h = poseidon5(R8.x, R8.y, A.x, A.y, msg), S = r + h * sk mod l
9
+ * Verify: h = poseidon5(R8.x, R8.y, A.x, A.y, msg), S * G == R8 + h * A
10
+ *
11
+ * Curve: Baby Jubjub (twisted Edwards, embedded in BN254)
12
+ * a = 168700, d = 168696
13
+ * Subgroup order l = 2736030358979909402780800718157159386076813972158567259200215660948447373041
14
+ */
15
+ import { sha512 } from '@noble/hashes/sha2';
16
+ import { poseidonHash } from './poseidon.js';
17
+ // Baby Jubjub parameters
18
+ const BJJ = {
19
+ a: 168700n,
20
+ d: 168696n,
21
+ // Prime subgroup order
22
+ l: 2736030358979909402780800718157159386076813972158567259200215660948447373041n,
23
+ // BN254 base field modulus (coordinate arithmetic)
24
+ p: 21888242871839275222246405745257275088548364400416034343698204186575808495617n,
25
+ // Generator point (prime-order subgroup)
26
+ Gx: 5299619240641551281634865583518297030282874472190772894086521144482721001553n,
27
+ Gy: 16950150798460657717958625567821834550301663161624707787222815936182638968203n,
28
+ };
29
+ const IDENTITY = { x: 0n, y: 1n };
30
+ // -- Field arithmetic mod p (coordinates) --
31
+ function mod(a, m) {
32
+ const r = a % m;
33
+ return r >= 0n ? r : r + m;
34
+ }
35
+ function modMul(a, b, m) {
36
+ return mod(a * b, m);
37
+ }
38
+ function modAdd(a, b, m) {
39
+ return mod(a + b, m);
40
+ }
41
+ function modSub(a, b, m) {
42
+ return mod(a - b, m);
43
+ }
44
+ function extGcd(a, b) {
45
+ if (a === 0n)
46
+ return [b, 0n, 1n];
47
+ const [g, x1, y1] = extGcd(mod(b, a), a);
48
+ return [g, y1 - (b / a) * x1, x1];
49
+ }
50
+ function modInv(a, m) {
51
+ const a_ = mod(a, m);
52
+ if (a_ === 0n)
53
+ throw new Error('modInv: zero');
54
+ const [g, x] = extGcd(a_, m);
55
+ if (g !== 1n)
56
+ throw new Error('modInv: not invertible');
57
+ return mod(x, m);
58
+ }
59
+ // -- Baby Jubjub point operations --
60
+ const { a: A_COEFF, d: D_COEFF, p: P } = BJJ;
61
+ function pointAdd(p1, p2) {
62
+ const x1x2 = modMul(p1.x, p2.x, P);
63
+ const y1y2 = modMul(p1.y, p2.y, P);
64
+ const dx1x2y1y2 = modMul(D_COEFF, modMul(x1x2, y1y2, P), P);
65
+ const numX = modAdd(modMul(p1.x, p2.y, P), modMul(p1.y, p2.x, P), P);
66
+ const denX = modAdd(1n, dx1x2y1y2, P);
67
+ const numY = modSub(y1y2, modMul(A_COEFF, x1x2, P), P);
68
+ const denY = modSub(1n, dx1x2y1y2, P);
69
+ return {
70
+ x: modMul(numX, modInv(denX, P), P),
71
+ y: modMul(numY, modInv(denY, P), P),
72
+ };
73
+ }
74
+ function scalarMul(pt, scalar) {
75
+ let s = mod(scalar, BJJ.l);
76
+ if (s === 0n)
77
+ return IDENTITY;
78
+ let result = IDENTITY;
79
+ let current = { ...pt };
80
+ while (s > 0n) {
81
+ if (s & 1n)
82
+ result = pointAdd(result, current);
83
+ current = pointAdd(current, current);
84
+ s >>= 1n;
85
+ }
86
+ return result;
87
+ }
88
+ const G = { x: BJJ.Gx, y: BJJ.Gy };
89
+ // -- Helpers --
90
+ function bigintToBytes(val, len) {
91
+ const bytes = new Uint8Array(len);
92
+ let v = val < 0n ? -val : val;
93
+ for (let i = len - 1; i >= 0; i--) {
94
+ bytes[i] = Number(v & 0xffn);
95
+ v >>= 8n;
96
+ }
97
+ return bytes;
98
+ }
99
+ function bytesToBigint(bytes) {
100
+ let r = 0n;
101
+ for (const b of bytes)
102
+ r = (r << 8n) | BigInt(b);
103
+ return r;
104
+ }
105
+ /**
106
+ * Derive a deterministic nonce from private key and message.
107
+ * Uses SHA-512 (same approach as standard EdDSA nonce generation).
108
+ */
109
+ function deriveNonce(privateKey, message) {
110
+ const skBytes = bigintToBytes(privateKey, 32);
111
+ const msgBytes = bigintToBytes(message, 32);
112
+ const combined = new Uint8Array(64);
113
+ combined.set(skBytes, 0);
114
+ combined.set(msgBytes, 32);
115
+ const hash = sha512(combined);
116
+ // Take first 32 bytes, reduce mod l
117
+ const val = bytesToBigint(hash.slice(0, 32));
118
+ const r = mod(val, BJJ.l);
119
+ return r === 0n ? 1n : r;
120
+ }
121
+ /**
122
+ * Compute public key from private key: A = sk * G
123
+ */
124
+ export function getPublicKey(privateKey) {
125
+ return scalarMul(G, privateKey);
126
+ }
127
+ /**
128
+ * Sign a message using EdDSA on Baby Jubjub with Poseidon hash.
129
+ *
130
+ * This produces signatures compatible with Noir's eddsa_poseidon_verify:
131
+ * h = poseidon5(R8.x, R8.y, A.x, A.y, msg)
132
+ * S = r + h * sk (mod l)
133
+ *
134
+ * @param privateKey - scalar in [1, l-1]
135
+ * @param msg - field element (the message to sign)
136
+ * @returns EdDSA signature {r8, s} and the public key
137
+ */
138
+ export function sign(privateKey, msg) {
139
+ const L = BJJ.l;
140
+ const A = getPublicKey(privateKey);
141
+ // Deterministic nonce
142
+ const r = deriveNonce(privateKey, msg);
143
+ const R8 = scalarMul(G, r);
144
+ // Hash: h = poseidon5(R8.x, R8.y, A.x, A.y, msg)
145
+ // Noir uses h as a BN254 field element (mod p), NOT reduced mod L.
146
+ // We must match: use h directly from Poseidon (already mod p), then
147
+ // compute S = r + h * sk mod L for the scalar equation.
148
+ const h = poseidonHash(R8.x, R8.y, A.x, A.y, msg);
149
+ // S = r + h * (8 * sk) mod l
150
+ // Noir's eddsa_poseidon_verify checks S*B8 == R8 + h*(8*A).
151
+ // Since A = sk*B8, we need 8*A = 8*sk*B8, so S must incorporate 8*sk.
152
+ const S = mod(r + h * (8n * privateKey), L);
153
+ return {
154
+ signature: { r8: R8, s: S },
155
+ publicKey: A,
156
+ };
157
+ }
158
+ /**
159
+ * Verify an EdDSA signature (mirrors Noir's eddsa_poseidon_verify).
160
+ *
161
+ * h = poseidon5(R8.x, R8.y, A.x, A.y, msg)
162
+ * Check: S * G == R8 + h * A
163
+ */
164
+ export function verify(publicKey, msg, signature) {
165
+ const L = BJJ.l;
166
+ // Use h as field element (mod p) to match Noir's eddsa_poseidon_verify
167
+ const h = poseidonHash(signature.r8.x, signature.r8.y, publicKey.x, publicKey.y, msg);
168
+ const lhs = scalarMul(G, signature.s);
169
+ // Noir multiplies pubkey by cofactor 8: A8 = 8*A
170
+ const A8 = scalarMul(publicKey, 8n);
171
+ const hA8 = scalarMul(A8, h);
172
+ const rhs = pointAdd(signature.r8, hA8);
173
+ return lhs.x === rhs.x && lhs.y === rhs.y;
174
+ }
175
+ // Re-export curve constants for external use
176
+ export { BJJ, G, IDENTITY, scalarMul, pointAdd, mod };
177
+ //# sourceMappingURL=eddsa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eddsa.js","sourceRoot":"","sources":["../../../sdk/src/eddsa.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Deterministic JSON-to-circuit-input encoder for REPUTRANS.
3
+ *
4
+ * Converts credential fields into BN254 field elements, builds a
5
+ * Poseidon Merkle tree (depth 4, 16 leaves), and outputs everything
6
+ * the circuit needs as witness inputs.
7
+ */
8
+ /** Depth of the credential field Merkle tree (16 leaves max). */
9
+ export declare const FIELD_TREE_DEPTH = 4;
10
+ export declare const MAX_LEAVES: number;
11
+ export interface MerklePath {
12
+ siblings: bigint[];
13
+ indices: number[];
14
+ }
15
+ export interface EncodedCredential {
16
+ /** Poseidon Merkle root of the field values. */
17
+ merkleRoot: bigint;
18
+ /** Ordered field values as BN254 field elements (padded to 16 with 0n). */
19
+ fieldValues: bigint[];
20
+ /** Canonical field names in the same order as fieldValues. */
21
+ fieldNames: string[];
22
+ /** Merkle path for each leaf index. */
23
+ merklePaths: MerklePath[];
24
+ }
25
+ /**
26
+ * Convert a string value to a BN254 field element.
27
+ *
28
+ * - Numeric strings and bigint-like hex strings are parsed directly.
29
+ * - Other strings are hashed: UTF-8 bytes are packed into a bigint, then reduced mod p.
30
+ */
31
+ export declare function stringToField(value: string): bigint;
32
+ /**
33
+ * Encode a record of string key-value pairs into circuit inputs.
34
+ *
35
+ * Keys are sorted alphabetically for deterministic ordering.
36
+ * Values are converted to BN254 field elements.
37
+ * A depth-4 Poseidon Merkle tree is built over the 16 leaf slots.
38
+ */
39
+ export declare function encodeCredential(fields: Record<string, string>): EncodedCredential;
40
+ /**
41
+ * Build a Poseidon Merkle tree from leaves.
42
+ * Returns all layers: layers[0] = leaves, layers[DEPTH] = [root].
43
+ */
44
+ export declare function buildMerkleTree(leaves: bigint[]): bigint[][];
45
+ /**
46
+ * Get the Merkle path (siblings + direction indices) for a leaf.
47
+ */
48
+ export declare function getMerklePath(tree: bigint[][], leafIndex: number): MerklePath;
49
+ //# sourceMappingURL=encoder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../sdk/src/encoder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,UAAU,QAAwB,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,uCAAuC;IACvC,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA2BnD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,iBAAiB,CA8BlF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE,CAkB5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAkB7E"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Deterministic JSON-to-circuit-input encoder for REPUTRANS.
3
+ *
4
+ * Converts credential fields into BN254 field elements, builds a
5
+ * Poseidon Merkle tree (depth 4, 16 leaves), and outputs everything
6
+ * the circuit needs as witness inputs.
7
+ */
8
+ import { poseidonHash, BN254_FIELD_ORDER } from './poseidon.js';
9
+ /** Depth of the credential field Merkle tree (16 leaves max). */
10
+ export const FIELD_TREE_DEPTH = 4;
11
+ export const MAX_LEAVES = 1 << FIELD_TREE_DEPTH; // 16
12
+ /**
13
+ * Convert a string value to a BN254 field element.
14
+ *
15
+ * - Numeric strings and bigint-like hex strings are parsed directly.
16
+ * - Other strings are hashed: UTF-8 bytes are packed into a bigint, then reduced mod p.
17
+ */
18
+ export function stringToField(value) {
19
+ // Try numeric parse first
20
+ const trimmed = value.trim();
21
+ // Hex
22
+ if (trimmed.startsWith('0x') || trimmed.startsWith('0X')) {
23
+ const val = BigInt(trimmed);
24
+ if (val >= 0n && val < BN254_FIELD_ORDER)
25
+ return val;
26
+ return val % BN254_FIELD_ORDER;
27
+ }
28
+ // Decimal integer or bigint
29
+ if (/^-?\d+$/.test(trimmed)) {
30
+ let val = BigInt(trimmed);
31
+ if (val < 0n)
32
+ val = val + BN254_FIELD_ORDER;
33
+ if (val >= BN254_FIELD_ORDER)
34
+ val = val % BN254_FIELD_ORDER;
35
+ return val;
36
+ }
37
+ // Arbitrary string: pack UTF-8 bytes into bigint, reduce mod p
38
+ const encoder = new TextEncoder();
39
+ const bytes = encoder.encode(trimmed);
40
+ let val = 0n;
41
+ for (const b of bytes) {
42
+ val = (val << 8n) | BigInt(b);
43
+ }
44
+ return val % BN254_FIELD_ORDER;
45
+ }
46
+ /**
47
+ * Encode a record of string key-value pairs into circuit inputs.
48
+ *
49
+ * Keys are sorted alphabetically for deterministic ordering.
50
+ * Values are converted to BN254 field elements.
51
+ * A depth-4 Poseidon Merkle tree is built over the 16 leaf slots.
52
+ */
53
+ export function encodeCredential(fields) {
54
+ const sortedKeys = Object.keys(fields).sort();
55
+ if (sortedKeys.length > MAX_LEAVES) {
56
+ throw new Error(`Too many fields: ${sortedKeys.length} (max ${MAX_LEAVES})`);
57
+ }
58
+ // Convert to field elements, pad to 16
59
+ const fieldValues = sortedKeys.map((k) => stringToField(fields[k]));
60
+ while (fieldValues.length < MAX_LEAVES) {
61
+ fieldValues.push(0n);
62
+ }
63
+ // Pad field names too
64
+ const fieldNames = [...sortedKeys];
65
+ while (fieldNames.length < MAX_LEAVES) {
66
+ fieldNames.push('');
67
+ }
68
+ // Build Poseidon Merkle tree bottom-up
69
+ const tree = buildMerkleTree(fieldValues);
70
+ const merkleRoot = tree[tree.length - 1][0];
71
+ // Compute paths for all leaves
72
+ const merklePaths = [];
73
+ for (let i = 0; i < MAX_LEAVES; i++) {
74
+ merklePaths.push(getMerklePath(tree, i));
75
+ }
76
+ return { merkleRoot, fieldValues, fieldNames, merklePaths };
77
+ }
78
+ /**
79
+ * Build a Poseidon Merkle tree from leaves.
80
+ * Returns all layers: layers[0] = leaves, layers[DEPTH] = [root].
81
+ */
82
+ export function buildMerkleTree(leaves) {
83
+ if (leaves.length !== MAX_LEAVES) {
84
+ throw new Error(`Expected ${MAX_LEAVES} leaves, got ${leaves.length}`);
85
+ }
86
+ const layers = [[...leaves]];
87
+ let current = leaves;
88
+ for (let d = 0; d < FIELD_TREE_DEPTH; d++) {
89
+ const next = [];
90
+ for (let i = 0; i < current.length; i += 2) {
91
+ next.push(poseidonHash(current[i], current[i + 1]));
92
+ }
93
+ layers.push(next);
94
+ current = next;
95
+ }
96
+ return layers;
97
+ }
98
+ /**
99
+ * Get the Merkle path (siblings + direction indices) for a leaf.
100
+ */
101
+ export function getMerklePath(tree, leafIndex) {
102
+ if (leafIndex < 0 || leafIndex >= MAX_LEAVES) {
103
+ throw new Error(`Leaf index out of range: ${leafIndex}`);
104
+ }
105
+ const siblings = [];
106
+ const indices = [];
107
+ let idx = leafIndex;
108
+ for (let d = 0; d < FIELD_TREE_DEPTH; d++) {
109
+ const layer = tree[d];
110
+ const siblingIdx = idx % 2 === 0 ? idx + 1 : idx - 1;
111
+ siblings.push(layer[siblingIdx]);
112
+ indices.push(idx % 2); // 0 if we are the left child, 1 if right
113
+ idx = Math.floor(idx / 2);
114
+ }
115
+ return { siblings, indices };
116
+ }
117
+ //# sourceMappingURL=encoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.js","sourceRoot":"","sources":["../../../sdk/src/encoder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Identity management for REPUTRANS Provars.
3
+ *
4
+ * All operations use Poseidon hash (NOT Pedersen) for consistency
5
+ * with the circuit layer. Generates master identities, derives
6
+ * platform-specific keys, and computes nullifiers.
7
+ *
8
+ * Naming: Provar = credential holder, Arbiter = verifier.
9
+ */
10
+ export interface ProvarIdentity {
11
+ /** Master secret - 254-bit BN254 field element. NEVER share this. */
12
+ masterSecret: bigint;
13
+ /** Poseidon commitment of master secret (for anonymity set membership). */
14
+ commitment: bigint;
15
+ }
16
+ export interface DerivedKey {
17
+ /** The platform identifier used in derivation. */
18
+ platformId: bigint;
19
+ /** Derived key: poseidon(masterSecret, platformId). */
20
+ key: bigint;
21
+ }
22
+ /**
23
+ * Generate a new Provar master identity.
24
+ *
25
+ * The master secret is a random BN254 field element.
26
+ * The commitment is poseidon(masterSecret, 0) - a binding commitment
27
+ * that can be registered in an anonymity set without revealing the secret.
28
+ */
29
+ export declare function generateIdentity(): ProvarIdentity;
30
+ /**
31
+ * Reconstruct identity from an existing master secret.
32
+ */
33
+ export declare function identityFromSecret(masterSecret: bigint): ProvarIdentity;
34
+ /**
35
+ * Derive a platform-specific key from the master secret.
36
+ *
37
+ * key = poseidon(masterSecret, platformId)
38
+ *
39
+ * This allows different keys per platform while maintaining
40
+ * a single master identity. The platform cannot link back to
41
+ * the master secret or to keys on other platforms.
42
+ */
43
+ export declare function derivePlatformKey(masterSecret: bigint, platformId: bigint): DerivedKey;
44
+ /**
45
+ * Compute a nullifier for replay prevention.
46
+ *
47
+ * nullifier = poseidon(masterSecret, contextId)
48
+ *
49
+ * The context is typically a domain separator (e.g. hash of the
50
+ * Arbiter's address + session nonce). Same master secret + same context
51
+ * always produces the same nullifier, preventing double-spending
52
+ * without revealing the identity.
53
+ */
54
+ export declare function computeNullifier(masterSecret: bigint, contextId: bigint): bigint;
55
+ /**
56
+ * Convert a string context (e.g. "arbiter:0x1234:session:5") into a
57
+ * field element suitable for nullifier computation.
58
+ *
59
+ * Uses Poseidon hash of packed chunks for collision resistance,
60
+ * rather than raw byte packing which is vulnerable to collisions
61
+ * on inputs longer than 31 bytes.
62
+ */
63
+ export declare function contextToField(context: string): bigint;
64
+ /**
65
+ * Compute a Poseidon commitment of the master secret.
66
+ * This is the value registered in the anonymity set.
67
+ */
68
+ export declare function computeCommitment(masterSecret: bigint): bigint;
69
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../sdk/src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;CACb;AAcD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAIjD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,CAMvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAGtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAqBtD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE9D"}