shogun-core 5.2.0 → 5.2.2
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 +145 -1143
- package/dist/browser/defaultVendors-node_modules_hpke_chacha20poly1305_esm_mod_js.shogun-core.js +1220 -0
- package/dist/browser/defaultVendors-node_modules_hpke_chacha20poly1305_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_hpke_hybridkem-x-wing_esm_mod_js.shogun-core.js +844 -0
- package/dist/browser/defaultVendors-node_modules_hpke_hybridkem-x-wing_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js +2335 -0
- package/dist/browser/defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_ciphers_chacha_js.shogun-core.js +999 -0
- package/dist/browser/defaultVendors-node_modules_noble_ciphers_chacha_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js +1651 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_edwards_js-node_modules_noble_curves_es-a82056.shogun-core.js +825 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_edwards_js-node_modules_noble_curves_es-a82056.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed25519_js.shogun-core.js +508 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed25519_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js +747 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js +1608 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_post-quantum_ml-dsa_js.shogun-core.js +2117 -0
- package/dist/browser/defaultVendors-node_modules_noble_post-quantum_ml-dsa_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_openpgp_dist_openpgp_min_mjs.shogun-core.js +86 -0
- package/dist/browser/defaultVendors-node_modules_openpgp_dist_openpgp_min_mjs.shogun-core.js.map +1 -0
- package/dist/browser/node_modules_hpke_ml-kem_esm_mod_js.shogun-core.js +539 -0
- package/dist/browser/node_modules_hpke_ml-kem_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/shogun-core.js +160386 -0
- package/dist/browser/shogun-core.js.map +1 -0
- package/dist/config/simplified-config.js +236 -0
- package/dist/core.js +329 -0
- package/dist/crypto/asymmetric.js +99 -0
- package/dist/crypto/double-ratchet.js +370 -0
- package/dist/crypto/file-encryption.js +213 -0
- package/dist/crypto/hashing.js +87 -0
- package/dist/crypto/index.js +34 -0
- package/dist/crypto/mls-codec.js +202 -0
- package/dist/crypto/mls.js +550 -0
- package/dist/crypto/pgp.js +390 -0
- package/dist/crypto/random-generation.js +341 -0
- package/dist/crypto/sframe.js +350 -0
- package/dist/crypto/signal-protocol.js +376 -0
- package/dist/crypto/symmetric.js +91 -0
- package/dist/crypto/types.js +2 -0
- package/dist/crypto/utils.js +140 -0
- package/dist/examples/auth-test.js +253 -0
- package/dist/examples/crypto-identity-example.js +151 -0
- package/dist/examples/crypto-working-test.js +83 -0
- package/dist/examples/double-ratchet-test.js +155 -0
- package/dist/examples/mls-advanced-example.js +294 -0
- package/dist/examples/mls-sframe-test.js +304 -0
- package/dist/examples/pgp-example.js +200 -0
- package/dist/examples/quick-auth-test.js +61 -0
- package/dist/examples/random-generation-test.js +151 -0
- package/dist/examples/signal-protocol-test.js +38 -0
- package/dist/examples/simple-api-test.js +114 -0
- package/dist/examples/simple-crypto-identity-example.js +84 -0
- package/dist/examples/timeout-test.js +227 -0
- package/dist/examples/zkproof-credentials-example.js +212 -0
- package/dist/examples/zkproof-example.js +201 -0
- package/dist/gundb/api.js +435 -0
- package/dist/gundb/crypto.js +283 -0
- package/dist/gundb/db.js +1946 -0
- package/dist/gundb/derive.js +232 -0
- package/dist/gundb/errors.js +76 -0
- package/dist/gundb/index.js +22 -0
- package/dist/gundb/rxjs.js +447 -0
- package/dist/gundb/types.js +5 -0
- package/dist/index.js +58 -0
- package/dist/interfaces/common.js +2 -0
- package/dist/interfaces/events.js +40 -0
- package/dist/interfaces/plugin.js +2 -0
- package/dist/interfaces/shogun.js +37 -0
- package/dist/managers/AuthManager.js +226 -0
- package/dist/managers/CoreInitializer.js +228 -0
- package/dist/managers/CryptoIdentityManager.js +366 -0
- package/dist/managers/EventManager.js +70 -0
- package/dist/managers/PluginManager.js +299 -0
- package/dist/plugins/base.js +50 -0
- package/dist/plugins/index.js +32 -0
- package/dist/plugins/nostr/index.js +20 -0
- package/dist/plugins/nostr/nostrConnector.js +419 -0
- package/dist/plugins/nostr/nostrConnectorPlugin.js +453 -0
- package/dist/plugins/nostr/nostrSigner.js +319 -0
- package/dist/plugins/nostr/types.js +2 -0
- package/dist/plugins/smartwallet/index.js +18 -0
- package/dist/plugins/smartwallet/smartWalletPlugin.js +511 -0
- package/dist/plugins/smartwallet/types.js +2 -0
- package/dist/plugins/web3/index.js +20 -0
- package/dist/plugins/web3/types.js +2 -0
- package/dist/plugins/web3/web3Connector.js +533 -0
- package/dist/plugins/web3/web3ConnectorPlugin.js +455 -0
- package/dist/plugins/web3/web3Signer.js +314 -0
- package/dist/plugins/webauthn/index.js +19 -0
- package/dist/plugins/webauthn/types.js +14 -0
- package/dist/plugins/webauthn/webauthn.js +496 -0
- package/dist/plugins/webauthn/webauthnPlugin.js +489 -0
- package/dist/plugins/webauthn/webauthnSigner.js +310 -0
- package/dist/plugins/zkproof/index.js +53 -0
- package/dist/plugins/zkproof/types.js +2 -0
- package/dist/plugins/zkproof/zkCredentials.js +213 -0
- package/dist/plugins/zkproof/zkProofConnector.js +198 -0
- package/dist/plugins/zkproof/zkProofPlugin.js +272 -0
- package/dist/storage/storage.js +145 -0
- package/dist/types/config/simplified-config.d.ts +114 -0
- package/dist/types/core.d.ts +305 -0
- package/dist/types/crypto/asymmetric.d.ts +6 -0
- package/dist/types/crypto/double-ratchet.d.ts +22 -0
- package/dist/types/crypto/file-encryption.d.ts +19 -0
- package/dist/types/crypto/hashing.d.ts +9 -0
- package/dist/types/crypto/index.d.ts +13 -0
- package/dist/types/crypto/mls-codec.d.ts +39 -0
- package/dist/types/crypto/mls.d.ts +130 -0
- package/dist/types/crypto/pgp.d.ts +95 -0
- package/dist/types/crypto/random-generation.d.ts +35 -0
- package/dist/types/crypto/sframe.d.ts +102 -0
- package/dist/types/crypto/signal-protocol.d.ts +26 -0
- package/dist/types/crypto/symmetric.d.ts +9 -0
- package/dist/types/crypto/types.d.ts +144 -0
- package/dist/types/crypto/utils.d.ts +22 -0
- package/dist/types/examples/auth-test.d.ts +8 -0
- package/dist/types/examples/crypto-identity-example.d.ts +5 -0
- package/dist/types/examples/crypto-working-test.d.ts +1 -0
- package/dist/types/examples/double-ratchet-test.d.ts +1 -0
- package/dist/types/examples/mls-advanced-example.d.ts +53 -0
- package/dist/types/examples/mls-sframe-test.d.ts +1 -0
- package/dist/types/examples/pgp-example.d.ts +75 -0
- package/dist/types/examples/quick-auth-test.d.ts +8 -0
- package/dist/types/examples/random-generation-test.d.ts +1 -0
- package/dist/types/examples/signal-protocol-test.d.ts +1 -0
- package/dist/types/examples/simple-api-test.d.ts +10 -0
- package/dist/types/examples/simple-crypto-identity-example.d.ts +6 -0
- package/dist/types/examples/timeout-test.d.ts +8 -0
- package/dist/types/examples/zkproof-credentials-example.d.ts +12 -0
- package/dist/types/examples/zkproof-example.d.ts +11 -0
- package/dist/types/gundb/api.d.ts +185 -0
- package/dist/types/gundb/crypto.d.ts +95 -0
- package/dist/types/gundb/db.d.ts +397 -0
- package/dist/types/gundb/derive.d.ts +21 -0
- package/dist/types/gundb/errors.d.ts +42 -0
- package/dist/types/gundb/index.d.ts +3 -0
- package/dist/types/gundb/rxjs.d.ts +110 -0
- package/dist/types/gundb/types.d.ts +255 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/interfaces/common.d.ts +85 -0
- package/dist/types/interfaces/events.d.ts +131 -0
- package/dist/types/interfaces/plugin.d.ts +162 -0
- package/dist/types/interfaces/shogun.d.ts +208 -0
- package/dist/types/managers/AuthManager.d.ts +72 -0
- package/dist/types/managers/CoreInitializer.d.ts +40 -0
- package/dist/types/managers/CryptoIdentityManager.d.ts +102 -0
- package/dist/types/managers/EventManager.d.ts +49 -0
- package/dist/types/managers/PluginManager.d.ts +145 -0
- package/dist/types/plugins/base.d.ts +35 -0
- package/dist/types/plugins/index.d.ts +18 -0
- package/dist/types/plugins/nostr/index.d.ts +4 -0
- package/dist/types/plugins/nostr/nostrConnector.d.ts +119 -0
- package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +163 -0
- package/dist/types/plugins/nostr/nostrSigner.d.ts +105 -0
- package/dist/types/plugins/nostr/types.d.ts +122 -0
- package/dist/types/plugins/smartwallet/index.d.ts +2 -0
- package/dist/types/plugins/smartwallet/smartWalletPlugin.d.ts +67 -0
- package/dist/types/plugins/smartwallet/types.d.ts +80 -0
- package/dist/types/plugins/web3/index.d.ts +4 -0
- package/dist/types/plugins/web3/types.d.ts +107 -0
- package/dist/types/plugins/web3/web3Connector.d.ts +129 -0
- package/dist/types/plugins/web3/web3ConnectorPlugin.d.ts +160 -0
- package/dist/types/plugins/web3/web3Signer.d.ts +114 -0
- package/dist/types/plugins/webauthn/index.d.ts +3 -0
- package/dist/types/plugins/webauthn/types.d.ts +183 -0
- package/dist/types/plugins/webauthn/webauthn.d.ts +129 -0
- package/dist/types/plugins/webauthn/webauthnPlugin.d.ts +179 -0
- package/dist/types/plugins/webauthn/webauthnSigner.d.ts +91 -0
- package/dist/types/plugins/zkproof/index.d.ts +48 -0
- package/dist/types/plugins/zkproof/types.d.ts +123 -0
- package/dist/types/plugins/zkproof/zkCredentials.d.ts +112 -0
- package/dist/types/plugins/zkproof/zkProofConnector.d.ts +46 -0
- package/dist/types/plugins/zkproof/zkProofPlugin.d.ts +76 -0
- package/dist/types/storage/storage.d.ts +51 -0
- package/dist/types/utils/errorHandler.d.ts +119 -0
- package/dist/types/utils/eventEmitter.d.ts +39 -0
- package/dist/types/utils/seedPhrase.d.ts +50 -0
- package/dist/types/utils/validation.d.ts +27 -0
- package/dist/utils/errorHandler.js +246 -0
- package/dist/utils/eventEmitter.js +79 -0
- package/dist/utils/seedPhrase.js +97 -0
- package/dist/utils/validation.js +81 -0
- package/package.json +10 -57
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WebAuthnSigner = void 0;
|
|
7
|
+
const webauthn_1 = require("./webauthn");
|
|
8
|
+
const p256_1 = require("@noble/curves/p256");
|
|
9
|
+
const sha256_1 = require("@noble/hashes/sha256");
|
|
10
|
+
const derive_1 = __importDefault(require("../../gundb/derive"));
|
|
11
|
+
const ethers_1 = require("ethers");
|
|
12
|
+
/**
|
|
13
|
+
* Base64URL encoding utilities
|
|
14
|
+
*/
|
|
15
|
+
const base64url = {
|
|
16
|
+
encode: function (buffer) {
|
|
17
|
+
const bytes = new Uint8Array(buffer);
|
|
18
|
+
return btoa(String.fromCharCode(...bytes))
|
|
19
|
+
.replace(/\+/g, "-")
|
|
20
|
+
.replace(/\//g, "_")
|
|
21
|
+
.replace(/=/g, "");
|
|
22
|
+
},
|
|
23
|
+
decode: function (str) {
|
|
24
|
+
str = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
25
|
+
while (str.length % 4)
|
|
26
|
+
str += "=";
|
|
27
|
+
const binary = atob(str);
|
|
28
|
+
return new Uint8Array(binary.split("").map((c) => c.charCodeAt(0)));
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* WebAuthn Signer - Provides oneshot signing functionality
|
|
33
|
+
* Similar to webauthn.js but integrated with our architecture
|
|
34
|
+
* CONSISTENT with normal WebAuthn approach
|
|
35
|
+
*/
|
|
36
|
+
class WebAuthnSigner {
|
|
37
|
+
constructor(webauthn) {
|
|
38
|
+
this.credentials = new Map();
|
|
39
|
+
this.webauthn = webauthn || new webauthn_1.Webauthn();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new WebAuthn credential for signing
|
|
43
|
+
* Similar to webauthn.js create functionality but CONSISTENT with normal approach
|
|
44
|
+
*/
|
|
45
|
+
async createSigningCredential(username) {
|
|
46
|
+
try {
|
|
47
|
+
const credential = (await navigator.credentials.create({
|
|
48
|
+
publicKey: {
|
|
49
|
+
challenge: crypto.getRandomValues(new Uint8Array(32)),
|
|
50
|
+
rp: {
|
|
51
|
+
id: window.location.hostname === "localhost"
|
|
52
|
+
? "localhost"
|
|
53
|
+
: window.location.hostname,
|
|
54
|
+
name: "Shogun Wallet",
|
|
55
|
+
},
|
|
56
|
+
user: {
|
|
57
|
+
id: new TextEncoder().encode(username),
|
|
58
|
+
name: username,
|
|
59
|
+
displayName: username,
|
|
60
|
+
},
|
|
61
|
+
// Use the same algorithms as webauthn.js for SEA compatibility
|
|
62
|
+
pubKeyCredParams: [
|
|
63
|
+
{ type: "public-key", alg: -7 }, // ECDSA, P-256 curve, for signing
|
|
64
|
+
{ type: "public-key", alg: -25 }, // ECDH, P-256 curve, for creating shared secrets
|
|
65
|
+
{ type: "public-key", alg: -257 },
|
|
66
|
+
],
|
|
67
|
+
authenticatorSelection: {
|
|
68
|
+
userVerification: "preferred",
|
|
69
|
+
},
|
|
70
|
+
timeout: 60000,
|
|
71
|
+
attestation: "none",
|
|
72
|
+
},
|
|
73
|
+
}));
|
|
74
|
+
if (!credential) {
|
|
75
|
+
throw new Error("Failed to create WebAuthn credential");
|
|
76
|
+
}
|
|
77
|
+
// Extract public key in the same way as webauthn.js
|
|
78
|
+
const response = credential.response;
|
|
79
|
+
const publicKey = response.getPublicKey();
|
|
80
|
+
if (!publicKey) {
|
|
81
|
+
throw new Error("Failed to get public key from credential");
|
|
82
|
+
}
|
|
83
|
+
const rawKey = new Uint8Array(publicKey);
|
|
84
|
+
// Extract coordinates like webauthn.js (slice positions may need adjustment)
|
|
85
|
+
const xCoord = rawKey.slice(27, 59);
|
|
86
|
+
const yCoord = rawKey.slice(59, 91);
|
|
87
|
+
const x = base64url.encode(xCoord);
|
|
88
|
+
const y = base64url.encode(yCoord);
|
|
89
|
+
const pub = `${x}.${y}`;
|
|
90
|
+
// CONSISTENCY: Use the same hashing approach as normal WebAuthn
|
|
91
|
+
const hashedCredentialId = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(credential.id));
|
|
92
|
+
const signingCredential = {
|
|
93
|
+
id: credential.id,
|
|
94
|
+
rawId: credential.rawId,
|
|
95
|
+
publicKey: { x, y },
|
|
96
|
+
pub,
|
|
97
|
+
hashedCredentialId, // This ensures consistency
|
|
98
|
+
};
|
|
99
|
+
// Store credential for later use
|
|
100
|
+
this.credentials.set(credential.id, signingCredential);
|
|
101
|
+
return signingCredential;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error("Error creating signing credential:", error);
|
|
105
|
+
throw new Error(`Failed to create signing credential: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Creates an authenticator function compatible with SEA.sign
|
|
110
|
+
* This is the key function that makes it work like webauthn.js
|
|
111
|
+
*/
|
|
112
|
+
createAuthenticator(credentialId) {
|
|
113
|
+
const credential = this.credentials.get(credentialId);
|
|
114
|
+
if (!credential) {
|
|
115
|
+
throw new Error(`Credential ${credentialId} not found`);
|
|
116
|
+
}
|
|
117
|
+
return async (data) => {
|
|
118
|
+
try {
|
|
119
|
+
const challenge = new TextEncoder().encode(JSON.stringify(data));
|
|
120
|
+
const options = {
|
|
121
|
+
challenge,
|
|
122
|
+
rpId: window.location.hostname === "localhost"
|
|
123
|
+
? "localhost"
|
|
124
|
+
: window.location.hostname,
|
|
125
|
+
userVerification: "preferred",
|
|
126
|
+
allowCredentials: [
|
|
127
|
+
{
|
|
128
|
+
type: "public-key",
|
|
129
|
+
id: credential.rawId,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
timeout: 60000,
|
|
133
|
+
};
|
|
134
|
+
const assertion = (await navigator.credentials.get({
|
|
135
|
+
publicKey: options,
|
|
136
|
+
}));
|
|
137
|
+
if (!assertion) {
|
|
138
|
+
throw new Error("WebAuthn assertion failed");
|
|
139
|
+
}
|
|
140
|
+
return assertion.response;
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.error("WebAuthn assertion error:", error);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Creates a derived key pair from WebAuthn credential
|
|
150
|
+
* CONSISTENT with normal approach: uses hashedCredentialId as password
|
|
151
|
+
*/
|
|
152
|
+
async createDerivedKeyPair(credentialId, username, extra) {
|
|
153
|
+
const credential = this.credentials.get(credentialId);
|
|
154
|
+
if (!credential) {
|
|
155
|
+
throw new Error(`Credential ${credentialId} not found`);
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
// CONSISTENCY: Use the same approach as normal WebAuthn
|
|
159
|
+
// Use hashedCredentialId as password (same as normal approach)
|
|
160
|
+
const derivedKeys = await (0, derive_1.default)(credential.hashedCredentialId, // This is the key change!
|
|
161
|
+
extra, { includeP256: true });
|
|
162
|
+
return {
|
|
163
|
+
pub: derivedKeys.pub,
|
|
164
|
+
priv: derivedKeys.priv,
|
|
165
|
+
epub: derivedKeys.epub,
|
|
166
|
+
epriv: derivedKeys.epriv,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error("Error deriving keys from WebAuthn credential:", error);
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Creates a Gun user from WebAuthn credential
|
|
176
|
+
* This ensures the SAME user is created as with normal approach
|
|
177
|
+
* FIX: Use derived pair instead of username/password for GunDB auth
|
|
178
|
+
*/
|
|
179
|
+
async createGunUser(credentialId, username, gunInstance) {
|
|
180
|
+
const credential = this.credentials.get(credentialId);
|
|
181
|
+
if (!credential) {
|
|
182
|
+
throw new Error(`Credential ${credentialId} not found`);
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
// FIX: Use derived pair for GunDB authentication instead of username/password
|
|
186
|
+
const derivedPair = await this.createDerivedKeyPair(credentialId, username);
|
|
187
|
+
return new Promise((resolve) => {
|
|
188
|
+
// Use the derived pair directly for GunDB auth
|
|
189
|
+
gunInstance.user().create(derivedPair, (ack) => {
|
|
190
|
+
if (ack.err) {
|
|
191
|
+
// Try to login if user already exists
|
|
192
|
+
gunInstance.user().auth(derivedPair, (authAck) => {
|
|
193
|
+
if (authAck.err) {
|
|
194
|
+
resolve({ success: false, error: authAck.err });
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
const userPub = authAck.pub;
|
|
198
|
+
// Update credential with Gun user pub
|
|
199
|
+
credential.gunUserPub = userPub;
|
|
200
|
+
this.credentials.set(credentialId, credential);
|
|
201
|
+
resolve({ success: true, userPub });
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// User created, now login
|
|
207
|
+
gunInstance.user().auth(derivedPair, (authAck) => {
|
|
208
|
+
if (authAck.err) {
|
|
209
|
+
resolve({ success: false, error: authAck.err });
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
const userPub = authAck.pub;
|
|
213
|
+
// Update credential with Gun user pub
|
|
214
|
+
credential.gunUserPub = userPub;
|
|
215
|
+
this.credentials.set(credentialId, credential);
|
|
216
|
+
resolve({ success: true, userPub });
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error("Error creating Gun user:", error);
|
|
225
|
+
return { success: false, error: error.message };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Signs data using WebAuthn + derived keys
|
|
230
|
+
* This provides a hybrid approach: WebAuthn for user verification + derived keys for actual signing
|
|
231
|
+
* CONSISTENT with normal approach
|
|
232
|
+
*/
|
|
233
|
+
async signWithDerivedKeys(data, credentialId, username, extra) {
|
|
234
|
+
try {
|
|
235
|
+
// First, verify user with WebAuthn
|
|
236
|
+
const authenticator = this.createAuthenticator(credentialId);
|
|
237
|
+
await authenticator(data); // This verifies the user
|
|
238
|
+
// Then use derived keys for actual signing (CONSISTENT approach)
|
|
239
|
+
const keyPair = await this.createDerivedKeyPair(credentialId, username, extra);
|
|
240
|
+
// Create signature using P-256 (same as SEA)
|
|
241
|
+
const message = JSON.stringify(data);
|
|
242
|
+
const messageHash = (0, sha256_1.sha256)(new TextEncoder().encode(message));
|
|
243
|
+
// Convert base64url private key to bytes
|
|
244
|
+
const privKeyBytes = base64url.decode(keyPair.priv);
|
|
245
|
+
// Sign with P-256
|
|
246
|
+
const signature = p256_1.p256.sign(messageHash, privKeyBytes);
|
|
247
|
+
// Format like SEA signature
|
|
248
|
+
const seaSignature = {
|
|
249
|
+
m: message,
|
|
250
|
+
s: base64url.encode(signature.toCompactRawBytes()),
|
|
251
|
+
};
|
|
252
|
+
return "SEA" + JSON.stringify(seaSignature);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
console.error("Error signing with derived keys:", error);
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get the Gun user public key for a credential
|
|
261
|
+
* This allows checking if the same user would be created
|
|
262
|
+
*/
|
|
263
|
+
getGunUserPub(credentialId) {
|
|
264
|
+
const credential = this.credentials.get(credentialId);
|
|
265
|
+
return credential?.gunUserPub;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get the hashed credential ID (for consistency checking)
|
|
269
|
+
*/
|
|
270
|
+
getHashedCredentialId(credentialId) {
|
|
271
|
+
const credential = this.credentials.get(credentialId);
|
|
272
|
+
return credential?.hashedCredentialId;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Check if this credential would create the same Gun user as normal approach
|
|
276
|
+
*/
|
|
277
|
+
async verifyConsistency(credentialId, username, expectedUserPub) {
|
|
278
|
+
const credential = this.credentials.get(credentialId);
|
|
279
|
+
if (!credential) {
|
|
280
|
+
return { consistent: false };
|
|
281
|
+
}
|
|
282
|
+
// The derived keys should be the same as normal approach
|
|
283
|
+
const derivedKeys = await this.createDerivedKeyPair(credentialId, username);
|
|
284
|
+
return {
|
|
285
|
+
consistent: expectedUserPub ? derivedKeys.pub === expectedUserPub : true,
|
|
286
|
+
actualUserPub: derivedKeys.pub,
|
|
287
|
+
expectedUserPub,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get credential by ID
|
|
292
|
+
*/
|
|
293
|
+
getCredential(credentialId) {
|
|
294
|
+
return this.credentials.get(credentialId);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* List all stored credentials
|
|
298
|
+
*/
|
|
299
|
+
listCredentials() {
|
|
300
|
+
return Array.from(this.credentials.values());
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Remove a credential
|
|
304
|
+
*/
|
|
305
|
+
removeCredential(credentialId) {
|
|
306
|
+
return this.credentials.delete(credentialId);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
exports.WebAuthnSigner = WebAuthnSigner;
|
|
310
|
+
exports.default = WebAuthnSigner;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ZK-Proof Plugin for Shogun Core
|
|
4
|
+
*
|
|
5
|
+
* Provides Zero-Knowledge Proof authentication using Semaphore protocol
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Anonymous authentication without revealing identity
|
|
9
|
+
* - Multi-device support via trapdoor backup
|
|
10
|
+
* - Privacy-preserving group membership proofs
|
|
11
|
+
* - Compatible with Gun decentralized storage
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Initialize Shogun with ZK-Proof plugin
|
|
16
|
+
* const shogun = new ShogunCore({
|
|
17
|
+
* peers: ['https://gun-manhattan.herokuapp.com/gun'],
|
|
18
|
+
* zkproof: {
|
|
19
|
+
* enabled: true,
|
|
20
|
+
* defaultGroupId: 'my-app-users'
|
|
21
|
+
* }
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* await shogun.initialize();
|
|
25
|
+
*
|
|
26
|
+
* // Get the plugin
|
|
27
|
+
* const zkPlugin = shogun.getPlugin<ZkProofPlugin>('zkproof');
|
|
28
|
+
*
|
|
29
|
+
* // Sign up with ZK-Proof
|
|
30
|
+
* const signupResult = await zkPlugin.signUp();
|
|
31
|
+
* if (signupResult.success) {
|
|
32
|
+
* console.log('Trapdoor (save this!):', signupResult.seedPhrase);
|
|
33
|
+
* console.log('Public commitment:', signupResult.username);
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* // Login with trapdoor
|
|
37
|
+
* const loginResult = await zkPlugin.login(trapdoor);
|
|
38
|
+
* if (loginResult.success) {
|
|
39
|
+
* console.log('Logged in anonymously!');
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @module zkproof
|
|
44
|
+
*/
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.CredentialType = exports.ZkCredentials = exports.ZkProofConnector = exports.ZkProofPlugin = void 0;
|
|
47
|
+
var zkProofPlugin_1 = require("./zkProofPlugin");
|
|
48
|
+
Object.defineProperty(exports, "ZkProofPlugin", { enumerable: true, get: function () { return zkProofPlugin_1.ZkProofPlugin; } });
|
|
49
|
+
var zkProofConnector_1 = require("./zkProofConnector");
|
|
50
|
+
Object.defineProperty(exports, "ZkProofConnector", { enumerable: true, get: function () { return zkProofConnector_1.ZkProofConnector; } });
|
|
51
|
+
var zkCredentials_1 = require("./zkCredentials");
|
|
52
|
+
Object.defineProperty(exports, "ZkCredentials", { enumerable: true, get: function () { return zkCredentials_1.ZkCredentials; } });
|
|
53
|
+
Object.defineProperty(exports, "CredentialType", { enumerable: true, get: function () { return zkCredentials_1.CredentialType; } });
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ZkCredentials = exports.CredentialType = void 0;
|
|
4
|
+
const group_1 = require("@semaphore-protocol/group");
|
|
5
|
+
const proof_1 = require("@semaphore-protocol/proof");
|
|
6
|
+
const ethers_1 = require("ethers");
|
|
7
|
+
const errorHandler_1 = require("../../utils/errorHandler");
|
|
8
|
+
/**
|
|
9
|
+
* Types of verifiable credentials
|
|
10
|
+
*/
|
|
11
|
+
var CredentialType;
|
|
12
|
+
(function (CredentialType) {
|
|
13
|
+
CredentialType["AGE"] = "age";
|
|
14
|
+
CredentialType["CITIZENSHIP"] = "citizenship";
|
|
15
|
+
CredentialType["EDUCATION"] = "education";
|
|
16
|
+
CredentialType["INCOME"] = "income";
|
|
17
|
+
CredentialType["EMPLOYMENT"] = "employment";
|
|
18
|
+
CredentialType["HEALTH"] = "health";
|
|
19
|
+
CredentialType["CUSTOM"] = "custom";
|
|
20
|
+
})(CredentialType || (exports.CredentialType = CredentialType = {}));
|
|
21
|
+
/**
|
|
22
|
+
* ZK Credentials Manager
|
|
23
|
+
* Extends ZK-Proof functionality to support verifiable credentials
|
|
24
|
+
*/
|
|
25
|
+
class ZkCredentials {
|
|
26
|
+
constructor() {
|
|
27
|
+
this.groups = new Map();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a verifiable credential from private data
|
|
31
|
+
*/
|
|
32
|
+
createCredential(identity, credentialData) {
|
|
33
|
+
try {
|
|
34
|
+
// Hash the private data to create a credential commitment
|
|
35
|
+
const privateDataString = JSON.stringify(credentialData.privateData);
|
|
36
|
+
const credentialHash = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(privateDataString));
|
|
37
|
+
// For now, return a basic credential structure
|
|
38
|
+
// Full proof generation requires circuit files
|
|
39
|
+
const credential = {
|
|
40
|
+
type: credentialData.type,
|
|
41
|
+
claim: credentialData.claim,
|
|
42
|
+
proof: {
|
|
43
|
+
merkleTreeRoot: "",
|
|
44
|
+
nullifierHash: "",
|
|
45
|
+
signal: credentialHash,
|
|
46
|
+
externalNullifier: "",
|
|
47
|
+
proof: [],
|
|
48
|
+
},
|
|
49
|
+
credentialHash,
|
|
50
|
+
timestamp: Date.now(),
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
credential,
|
|
54
|
+
credentialHash,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
errorHandler_1.ErrorHandler.handle(errorHandler_1.ErrorType.ENCRYPTION, "CREDENTIAL_CREATION_FAILED", `Failed to create verifiable credential: ${error.message}`, error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Prove an attribute about yourself without revealing the underlying data
|
|
64
|
+
*/
|
|
65
|
+
async proveAttribute(identity, credentialData, groupId = "verified-credentials") {
|
|
66
|
+
try {
|
|
67
|
+
const { credential, credentialHash } = this.createCredential(identity, credentialData);
|
|
68
|
+
// Convert claim to signal
|
|
69
|
+
const signal = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(credentialData.claim));
|
|
70
|
+
const signalBigInt = BigInt(signal);
|
|
71
|
+
// Create or get group
|
|
72
|
+
const group = this.getOrCreateGroup(groupId);
|
|
73
|
+
// Add identity if not already in group
|
|
74
|
+
if (group.indexOf(identity.commitment) === -1) {
|
|
75
|
+
group.addMember(identity.commitment);
|
|
76
|
+
}
|
|
77
|
+
// External nullifier from credential type
|
|
78
|
+
const externalNullifier = BigInt(ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(credentialData.type)));
|
|
79
|
+
// Generate ZK proof
|
|
80
|
+
// Note: This requires circuit files to be available
|
|
81
|
+
const fullProof = await (0, proof_1.generateProof)(identity, group, signalBigInt, externalNullifier);
|
|
82
|
+
return {
|
|
83
|
+
type: credentialData.type,
|
|
84
|
+
claim: credentialData.claim,
|
|
85
|
+
proof: {
|
|
86
|
+
merkleTreeRoot: fullProof.merkleTreeRoot.toString(),
|
|
87
|
+
nullifierHash: fullProof.nullifierHash.toString(),
|
|
88
|
+
signal: fullProof.signal.toString(),
|
|
89
|
+
externalNullifier: fullProof.externalNullifier.toString(),
|
|
90
|
+
proof: fullProof.proof.map((p) => p.toString()),
|
|
91
|
+
},
|
|
92
|
+
credentialHash,
|
|
93
|
+
timestamp: Date.now(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
errorHandler_1.ErrorHandler.handle(errorHandler_1.ErrorType.ENCRYPTION, "ATTRIBUTE_PROOF_FAILED", `Failed to prove attribute: ${error.message}`, error);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Verify a credential proof
|
|
103
|
+
*/
|
|
104
|
+
async verifyCredential(proof, treeDepth = 20) {
|
|
105
|
+
try {
|
|
106
|
+
const verified = await (0, proof_1.verifyProof)(proof.proof, treeDepth);
|
|
107
|
+
return {
|
|
108
|
+
verified,
|
|
109
|
+
type: proof.type,
|
|
110
|
+
claim: proof.claim,
|
|
111
|
+
timestamp: proof.timestamp,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
errorHandler_1.ErrorHandler.handle(errorHandler_1.ErrorType.ENCRYPTION, "CREDENTIAL_VERIFICATION_FAILED", `Failed to verify credential: ${error.message}`, error);
|
|
116
|
+
return {
|
|
117
|
+
verified: false,
|
|
118
|
+
error: error.message,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a group for credential holders
|
|
124
|
+
*/
|
|
125
|
+
getOrCreateGroup(groupId) {
|
|
126
|
+
if (!this.groups.has(groupId)) {
|
|
127
|
+
const groupIdHash = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(groupId));
|
|
128
|
+
const groupIdNumber = BigInt(groupIdHash);
|
|
129
|
+
this.groups.set(groupId, new group_1.Group(groupIdNumber));
|
|
130
|
+
}
|
|
131
|
+
return this.groups.get(groupId);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Add an identity to a credentials group
|
|
135
|
+
*/
|
|
136
|
+
addToCredentialGroup(identity, groupId = "verified-credentials") {
|
|
137
|
+
const group = this.getOrCreateGroup(groupId);
|
|
138
|
+
if (group.indexOf(identity.commitment) === -1) {
|
|
139
|
+
group.addMember(identity.commitment);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Common credential proofs
|
|
144
|
+
*/
|
|
145
|
+
/**
|
|
146
|
+
* Prove age without revealing exact birthdate
|
|
147
|
+
*/
|
|
148
|
+
async proveAge(identity, birthDate, minimumAge) {
|
|
149
|
+
const age = Math.floor((Date.now() - birthDate.getTime()) / (365.25 * 24 * 60 * 60 * 1000));
|
|
150
|
+
if (age < minimumAge) {
|
|
151
|
+
throw new Error(`Age ${age} is less than required ${minimumAge}`);
|
|
152
|
+
}
|
|
153
|
+
return this.proveAttribute(identity, {
|
|
154
|
+
type: CredentialType.AGE,
|
|
155
|
+
claim: `Age is ${minimumAge} or older`,
|
|
156
|
+
privateData: {
|
|
157
|
+
birthDate: birthDate.toISOString(),
|
|
158
|
+
actualAge: age,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Prove citizenship without revealing country
|
|
164
|
+
*/
|
|
165
|
+
async proveCitizenship(identity, country, region = "EU") {
|
|
166
|
+
return this.proveAttribute(identity, {
|
|
167
|
+
type: CredentialType.CITIZENSHIP,
|
|
168
|
+
claim: `Citizen of ${region}`,
|
|
169
|
+
privateData: {
|
|
170
|
+
country,
|
|
171
|
+
passportNumber: "hidden",
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Prove education without revealing institution
|
|
177
|
+
*/
|
|
178
|
+
async proveEducation(identity, degree, university, year) {
|
|
179
|
+
return this.proveAttribute(identity, {
|
|
180
|
+
type: CredentialType.EDUCATION,
|
|
181
|
+
claim: `Has ${degree} degree`,
|
|
182
|
+
privateData: {
|
|
183
|
+
university,
|
|
184
|
+
degree,
|
|
185
|
+
year,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Prove income range without revealing exact amount
|
|
191
|
+
*/
|
|
192
|
+
async proveIncome(identity, amount, minimumRequired, currency = "USD") {
|
|
193
|
+
if (amount < minimumRequired) {
|
|
194
|
+
throw new Error(`Income ${amount} is less than required ${minimumRequired}`);
|
|
195
|
+
}
|
|
196
|
+
return this.proveAttribute(identity, {
|
|
197
|
+
type: CredentialType.INCOME,
|
|
198
|
+
claim: `Income ≥ ${minimumRequired} ${currency}`,
|
|
199
|
+
privateData: {
|
|
200
|
+
actualIncome: amount,
|
|
201
|
+
currency,
|
|
202
|
+
verified: true,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Cleanup resources
|
|
208
|
+
*/
|
|
209
|
+
cleanup() {
|
|
210
|
+
this.groups.clear();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.ZkCredentials = ZkCredentials;
|