@bananalink-sdk/protocol 1.2.7
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 +604 -0
- package/dist/chunk-32OWUOZ3.js +308 -0
- package/dist/chunk-32OWUOZ3.js.map +1 -0
- package/dist/chunk-65HNHRJK.cjs +123 -0
- package/dist/chunk-65HNHRJK.cjs.map +1 -0
- package/dist/chunk-7KYDLL3B.js +480 -0
- package/dist/chunk-7KYDLL3B.js.map +1 -0
- package/dist/chunk-A6FLEJ7R.cjs +62 -0
- package/dist/chunk-A6FLEJ7R.cjs.map +1 -0
- package/dist/chunk-CUJK7ZTS.js +217 -0
- package/dist/chunk-CUJK7ZTS.js.map +1 -0
- package/dist/chunk-GI3BUPIH.cjs +236 -0
- package/dist/chunk-GI3BUPIH.cjs.map +1 -0
- package/dist/chunk-JXHV66Q4.js +106 -0
- package/dist/chunk-JXHV66Q4.js.map +1 -0
- package/dist/chunk-KNGZKGRS.cjs +552 -0
- package/dist/chunk-KNGZKGRS.cjs.map +1 -0
- package/dist/chunk-LELPCIE7.js +840 -0
- package/dist/chunk-LELPCIE7.js.map +1 -0
- package/dist/chunk-MCZG7QEM.cjs +310 -0
- package/dist/chunk-MCZG7QEM.cjs.map +1 -0
- package/dist/chunk-TCVKC227.js +56 -0
- package/dist/chunk-TCVKC227.js.map +1 -0
- package/dist/chunk-VXLUSU5B.cjs +856 -0
- package/dist/chunk-VXLUSU5B.cjs.map +1 -0
- package/dist/chunk-WCQVDF3K.js +12 -0
- package/dist/chunk-WCQVDF3K.js.map +1 -0
- package/dist/chunk-WGEGR3DF.cjs +15 -0
- package/dist/chunk-WGEGR3DF.cjs.map +1 -0
- package/dist/client-session-claim-3QF3noOr.d.ts +197 -0
- package/dist/client-session-claim-C4lUik3b.d.cts +197 -0
- package/dist/core-DMhuNfoz.d.cts +62 -0
- package/dist/core-DMhuNfoz.d.ts +62 -0
- package/dist/crypto/providers/noble-provider.cjs +14 -0
- package/dist/crypto/providers/noble-provider.cjs.map +1 -0
- package/dist/crypto/providers/noble-provider.d.cts +30 -0
- package/dist/crypto/providers/noble-provider.d.ts +30 -0
- package/dist/crypto/providers/noble-provider.js +5 -0
- package/dist/crypto/providers/noble-provider.js.map +1 -0
- package/dist/crypto/providers/node-provider.cjs +308 -0
- package/dist/crypto/providers/node-provider.cjs.map +1 -0
- package/dist/crypto/providers/node-provider.d.cts +32 -0
- package/dist/crypto/providers/node-provider.d.ts +32 -0
- package/dist/crypto/providers/node-provider.js +306 -0
- package/dist/crypto/providers/node-provider.js.map +1 -0
- package/dist/crypto/providers/quickcrypto-provider.cjs +339 -0
- package/dist/crypto/providers/quickcrypto-provider.cjs.map +1 -0
- package/dist/crypto/providers/quickcrypto-provider.d.cts +34 -0
- package/dist/crypto/providers/quickcrypto-provider.d.ts +34 -0
- package/dist/crypto/providers/quickcrypto-provider.js +337 -0
- package/dist/crypto/providers/quickcrypto-provider.js.map +1 -0
- package/dist/crypto/providers/webcrypto-provider.cjs +310 -0
- package/dist/crypto/providers/webcrypto-provider.cjs.map +1 -0
- package/dist/crypto/providers/webcrypto-provider.d.cts +30 -0
- package/dist/crypto/providers/webcrypto-provider.d.ts +30 -0
- package/dist/crypto/providers/webcrypto-provider.js +308 -0
- package/dist/crypto/providers/webcrypto-provider.js.map +1 -0
- package/dist/crypto-BUS06Qz-.d.cts +40 -0
- package/dist/crypto-BUS06Qz-.d.ts +40 -0
- package/dist/crypto-export.cjs +790 -0
- package/dist/crypto-export.cjs.map +1 -0
- package/dist/crypto-export.d.cts +257 -0
- package/dist/crypto-export.d.ts +257 -0
- package/dist/crypto-export.js +709 -0
- package/dist/crypto-export.js.map +1 -0
- package/dist/crypto-provider-deYoVIxi.d.cts +36 -0
- package/dist/crypto-provider-deYoVIxi.d.ts +36 -0
- package/dist/index.cjs +615 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +379 -0
- package/dist/index.d.ts +379 -0
- package/dist/index.js +504 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas-export.cjs +294 -0
- package/dist/schemas-export.cjs.map +1 -0
- package/dist/schemas-export.d.cts +1598 -0
- package/dist/schemas-export.d.ts +1598 -0
- package/dist/schemas-export.js +5 -0
- package/dist/schemas-export.js.map +1 -0
- package/dist/siwe-export.cjs +237 -0
- package/dist/siwe-export.cjs.map +1 -0
- package/dist/siwe-export.d.cts +27 -0
- package/dist/siwe-export.d.ts +27 -0
- package/dist/siwe-export.js +228 -0
- package/dist/siwe-export.js.map +1 -0
- package/dist/testing.cjs +54 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +20 -0
- package/dist/testing.d.ts +20 -0
- package/dist/testing.js +51 -0
- package/dist/testing.js.map +1 -0
- package/dist/validation-export.cjs +359 -0
- package/dist/validation-export.cjs.map +1 -0
- package/dist/validation-export.d.cts +3 -0
- package/dist/validation-export.d.ts +3 -0
- package/dist/validation-export.js +6 -0
- package/dist/validation-export.js.map +1 -0
- package/dist/validators-export.cjs +73 -0
- package/dist/validators-export.cjs.map +1 -0
- package/dist/validators-export.d.cts +37 -0
- package/dist/validators-export.d.ts +37 -0
- package/dist/validators-export.js +4 -0
- package/dist/validators-export.js.map +1 -0
- package/package.json +140 -0
- package/src/constants/index.ts +205 -0
- package/src/crypto/context.ts +228 -0
- package/src/crypto/diagnostics.ts +772 -0
- package/src/crypto/errors.ts +114 -0
- package/src/crypto/index.ts +89 -0
- package/src/crypto/payload-handler.ts +102 -0
- package/src/crypto/providers/compliance-provider.ts +579 -0
- package/src/crypto/providers/factory.ts +204 -0
- package/src/crypto/providers/index.ts +44 -0
- package/src/crypto/providers/noble-provider.ts +392 -0
- package/src/crypto/providers/node-provider.ts +433 -0
- package/src/crypto/providers/quickcrypto-provider.ts +483 -0
- package/src/crypto/providers/registry.ts +129 -0
- package/src/crypto/providers/webcrypto-provider.ts +364 -0
- package/src/crypto/session-security.ts +185 -0
- package/src/crypto/types.ts +93 -0
- package/src/crypto/utils.ts +190 -0
- package/src/crypto-export.ts +21 -0
- package/src/index.ts +38 -0
- package/src/schemas/auth.ts +60 -0
- package/src/schemas/client-messages.ts +57 -0
- package/src/schemas/core.ts +144 -0
- package/src/schemas/crypto.ts +65 -0
- package/src/schemas/discovery.ts +79 -0
- package/src/schemas/index.ts +239 -0
- package/src/schemas/relay-messages.ts +45 -0
- package/src/schemas/wallet-messages.ts +177 -0
- package/src/schemas-export.ts +23 -0
- package/src/siwe-export.ts +27 -0
- package/src/testing.ts +71 -0
- package/src/types/auth.ts +60 -0
- package/src/types/client-messages.ts +84 -0
- package/src/types/core.ts +131 -0
- package/src/types/crypto-provider.ts +264 -0
- package/src/types/crypto.ts +90 -0
- package/src/types/discovery.ts +50 -0
- package/src/types/errors.ts +87 -0
- package/src/types/index.ts +197 -0
- package/src/types/post-auth-operations.ts +363 -0
- package/src/types/providers.ts +72 -0
- package/src/types/relay-messages.ts +60 -0
- package/src/types/request-lifecycle.ts +161 -0
- package/src/types/signing-operations.ts +99 -0
- package/src/types/wallet-messages.ts +251 -0
- package/src/utils/client-session-claim.ts +188 -0
- package/src/utils/index.ts +54 -0
- package/src/utils/public-keys.ts +49 -0
- package/src/utils/siwe.ts +362 -0
- package/src/utils/url-decoding.ts +126 -0
- package/src/utils/url-encoding.ts +144 -0
- package/src/utils/wallet-session-claim.ts +188 -0
- package/src/validation-export.ts +32 -0
- package/src/validators/index.ts +222 -0
- package/src/validators-export.ts +8 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkA6FLEJ7R_cjs = require('./chunk-A6FLEJ7R.cjs');
|
|
4
|
+
var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
|
|
5
|
+
|
|
6
|
+
// src/crypto/errors.ts
|
|
7
|
+
var _CryptoError = class _CryptoError extends Error {
|
|
8
|
+
constructor(message, code, context) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.context = context;
|
|
12
|
+
this.name = "CryptoError";
|
|
13
|
+
if (Error.captureStackTrace) {
|
|
14
|
+
Error.captureStackTrace(this, this.constructor);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
chunkWGEGR3DF_cjs.__name(_CryptoError, "CryptoError");
|
|
19
|
+
var CryptoError = _CryptoError;
|
|
20
|
+
var _CryptoProviderUnavailableError = class _CryptoProviderUnavailableError extends CryptoError {
|
|
21
|
+
constructor(message, context) {
|
|
22
|
+
super(message, "PROVIDER_UNAVAILABLE", context);
|
|
23
|
+
this.name = "CryptoProviderUnavailableError";
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Format a developer-friendly error message with context
|
|
27
|
+
* Includes available alternatives and actionable recommendations
|
|
28
|
+
*/
|
|
29
|
+
toDevMessage() {
|
|
30
|
+
if (!this.context) {
|
|
31
|
+
return this.message;
|
|
32
|
+
}
|
|
33
|
+
const ctx = this.context;
|
|
34
|
+
const lines = [
|
|
35
|
+
this.message,
|
|
36
|
+
"",
|
|
37
|
+
"Available providers:",
|
|
38
|
+
...ctx.availableProviders.map((p) => ` - ${p}`)
|
|
39
|
+
];
|
|
40
|
+
if (ctx.recommendations.length > 0) {
|
|
41
|
+
lines.push("", "Recommendations:");
|
|
42
|
+
lines.push(...ctx.recommendations.map((r) => ` - ${r}`));
|
|
43
|
+
}
|
|
44
|
+
if (ctx.platform) {
|
|
45
|
+
const platformType = ctx.platform.isNode ? "Node.js" : ctx.platform.isBrowser ? "Browser" : ctx.platform.isReactNative ? "React Native" : "Unknown";
|
|
46
|
+
lines.push("", `Platform: ${platformType}`);
|
|
47
|
+
if (ctx.platform.platform) {
|
|
48
|
+
lines.push(`OS: ${ctx.platform.platform}`);
|
|
49
|
+
}
|
|
50
|
+
if (ctx.platform.userAgent) {
|
|
51
|
+
const ua = ctx.platform.userAgent;
|
|
52
|
+
const truncated = ua.length > 100 ? `${ua.substring(0, 100)}...` : ua;
|
|
53
|
+
lines.push(`User Agent: ${truncated}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return lines.join("\n");
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
chunkWGEGR3DF_cjs.__name(_CryptoProviderUnavailableError, "CryptoProviderUnavailableError");
|
|
60
|
+
var CryptoProviderUnavailableError = _CryptoProviderUnavailableError;
|
|
61
|
+
var _CryptoCapabilityMissingError = class _CryptoCapabilityMissingError extends CryptoError {
|
|
62
|
+
constructor(operation, provider, reason) {
|
|
63
|
+
super(
|
|
64
|
+
`Crypto operation '${operation}' is not available in provider '${provider}': ${reason}`,
|
|
65
|
+
"CAPABILITY_MISSING",
|
|
66
|
+
{ operation, provider, reason }
|
|
67
|
+
);
|
|
68
|
+
this.name = "CryptoCapabilityMissingError";
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
chunkWGEGR3DF_cjs.__name(_CryptoCapabilityMissingError, "CryptoCapabilityMissingError");
|
|
72
|
+
var CryptoCapabilityMissingError = _CryptoCapabilityMissingError;
|
|
73
|
+
|
|
74
|
+
// src/crypto/providers/compliance-provider.ts
|
|
75
|
+
var _DefaultComplianceAuditor = class _DefaultComplianceAuditor {
|
|
76
|
+
constructor(logger) {
|
|
77
|
+
this.auditLog = [];
|
|
78
|
+
this.logger = logger?.child({ component: "ComplianceAuditor" });
|
|
79
|
+
}
|
|
80
|
+
logEvent(event) {
|
|
81
|
+
this.auditLog.push(event);
|
|
82
|
+
this.logger?.info("Compliance audit event", {
|
|
83
|
+
eventType: event.eventType,
|
|
84
|
+
success: event.success,
|
|
85
|
+
sessionId: event.sessionId,
|
|
86
|
+
timestamp: event.timestamp
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
getAuditLog() {
|
|
90
|
+
return [...this.auditLog];
|
|
91
|
+
}
|
|
92
|
+
clearAuditLog() {
|
|
93
|
+
this.auditLog = [];
|
|
94
|
+
this.logger?.debug("Compliance audit log cleared");
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
chunkWGEGR3DF_cjs.__name(_DefaultComplianceAuditor, "DefaultComplianceAuditor");
|
|
98
|
+
var DefaultComplianceAuditor = _DefaultComplianceAuditor;
|
|
99
|
+
var _ComplianceCryptoProvider = class _ComplianceCryptoProvider {
|
|
100
|
+
constructor(underlyingProvider, config = {}, logger) {
|
|
101
|
+
this.underlyingProvider = underlyingProvider;
|
|
102
|
+
this.config = config;
|
|
103
|
+
this.auditor = config.auditor || new DefaultComplianceAuditor(logger);
|
|
104
|
+
this.logger = logger?.child({
|
|
105
|
+
component: "ComplianceCryptoProvider",
|
|
106
|
+
underlyingProvider: underlyingProvider.name
|
|
107
|
+
});
|
|
108
|
+
this.name = `Compliance(${underlyingProvider.name})`;
|
|
109
|
+
this.isAvailable = underlyingProvider.isAvailable;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create compliance audit event
|
|
113
|
+
*/
|
|
114
|
+
createAuditEvent(eventType, success, metadata = {}, error) {
|
|
115
|
+
return {
|
|
116
|
+
eventType,
|
|
117
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
118
|
+
sessionId: this.config.sessionId,
|
|
119
|
+
success,
|
|
120
|
+
error,
|
|
121
|
+
metadata,
|
|
122
|
+
...metadata
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Validate key usage restrictions
|
|
127
|
+
*/
|
|
128
|
+
validateKeyUsage(operation, keyUsages, dataSize) {
|
|
129
|
+
const restrictions = this.config.keyRestrictions;
|
|
130
|
+
if (!restrictions) return;
|
|
131
|
+
if (restrictions.requireSessionId && !this.config.sessionId) {
|
|
132
|
+
throw new Error("Session ID required for compliance but not provided");
|
|
133
|
+
}
|
|
134
|
+
if (restrictions.maxDataSize && dataSize && dataSize > restrictions.maxDataSize) {
|
|
135
|
+
throw new Error(`Data size ${dataSize} exceeds maximum allowed ${restrictions.maxDataSize} bytes`);
|
|
136
|
+
}
|
|
137
|
+
if (keyUsages && restrictions.requiredKeyUsages) {
|
|
138
|
+
const hasRequiredUsage = restrictions.requiredKeyUsages.some((usage) => keyUsages.includes(usage));
|
|
139
|
+
if (!hasRequiredUsage) {
|
|
140
|
+
throw new Error(`Key must have one of required usages: ${restrictions.requiredKeyUsages.join(", ")}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (keyUsages && restrictions.forbiddenKeyUsages) {
|
|
144
|
+
const hasForbiddenUsage = restrictions.forbiddenKeyUsages.some((usage) => keyUsages.includes(usage));
|
|
145
|
+
if (hasForbiddenUsage) {
|
|
146
|
+
throw new Error(`Key has forbidden usage. Forbidden: ${restrictions.forbiddenKeyUsages.join(", ")}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (operation === "export" && restrictions.allowKeyExport === false) {
|
|
150
|
+
throw new Error("Key export is forbidden by compliance policy");
|
|
151
|
+
}
|
|
152
|
+
if (operation === "import" && restrictions.allowKeyImport === false) {
|
|
153
|
+
throw new Error("Key import is forbidden by compliance policy");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Generate ECDH P-256 key pair with compliance audit
|
|
158
|
+
*/
|
|
159
|
+
async generateKeyPair() {
|
|
160
|
+
const startTime = Date.now();
|
|
161
|
+
try {
|
|
162
|
+
this.logger?.debug("Generating key pair with compliance audit");
|
|
163
|
+
const keyPair = await this.underlyingProvider.generateKeyPair();
|
|
164
|
+
this.validateKeyUsage("generation", keyPair.privateKey.usages);
|
|
165
|
+
this.auditor.logEvent(this.createAuditEvent("key_generation", true, {
|
|
166
|
+
algorithm: keyPair.privateKey.algorithm,
|
|
167
|
+
keyUsage: keyPair.privateKey.usages,
|
|
168
|
+
duration: Date.now() - startTime
|
|
169
|
+
}));
|
|
170
|
+
return keyPair;
|
|
171
|
+
} catch (error) {
|
|
172
|
+
this.auditor.logEvent(this.createAuditEvent("key_generation", false, {
|
|
173
|
+
duration: Date.now() - startTime
|
|
174
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Export public key with compliance audit
|
|
180
|
+
*/
|
|
181
|
+
async exportPublicKey(publicKey) {
|
|
182
|
+
const startTime = Date.now();
|
|
183
|
+
try {
|
|
184
|
+
this.validateKeyUsage("export", publicKey.usages);
|
|
185
|
+
const keyData = await this.underlyingProvider.exportPublicKey(publicKey);
|
|
186
|
+
this.auditor.logEvent(this.createAuditEvent("key_export", true, {
|
|
187
|
+
keyType: "public",
|
|
188
|
+
algorithm: publicKey.algorithm,
|
|
189
|
+
keySize: keyData.byteLength,
|
|
190
|
+
duration: Date.now() - startTime
|
|
191
|
+
}));
|
|
192
|
+
return keyData;
|
|
193
|
+
} catch (error) {
|
|
194
|
+
this.auditor.logEvent(this.createAuditEvent("key_export", false, {
|
|
195
|
+
keyType: "public",
|
|
196
|
+
algorithm: publicKey.algorithm,
|
|
197
|
+
duration: Date.now() - startTime
|
|
198
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Export private key with compliance audit
|
|
204
|
+
*/
|
|
205
|
+
async exportPrivateKey(privateKey) {
|
|
206
|
+
const startTime = Date.now();
|
|
207
|
+
try {
|
|
208
|
+
this.validateKeyUsage("export", privateKey.usages);
|
|
209
|
+
if (this.config.enableStrictMode) {
|
|
210
|
+
this.logger?.warn("Private key export in strict compliance mode", {
|
|
211
|
+
sessionId: this.config.sessionId,
|
|
212
|
+
algorithm: privateKey.algorithm
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const keyData = await this.underlyingProvider.exportPrivateKey(privateKey);
|
|
216
|
+
this.auditor.logEvent(this.createAuditEvent("key_export", true, {
|
|
217
|
+
keyType: "private",
|
|
218
|
+
algorithm: privateKey.algorithm,
|
|
219
|
+
keySize: keyData.byteLength,
|
|
220
|
+
strictMode: this.config.enableStrictMode,
|
|
221
|
+
duration: Date.now() - startTime
|
|
222
|
+
}));
|
|
223
|
+
return keyData;
|
|
224
|
+
} catch (error) {
|
|
225
|
+
this.auditor.logEvent(this.createAuditEvent("key_export", false, {
|
|
226
|
+
keyType: "private",
|
|
227
|
+
algorithm: privateKey.algorithm,
|
|
228
|
+
strictMode: this.config.enableStrictMode,
|
|
229
|
+
duration: Date.now() - startTime
|
|
230
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Import public key with compliance audit
|
|
236
|
+
*/
|
|
237
|
+
async importPublicKey(keyData) {
|
|
238
|
+
const startTime = Date.now();
|
|
239
|
+
try {
|
|
240
|
+
this.validateKeyUsage("import");
|
|
241
|
+
const key = await this.underlyingProvider.importPublicKey(keyData);
|
|
242
|
+
this.auditor.logEvent(this.createAuditEvent("key_import", true, {
|
|
243
|
+
keyType: "public",
|
|
244
|
+
algorithm: key.algorithm,
|
|
245
|
+
keySize: keyData.byteLength,
|
|
246
|
+
keyUsage: key.usages,
|
|
247
|
+
duration: Date.now() - startTime
|
|
248
|
+
}));
|
|
249
|
+
return key;
|
|
250
|
+
} catch (error) {
|
|
251
|
+
this.auditor.logEvent(this.createAuditEvent("key_import", false, {
|
|
252
|
+
keyType: "public",
|
|
253
|
+
keySize: keyData.byteLength,
|
|
254
|
+
duration: Date.now() - startTime
|
|
255
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Import private key with compliance audit
|
|
261
|
+
*/
|
|
262
|
+
async importPrivateKey(keyData) {
|
|
263
|
+
const startTime = Date.now();
|
|
264
|
+
try {
|
|
265
|
+
this.validateKeyUsage("import");
|
|
266
|
+
const key = await this.underlyingProvider.importPrivateKey(keyData);
|
|
267
|
+
this.auditor.logEvent(this.createAuditEvent("key_import", true, {
|
|
268
|
+
keyType: "private",
|
|
269
|
+
algorithm: key.algorithm,
|
|
270
|
+
keySize: keyData.byteLength,
|
|
271
|
+
keyUsage: key.usages,
|
|
272
|
+
duration: Date.now() - startTime
|
|
273
|
+
}));
|
|
274
|
+
return key;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
this.auditor.logEvent(this.createAuditEvent("key_import", false, {
|
|
277
|
+
keyType: "private",
|
|
278
|
+
keySize: keyData.byteLength,
|
|
279
|
+
duration: Date.now() - startTime
|
|
280
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Derive shared secret with compliance audit
|
|
286
|
+
*/
|
|
287
|
+
async deriveSharedSecret(privateKey, publicKey) {
|
|
288
|
+
const startTime = Date.now();
|
|
289
|
+
try {
|
|
290
|
+
this.validateKeyUsage("derivation", privateKey.usages);
|
|
291
|
+
const sharedSecret = await this.underlyingProvider.deriveSharedSecret(privateKey, publicKey);
|
|
292
|
+
this.auditor.logEvent(this.createAuditEvent("key_derivation", true, {
|
|
293
|
+
operation: "ECDH",
|
|
294
|
+
algorithm: privateKey.algorithm,
|
|
295
|
+
duration: Date.now() - startTime
|
|
296
|
+
}));
|
|
297
|
+
return sharedSecret;
|
|
298
|
+
} catch (error) {
|
|
299
|
+
this.auditor.logEvent(this.createAuditEvent("key_derivation", false, {
|
|
300
|
+
operation: "ECDH",
|
|
301
|
+
algorithm: privateKey.algorithm,
|
|
302
|
+
duration: Date.now() - startTime
|
|
303
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Derive encryption key with compliance audit
|
|
309
|
+
*/
|
|
310
|
+
async deriveEncryptionKey(sharedSecret, salt, info) {
|
|
311
|
+
const startTime = Date.now();
|
|
312
|
+
try {
|
|
313
|
+
const encryptionKey = await this.underlyingProvider.deriveEncryptionKey(sharedSecret, salt, info);
|
|
314
|
+
this.auditor.logEvent(this.createAuditEvent("key_derivation", true, {
|
|
315
|
+
operation: "HKDF",
|
|
316
|
+
algorithm: "HKDF-SHA256",
|
|
317
|
+
saltSize: salt.byteLength,
|
|
318
|
+
infoSize: info.byteLength,
|
|
319
|
+
duration: Date.now() - startTime
|
|
320
|
+
}));
|
|
321
|
+
return encryptionKey;
|
|
322
|
+
} catch (error) {
|
|
323
|
+
this.auditor.logEvent(this.createAuditEvent("key_derivation", false, {
|
|
324
|
+
operation: "HKDF",
|
|
325
|
+
algorithm: "HKDF-SHA256",
|
|
326
|
+
saltSize: salt.byteLength,
|
|
327
|
+
infoSize: info.byteLength,
|
|
328
|
+
duration: Date.now() - startTime
|
|
329
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Generate random bytes with compliance audit
|
|
335
|
+
*/
|
|
336
|
+
randomBytes(length) {
|
|
337
|
+
const startTime = Date.now();
|
|
338
|
+
try {
|
|
339
|
+
const randomData = this.underlyingProvider.randomBytes(length);
|
|
340
|
+
this.auditor.logEvent(this.createAuditEvent("random_generation", true, {
|
|
341
|
+
length,
|
|
342
|
+
duration: Date.now() - startTime
|
|
343
|
+
}));
|
|
344
|
+
return randomData;
|
|
345
|
+
} catch (error) {
|
|
346
|
+
this.auditor.logEvent(this.createAuditEvent("random_generation", false, {
|
|
347
|
+
length,
|
|
348
|
+
duration: Date.now() - startTime
|
|
349
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Encrypt data with compliance audit
|
|
355
|
+
*/
|
|
356
|
+
async encrypt(key, data, iv) {
|
|
357
|
+
const startTime = Date.now();
|
|
358
|
+
try {
|
|
359
|
+
this.validateKeyUsage("encryption", key.usages, data.byteLength);
|
|
360
|
+
const ciphertext = await this.underlyingProvider.encrypt(key, data, iv);
|
|
361
|
+
this.auditor.logEvent(this.createAuditEvent("encryption", true, {
|
|
362
|
+
algorithm: key.algorithm,
|
|
363
|
+
dataSize: data.byteLength,
|
|
364
|
+
ivSize: iv.byteLength,
|
|
365
|
+
ciphertextSize: ciphertext.byteLength,
|
|
366
|
+
duration: Date.now() - startTime
|
|
367
|
+
}));
|
|
368
|
+
return ciphertext;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
this.auditor.logEvent(this.createAuditEvent("encryption", false, {
|
|
371
|
+
algorithm: key.algorithm,
|
|
372
|
+
dataSize: data.byteLength,
|
|
373
|
+
ivSize: iv.byteLength,
|
|
374
|
+
duration: Date.now() - startTime
|
|
375
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
376
|
+
throw error;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Decrypt data with compliance audit
|
|
381
|
+
*/
|
|
382
|
+
async decrypt(key, data, iv) {
|
|
383
|
+
const startTime = Date.now();
|
|
384
|
+
try {
|
|
385
|
+
this.validateKeyUsage("decryption", key.usages, data.byteLength);
|
|
386
|
+
const plaintext = await this.underlyingProvider.decrypt(key, data, iv);
|
|
387
|
+
this.auditor.logEvent(this.createAuditEvent("decryption", true, {
|
|
388
|
+
algorithm: key.algorithm,
|
|
389
|
+
dataSize: data.byteLength,
|
|
390
|
+
ivSize: iv.byteLength,
|
|
391
|
+
plaintextSize: plaintext.byteLength,
|
|
392
|
+
duration: Date.now() - startTime
|
|
393
|
+
}));
|
|
394
|
+
return plaintext;
|
|
395
|
+
} catch (error) {
|
|
396
|
+
this.auditor.logEvent(this.createAuditEvent("decryption", false, {
|
|
397
|
+
algorithm: key.algorithm,
|
|
398
|
+
dataSize: data.byteLength,
|
|
399
|
+
ivSize: iv.byteLength,
|
|
400
|
+
duration: Date.now() - startTime
|
|
401
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
402
|
+
throw error;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Generate HMAC with compliance audit
|
|
407
|
+
*/
|
|
408
|
+
async generateHMAC(key, data) {
|
|
409
|
+
const startTime = Date.now();
|
|
410
|
+
try {
|
|
411
|
+
this.validateKeyUsage("hmac", key.usages, data.byteLength);
|
|
412
|
+
const mac = await this.underlyingProvider.generateHMAC(key, data);
|
|
413
|
+
this.auditor.logEvent(this.createAuditEvent("hmac_generation", true, {
|
|
414
|
+
algorithm: "HMAC-SHA256",
|
|
415
|
+
dataSize: data.byteLength,
|
|
416
|
+
macSize: mac.byteLength,
|
|
417
|
+
duration: Date.now() - startTime
|
|
418
|
+
}));
|
|
419
|
+
return mac;
|
|
420
|
+
} catch (error) {
|
|
421
|
+
this.auditor.logEvent(this.createAuditEvent("hmac_generation", false, {
|
|
422
|
+
algorithm: "HMAC-SHA256",
|
|
423
|
+
dataSize: data.byteLength,
|
|
424
|
+
duration: Date.now() - startTime
|
|
425
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Verify HMAC with compliance audit
|
|
431
|
+
*/
|
|
432
|
+
async verifyHMAC(key, data, mac) {
|
|
433
|
+
const startTime = Date.now();
|
|
434
|
+
try {
|
|
435
|
+
this.validateKeyUsage("hmac", key.usages, data.byteLength);
|
|
436
|
+
const isValid = await this.underlyingProvider.verifyHMAC(key, data, mac);
|
|
437
|
+
this.auditor.logEvent(this.createAuditEvent("hmac_verification", true, {
|
|
438
|
+
algorithm: "HMAC-SHA256",
|
|
439
|
+
dataSize: data.byteLength,
|
|
440
|
+
macSize: mac.byteLength,
|
|
441
|
+
verified: isValid,
|
|
442
|
+
duration: Date.now() - startTime
|
|
443
|
+
}));
|
|
444
|
+
return isValid;
|
|
445
|
+
} catch (error) {
|
|
446
|
+
this.auditor.logEvent(this.createAuditEvent("hmac_verification", false, {
|
|
447
|
+
algorithm: "HMAC-SHA256",
|
|
448
|
+
dataSize: data.byteLength,
|
|
449
|
+
macSize: mac.byteLength,
|
|
450
|
+
duration: Date.now() - startTime
|
|
451
|
+
}, error instanceof Error ? error.message : String(error)));
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Get compliance auditor for external access
|
|
457
|
+
*/
|
|
458
|
+
getAuditor() {
|
|
459
|
+
return this.auditor;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Update compliance configuration
|
|
463
|
+
*/
|
|
464
|
+
updateConfig(newConfig) {
|
|
465
|
+
Object.assign(this.config, newConfig);
|
|
466
|
+
this.logger?.debug("Compliance configuration updated", newConfig);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Get underlying provider (for debugging/testing)
|
|
470
|
+
*/
|
|
471
|
+
getUnderlyingProvider() {
|
|
472
|
+
return this.underlyingProvider;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
chunkWGEGR3DF_cjs.__name(_ComplianceCryptoProvider, "ComplianceCryptoProvider");
|
|
476
|
+
var ComplianceCryptoProvider = _ComplianceCryptoProvider;
|
|
477
|
+
|
|
478
|
+
// src/crypto/context.ts
|
|
479
|
+
var _CryptoContextManager = class _CryptoContextManager {
|
|
480
|
+
constructor() {
|
|
481
|
+
this.provider = null;
|
|
482
|
+
this.config = null;
|
|
483
|
+
this.initialized = false;
|
|
484
|
+
this.initializing = false;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Initialize the crypto context with specific configuration
|
|
488
|
+
*
|
|
489
|
+
* @param config - Provider configuration options
|
|
490
|
+
* @throws Error if already initialized (call reset() first)
|
|
491
|
+
* @throws CryptoProviderUnavailableError if strict mode enabled and provider unavailable
|
|
492
|
+
*/
|
|
493
|
+
initialize(config = {}) {
|
|
494
|
+
if (this.initialized && this.provider) {
|
|
495
|
+
throw new Error(
|
|
496
|
+
"CryptoContext already initialized. Call CryptoContext.reset() first to reconfigure."
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
if (config.strict && config.type) {
|
|
500
|
+
const availableProviders = chunkA6FLEJ7R_cjs.getRegisteredCryptoProviders();
|
|
501
|
+
if (!availableProviders.includes(config.type)) {
|
|
502
|
+
const platform = detectPlatform();
|
|
503
|
+
const recommendations = [
|
|
504
|
+
`Import the provider: import '@bananalink-sdk/protocol/crypto/provider/${config.type}'`,
|
|
505
|
+
"Ensure the provider package is installed"
|
|
506
|
+
];
|
|
507
|
+
if (config.type === "quickcrypto" && !platform.isReactNative) {
|
|
508
|
+
recommendations.push("QuickCrypto requires React Native environment");
|
|
509
|
+
if (platform.isNode) {
|
|
510
|
+
recommendations.push("Try 'node' provider for Node.js");
|
|
511
|
+
} else if (platform.isBrowser) {
|
|
512
|
+
recommendations.push("Try 'webcrypto' provider for browsers");
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (availableProviders.includes("noble")) {
|
|
516
|
+
recommendations.push("'noble' provider works in all environments as a fallback");
|
|
517
|
+
}
|
|
518
|
+
throw new CryptoProviderUnavailableError(
|
|
519
|
+
`Strict mode: Crypto provider '${config.type}' is not registered. Did you forget to import it?`,
|
|
520
|
+
{
|
|
521
|
+
requestedProvider: config.type,
|
|
522
|
+
availableProviders,
|
|
523
|
+
platform,
|
|
524
|
+
recommendations
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
this.config = config;
|
|
530
|
+
this.provider = this.createProvider(config);
|
|
531
|
+
this.initialized = true;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Get the active crypto provider
|
|
535
|
+
* Automatically initializes with default config if not already initialized
|
|
536
|
+
*
|
|
537
|
+
* @returns The active crypto provider instance
|
|
538
|
+
* @throws Error if called concurrently during initialization
|
|
539
|
+
*
|
|
540
|
+
* @remarks
|
|
541
|
+
* This method performs lazy initialization on first call. It is NOT safe to call
|
|
542
|
+
* concurrently from multiple contexts before initialization completes (e.g., from
|
|
543
|
+
* Worker threads or Promise.all). For concurrent access scenarios, explicitly call
|
|
544
|
+
* initialize() first to ensure the provider is ready before concurrent operations begin.
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```typescript
|
|
548
|
+
* // Safe: Single-threaded lazy initialization
|
|
549
|
+
* const provider = CryptoContext.getProvider();
|
|
550
|
+
*
|
|
551
|
+
* // Safe: Pre-initialize for concurrent access
|
|
552
|
+
* CryptoContext.initialize({ type: 'noble' });
|
|
553
|
+
* await Promise.all([
|
|
554
|
+
* operation1(CryptoContext.getProvider()),
|
|
555
|
+
* operation2(CryptoContext.getProvider())
|
|
556
|
+
* ]);
|
|
557
|
+
*
|
|
558
|
+
* // Unsafe: Concurrent calls during lazy initialization
|
|
559
|
+
* await Promise.all([
|
|
560
|
+
* operation1(CryptoContext.getProvider()), // May throw if not initialized yet
|
|
561
|
+
* operation2(CryptoContext.getProvider())
|
|
562
|
+
* ]);
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
565
|
+
getProvider() {
|
|
566
|
+
if (this.provider) {
|
|
567
|
+
return this.provider;
|
|
568
|
+
}
|
|
569
|
+
if (this.initializing) {
|
|
570
|
+
throw new Error(
|
|
571
|
+
"CryptoContext initialization in progress. Avoid concurrent calls to getProvider() during initialization."
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
this.initializing = true;
|
|
575
|
+
try {
|
|
576
|
+
this.initialize();
|
|
577
|
+
if (!this.provider) {
|
|
578
|
+
throw new Error("CryptoContext initialization failed: provider is null");
|
|
579
|
+
}
|
|
580
|
+
return this.provider;
|
|
581
|
+
} finally {
|
|
582
|
+
this.initializing = false;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Set a custom provider instance
|
|
587
|
+
* Useful for testing or advanced use cases
|
|
588
|
+
*
|
|
589
|
+
* @param provider - Custom provider instance
|
|
590
|
+
*/
|
|
591
|
+
setProvider(provider) {
|
|
592
|
+
this.provider = provider;
|
|
593
|
+
this.initialized = true;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Check if context has been explicitly initialized
|
|
597
|
+
*/
|
|
598
|
+
isInitialized() {
|
|
599
|
+
return this.initialized;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Get current configuration
|
|
603
|
+
*/
|
|
604
|
+
getConfig() {
|
|
605
|
+
return this.config;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Reset the context (for testing or reconfiguration)
|
|
609
|
+
*/
|
|
610
|
+
reset() {
|
|
611
|
+
this.provider = null;
|
|
612
|
+
this.config = null;
|
|
613
|
+
this.initialized = false;
|
|
614
|
+
this.initializing = false;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Create a provider instance from configuration
|
|
618
|
+
*/
|
|
619
|
+
createProvider(config) {
|
|
620
|
+
const baseProvider = createCryptoProvider(config.type, config.logger, config.strict);
|
|
621
|
+
if (config.compliance?.enabled) {
|
|
622
|
+
return new ComplianceCryptoProvider(baseProvider, config.compliance);
|
|
623
|
+
}
|
|
624
|
+
return baseProvider;
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
chunkWGEGR3DF_cjs.__name(_CryptoContextManager, "CryptoContextManager");
|
|
628
|
+
var CryptoContextManager = _CryptoContextManager;
|
|
629
|
+
var CryptoContext = new CryptoContextManager();
|
|
630
|
+
|
|
631
|
+
// src/crypto/utils.ts
|
|
632
|
+
function randomBytes(length, provider) {
|
|
633
|
+
const activeProvider = provider || CryptoContext.getProvider();
|
|
634
|
+
const buffer = activeProvider.randomBytes(length);
|
|
635
|
+
return new Uint8Array(buffer);
|
|
636
|
+
}
|
|
637
|
+
chunkWGEGR3DF_cjs.__name(randomBytes, "randomBytes");
|
|
638
|
+
function arrayBufferToBase64(buffer) {
|
|
639
|
+
const bytes = new Uint8Array(buffer);
|
|
640
|
+
let binary = "";
|
|
641
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
642
|
+
binary += String.fromCharCode(bytes[i]);
|
|
643
|
+
}
|
|
644
|
+
return btoa(binary);
|
|
645
|
+
}
|
|
646
|
+
chunkWGEGR3DF_cjs.__name(arrayBufferToBase64, "arrayBufferToBase64");
|
|
647
|
+
function base64ToArrayBuffer(base64) {
|
|
648
|
+
const cleanBase64 = base64.replace(/[^A-Za-z0-9+/=]/g, "");
|
|
649
|
+
let paddedBase64 = cleanBase64;
|
|
650
|
+
while (paddedBase64.length % 4 !== 0) {
|
|
651
|
+
paddedBase64 += "=";
|
|
652
|
+
}
|
|
653
|
+
try {
|
|
654
|
+
const binary = atob(paddedBase64);
|
|
655
|
+
const bytes = new Uint8Array(binary.length);
|
|
656
|
+
for (let i = 0; i < binary.length; i++) {
|
|
657
|
+
bytes[i] = binary.charCodeAt(i);
|
|
658
|
+
}
|
|
659
|
+
return bytes.buffer;
|
|
660
|
+
} catch (error) {
|
|
661
|
+
throw new Error(`Failed to decode base64 string: ${error instanceof Error ? error.message : "Invalid base64 format"}. Original string: ${base64.substring(0, 50)}...`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
chunkWGEGR3DF_cjs.__name(base64ToArrayBuffer, "base64ToArrayBuffer");
|
|
665
|
+
function stringToArrayBuffer(str) {
|
|
666
|
+
return new TextEncoder().encode(str).buffer;
|
|
667
|
+
}
|
|
668
|
+
chunkWGEGR3DF_cjs.__name(stringToArrayBuffer, "stringToArrayBuffer");
|
|
669
|
+
function arrayBufferToString(buffer) {
|
|
670
|
+
return new TextDecoder().decode(buffer);
|
|
671
|
+
}
|
|
672
|
+
chunkWGEGR3DF_cjs.__name(arrayBufferToString, "arrayBufferToString");
|
|
673
|
+
function generateNonce(length = 32, provider) {
|
|
674
|
+
const bytes = randomBytes(length, provider);
|
|
675
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
676
|
+
}
|
|
677
|
+
chunkWGEGR3DF_cjs.__name(generateNonce, "generateNonce");
|
|
678
|
+
function generateUUID(provider) {
|
|
679
|
+
const bytes = randomBytes(16, provider);
|
|
680
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
681
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
682
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
683
|
+
return [
|
|
684
|
+
hex.slice(0, 8),
|
|
685
|
+
hex.slice(8, 12),
|
|
686
|
+
hex.slice(12, 16),
|
|
687
|
+
hex.slice(16, 20),
|
|
688
|
+
hex.slice(20, 32)
|
|
689
|
+
].join("-");
|
|
690
|
+
}
|
|
691
|
+
chunkWGEGR3DF_cjs.__name(generateUUID, "generateUUID");
|
|
692
|
+
function detectPlatform() {
|
|
693
|
+
const isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
694
|
+
const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
|
|
695
|
+
const isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
|
|
696
|
+
let platform;
|
|
697
|
+
if (isNode && typeof process.platform === "string") {
|
|
698
|
+
platform = process.platform;
|
|
699
|
+
}
|
|
700
|
+
let userAgent;
|
|
701
|
+
if (typeof navigator !== "undefined" && typeof navigator.userAgent === "string") {
|
|
702
|
+
userAgent = navigator.userAgent;
|
|
703
|
+
}
|
|
704
|
+
return {
|
|
705
|
+
isNode,
|
|
706
|
+
isBrowser,
|
|
707
|
+
isReactNative,
|
|
708
|
+
platform,
|
|
709
|
+
userAgent
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
chunkWGEGR3DF_cjs.__name(detectPlatform, "detectPlatform");
|
|
713
|
+
|
|
714
|
+
// src/crypto/providers/factory.ts
|
|
715
|
+
function generateRecommendations(requestedProvider, platform) {
|
|
716
|
+
const recommendations = [];
|
|
717
|
+
if (requestedProvider === "webcrypto") {
|
|
718
|
+
recommendations.push("WebCrypto requires a browser or Node.js 15+ environment");
|
|
719
|
+
if (platform.isNode) {
|
|
720
|
+
recommendations.push("Try 'node' provider for Node.js");
|
|
721
|
+
}
|
|
722
|
+
} else if (requestedProvider === "node") {
|
|
723
|
+
recommendations.push("Node crypto requires Node.js environment");
|
|
724
|
+
if (platform.isBrowser) {
|
|
725
|
+
recommendations.push("Try 'webcrypto' provider for browsers");
|
|
726
|
+
}
|
|
727
|
+
} else if (requestedProvider === "quickcrypto") {
|
|
728
|
+
recommendations.push("QuickCrypto requires React Native environment");
|
|
729
|
+
if (!platform.isReactNative) {
|
|
730
|
+
if (platform.isNode) {
|
|
731
|
+
recommendations.push("Try 'node' provider for Node.js");
|
|
732
|
+
} else if (platform.isBrowser) {
|
|
733
|
+
recommendations.push("Try 'webcrypto' provider for browsers");
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
recommendations.push("'noble' provider works in all environments as a fallback");
|
|
738
|
+
recommendations.push(`Import the provider: import '@bananalink-sdk/protocol/crypto/provider/${requestedProvider}'`);
|
|
739
|
+
return recommendations;
|
|
740
|
+
}
|
|
741
|
+
chunkWGEGR3DF_cjs.__name(generateRecommendations, "generateRecommendations");
|
|
742
|
+
function createCryptoProvider(preferredProvider, logger, strict) {
|
|
743
|
+
const registeredProviders = chunkA6FLEJ7R_cjs.getRegisteredCryptoProviders();
|
|
744
|
+
logger?.debug("Creating crypto provider", {
|
|
745
|
+
preferredProvider,
|
|
746
|
+
strict,
|
|
747
|
+
registeredProviders
|
|
748
|
+
});
|
|
749
|
+
let providerType = preferredProvider;
|
|
750
|
+
if (!providerType) {
|
|
751
|
+
if (registeredProviders.length === 0) {
|
|
752
|
+
throw new CryptoProviderUnavailableError(
|
|
753
|
+
"No crypto providers are registered. Did you forget to import a provider?",
|
|
754
|
+
{
|
|
755
|
+
availableProviders: [],
|
|
756
|
+
recommendations: [
|
|
757
|
+
"Import at least one crypto provider, e.g.: import '@bananalink-sdk/protocol/crypto/provider/noble'",
|
|
758
|
+
"Noble provider is recommended as a universal fallback"
|
|
759
|
+
]
|
|
760
|
+
}
|
|
761
|
+
);
|
|
762
|
+
} else if (registeredProviders.length === 1) {
|
|
763
|
+
providerType = registeredProviders[0];
|
|
764
|
+
logger?.debug(`Auto-selected '${providerType}' provider (only one registered)`);
|
|
765
|
+
} else {
|
|
766
|
+
throw new CryptoProviderUnavailableError(
|
|
767
|
+
`Multiple crypto providers registered: ${registeredProviders.join(", ")}. Either import only one provider OR explicitly set cryptoProvider.type. Example: cryptoProvider: { type: '${registeredProviders[0]}' }`,
|
|
768
|
+
{
|
|
769
|
+
availableProviders: registeredProviders,
|
|
770
|
+
recommendations: [
|
|
771
|
+
`Import only one crypto provider, or specify which one to use`,
|
|
772
|
+
`Registered providers: ${registeredProviders.join(", ")}`,
|
|
773
|
+
`Set cryptoProvider.type to one of the registered providers`
|
|
774
|
+
]
|
|
775
|
+
}
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
try {
|
|
780
|
+
const factory = chunkA6FLEJ7R_cjs.getCryptoProviderFactory(providerType);
|
|
781
|
+
const provider = factory(logger);
|
|
782
|
+
logger?.info(`Using ${provider.name} crypto provider`, {
|
|
783
|
+
providerType,
|
|
784
|
+
isAvailable: provider.isAvailable
|
|
785
|
+
});
|
|
786
|
+
return provider;
|
|
787
|
+
} catch (error) {
|
|
788
|
+
const userRequestedSpecificProvider = preferredProvider !== void 0;
|
|
789
|
+
if (strict && userRequestedSpecificProvider) {
|
|
790
|
+
if (error instanceof CryptoProviderUnavailableError) {
|
|
791
|
+
throw error;
|
|
792
|
+
}
|
|
793
|
+
const platform2 = detectPlatform();
|
|
794
|
+
const availableProviders = chunkA6FLEJ7R_cjs.getRegisteredCryptoProviders();
|
|
795
|
+
const recommendations2 = generateRecommendations(providerType, platform2);
|
|
796
|
+
throw new CryptoProviderUnavailableError(
|
|
797
|
+
`Strict mode: Crypto provider '${providerType}' failed to initialize: ${error instanceof Error ? error.message : String(error)}`,
|
|
798
|
+
{
|
|
799
|
+
requestedProvider: providerType,
|
|
800
|
+
availableProviders,
|
|
801
|
+
platform: platform2,
|
|
802
|
+
recommendations: recommendations2
|
|
803
|
+
}
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
logger?.warn(`Failed to create '${providerType}' provider, trying fallback`, {
|
|
807
|
+
error: error instanceof Error ? { message: error.message } : { message: String(error) }
|
|
808
|
+
});
|
|
809
|
+
for (const fallbackType of registeredProviders) {
|
|
810
|
+
if (fallbackType === providerType) continue;
|
|
811
|
+
try {
|
|
812
|
+
const factory = chunkA6FLEJ7R_cjs.getCryptoProviderFactory(fallbackType);
|
|
813
|
+
const provider = factory(logger);
|
|
814
|
+
logger?.info(`Using ${provider.name} crypto provider (fallback)`, {
|
|
815
|
+
originalType: providerType,
|
|
816
|
+
fallbackType
|
|
817
|
+
});
|
|
818
|
+
return provider;
|
|
819
|
+
} catch (fallbackError) {
|
|
820
|
+
logger?.debug(`Fallback to '${fallbackType}' failed`, {
|
|
821
|
+
error: fallbackError instanceof Error ? { message: fallbackError.message } : { message: String(fallbackError) }
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const platform = detectPlatform();
|
|
826
|
+
const recommendations = generateRecommendations(providerType, platform);
|
|
827
|
+
throw new CryptoProviderUnavailableError(
|
|
828
|
+
`Failed to create any crypto provider. Requested: '${providerType}'`,
|
|
829
|
+
{
|
|
830
|
+
requestedProvider: providerType,
|
|
831
|
+
availableProviders: registeredProviders,
|
|
832
|
+
platform,
|
|
833
|
+
recommendations
|
|
834
|
+
}
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
chunkWGEGR3DF_cjs.__name(createCryptoProvider, "createCryptoProvider");
|
|
839
|
+
|
|
840
|
+
exports.ComplianceCryptoProvider = ComplianceCryptoProvider;
|
|
841
|
+
exports.CryptoCapabilityMissingError = CryptoCapabilityMissingError;
|
|
842
|
+
exports.CryptoContext = CryptoContext;
|
|
843
|
+
exports.CryptoError = CryptoError;
|
|
844
|
+
exports.CryptoProviderUnavailableError = CryptoProviderUnavailableError;
|
|
845
|
+
exports.DefaultComplianceAuditor = DefaultComplianceAuditor;
|
|
846
|
+
exports.arrayBufferToBase64 = arrayBufferToBase64;
|
|
847
|
+
exports.arrayBufferToString = arrayBufferToString;
|
|
848
|
+
exports.base64ToArrayBuffer = base64ToArrayBuffer;
|
|
849
|
+
exports.createCryptoProvider = createCryptoProvider;
|
|
850
|
+
exports.detectPlatform = detectPlatform;
|
|
851
|
+
exports.generateNonce = generateNonce;
|
|
852
|
+
exports.generateUUID = generateUUID;
|
|
853
|
+
exports.randomBytes = randomBytes;
|
|
854
|
+
exports.stringToArrayBuffer = stringToArrayBuffer;
|
|
855
|
+
//# sourceMappingURL=chunk-VXLUSU5B.cjs.map
|
|
856
|
+
//# sourceMappingURL=chunk-VXLUSU5B.cjs.map
|