@dynamic-labs-wallet/forward-mpc-client 0.2.0 → 0.3.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.
- package/dist/index.cjs +52 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +53 -1
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var init = require('@evervault/wasm-attestation-bindings');
|
|
|
7
7
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
8
8
|
var utils_js = require('@noble/hashes/utils.js');
|
|
9
9
|
var fpTs = require('fp-ts');
|
|
10
|
+
var core = require('@dynamic-labs-wallet/core');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -489,6 +490,57 @@ var ForwardMPCClient = class extends eventemitter3.EventEmitter {
|
|
|
489
490
|
});
|
|
490
491
|
return this.sendRequest(request);
|
|
491
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Perform MPC keygen for ECDSA and BIP340 algorithms
|
|
495
|
+
* For ED25519, use sampleKey() or receiveKey() methods instead
|
|
496
|
+
*/
|
|
497
|
+
async keygen(params) {
|
|
498
|
+
if (params.signingAlgo === core.SigningAlgorithm.ED25519) {
|
|
499
|
+
throw new Error("ED25519 keygen not supported via keygen() method. Use sampleKey() or receiveKey() instead.");
|
|
500
|
+
}
|
|
501
|
+
const { sharedSecret, connectionId } = await this.ensureWsConnection();
|
|
502
|
+
const encryptedKeygenInit = forwardMpcShared.encryptKeygenInit(params.keygenInit, sharedSecret, connectionId);
|
|
503
|
+
const request = new forwardMpcShared.KeygenV1RequestMessage({
|
|
504
|
+
relayDomain: params.relayDomain,
|
|
505
|
+
signingAlgo: params.signingAlgo,
|
|
506
|
+
roomUuid: params.roomUuid,
|
|
507
|
+
numParties: params.numParties,
|
|
508
|
+
threshold: params.threshold,
|
|
509
|
+
keygenInit: encryptedKeygenInit,
|
|
510
|
+
keygenIds: params.keygenIds,
|
|
511
|
+
traceContext: params.traceContext,
|
|
512
|
+
userId: params.userId,
|
|
513
|
+
environmentId: params.environmentId
|
|
514
|
+
});
|
|
515
|
+
const response = await this.sendRequest(request);
|
|
516
|
+
const responseData = response.getData();
|
|
517
|
+
const keygenResult = forwardMpcShared.decryptKeygenResult(responseData.keygenResult, sharedSecret, connectionId);
|
|
518
|
+
return keygenResult;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Receive an ED25519 key (one party receives the key generated by another)
|
|
522
|
+
* Uses ExportableEd25519 - the receiving party gets the key sampled by another party
|
|
523
|
+
*/
|
|
524
|
+
async receiveKey(params) {
|
|
525
|
+
const { sharedSecret, connectionId } = await this.ensureWsConnection();
|
|
526
|
+
const encryptedKeygenInit = forwardMpcShared.encryptKeygenInit(params.keygenInit, sharedSecret, connectionId);
|
|
527
|
+
const request = new forwardMpcShared.ReceiveKeyV1RequestMessage({
|
|
528
|
+
relayDomain: params.relayDomain,
|
|
529
|
+
signingAlgo: "ed25519",
|
|
530
|
+
roomUuid: params.roomUuid,
|
|
531
|
+
numParties: params.numParties,
|
|
532
|
+
threshold: params.threshold,
|
|
533
|
+
keygenInit: encryptedKeygenInit,
|
|
534
|
+
keygenIds: params.keygenIds,
|
|
535
|
+
traceContext: params.traceContext,
|
|
536
|
+
userId: params.userId,
|
|
537
|
+
environmentId: params.environmentId
|
|
538
|
+
});
|
|
539
|
+
const response = await this.sendRequest(request);
|
|
540
|
+
const responseData = response.getData();
|
|
541
|
+
const keygenResult = forwardMpcShared.decryptKeygenResult(responseData.keygenResult, sharedSecret, connectionId);
|
|
542
|
+
return keygenResult;
|
|
543
|
+
}
|
|
492
544
|
get connected() {
|
|
493
545
|
return this.isConnected;
|
|
494
546
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/attestation/constants.ts","../src/attestation/verifier.ts","../src/client.ts"],"names":["ATTESTATION_CONSTANTS","MAX_ATTESTATION_AGE","NitroAttestationVerifier","config","wasmInitialized","strictCertValidation","maxAge","ensureWasmInitialized","init","error","Error","message","verify","attestationDocBase64","expectedChallenge","expectedNonce","expectedPcrs","PCRs","empty","pcr8","expectedPcr8","isValid","validateAttestationDocPcrs","valid","errors","timestamp","Date","now","userData","getUserData","userDataString","TextDecoder","decode","includes","String","extractedNonceRaw","getNonce","extractedNonce","nonceString","atob","binaryString","Uint8Array","length","i","charCodeAt","decodedBuffer","Buffer","from","decodeError","isWindow","globalThis","window","WebSocketImpl","WebSocket","ForwardMPCClient","EventEmitter","ws","url","options","attestationVerifier","isConnected","messageId","pendingRequests","Map","sharedSecret","decapsulationKey","connectionId","handshakeNonce","attestationPromise","reconnectAttempts","reconnectInterval","connectionTimeout","heartbeatInterval","attestationConfig","bypassAttestation","connect","Promise","resolve","reject","timeout","setTimeout","onopen","clearTimeout","emit","onerror","_error","onmessage","event","handleMessage","data","onclose","cleanup","on","toString","disconnect","close","request","clear","fill","ensureWsConnection","handshake","parsed","JSON","parse","requestId","deserializeMessage","stringify","has","get","delete","type","errorMsg","endsWith","responseData","getData","sendRequest","messageWithId","set","serializedMessage","serializeMessage","send","encode","encoded","messageRegistry","result","either","isLeft","right","traceContext","encapsulationKey","generateMlKem768Keypair","nonceBytes","randomBytes","HandshakeV1RequestMessage","challenge","nonce","response","encapsulatedSharedSecret","cipherText","hexToBytes","decapsulateMlKem768","attestationDoc","verifyAttestationDocument","signMessage","params","messageToSign","cleanHex","startsWith","slice","encryptedKeyshare","encryptKeyshare","keyshare","signingAlgo","SignMessageV1RequestMessage","relayDomain","hashAlgo","derivationPath","tweak","roomUuid","userId","environmentId","connected","challengeHash","sha256","Array","map","b","padStart","join"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * AWS Nitro Security Module (NSM) Root Certificate\n * This is the official AWS root certificate used to verify attestation documents\n */\nexport const AWS_NITRO_ROOT_CERTIFICATE = `-----BEGIN CERTIFICATE-----\nMIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL\nMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD\nVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4\nMTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL\nDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb\n48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE\nh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF\nR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC\nMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW\nrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N\nIwLz3/Y=\n-----END CERTIFICATE-----`;\n\n/**\n * Expected PCR values for different environments\n */\nexport const EXPECTED_PCR_VALUES = {\n // Production PCR8 values would be set based on actual enclave builds\n // These would be configured via environment variables in production\n // Development values should be set in the application configuration, not here\n} as const;\n\n/**\n * Attestation document validation constants\n */\nexport const ATTESTATION_CONSTANTS = {\n // Maximum age of attestation document in milliseconds\n MAX_ATTESTATION_AGE: 5 * 60 * 1000, // 5 minutes\n\n // Expected digest algorithm\n EXPECTED_DIGEST: 'SHA384',\n\n // Expected module ID pattern\n MODULE_ID_PATTERN: /^i-[0-9a-f]{8,17}-enc[0-9a-f]{8,17}$/,\n\n // PCR indices that must be present\n REQUIRED_PCRS: [0, 1, 2, 8] as const,\n} as const;\n","import {\n AttestationVerificationResult,\n AttestationVerificationConfig,\n} from './types';\nimport { ATTESTATION_CONSTANTS } from './constants';\n\n// Import Evervault WASM attestation bindings\nimport init, {\n validateAttestationDocPcrs,\n PCRs,\n getUserData,\n getNonce,\n} from '@evervault/wasm-attestation-bindings';\n\n/**\n * Nitro Enclave Attestation Document Verifier\n * Uses Evervault's official WASM attestation bindings\n * Optimized for client-side usage with hex string input\n */\nexport class NitroAttestationVerifier {\n private readonly config: AttestationVerificationConfig;\n private wasmInitialized = false;\n\n constructor(config: AttestationVerificationConfig) {\n this.config = {\n strictCertValidation: true,\n maxAge: ATTESTATION_CONSTANTS.MAX_ATTESTATION_AGE,\n ...config,\n };\n }\n\n /**\n * Initialize WASM module if not already initialized\n */\n private async ensureWasmInitialized(): Promise<void> {\n if (!this.wasmInitialized) {\n try {\n // Initialize WASM module - in browser, this will automatically load the .wasm file\n await init();\n this.wasmInitialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n }\n\n /**\n * Verify an attestation document using Evervault WASM bindings\n * Accepts base64-encoded attestation document directly\n *\n * @param attestationDocBase64 - Base64-encoded attestation document\n * @param expectedChallenge - Expected challenge (ciphertext hash)\n * @param expectedNonce - Expected nonce (REQUIRED for security)\n */\n async verify(\n attestationDocBase64: string,\n expectedChallenge: string,\n expectedNonce: Uint8Array\n ): Promise<AttestationVerificationResult> {\n try {\n // Ensure WASM module is initialized\n await this.ensureWasmInitialized();\n\n // Create PCRs container with expected values\n const expectedPcrs = PCRs.empty();\n expectedPcrs.pcr8 = this.config.expectedPcr8;\n\n // Use Evervault WASM bindings to verify the attestation document (already in base64)\n const isValid = validateAttestationDocPcrs(attestationDocBase64, [\n expectedPcrs,\n ]);\n\n if (!isValid) {\n return {\n valid: false,\n errors: ['Attestation document PCR verification failed'],\n timestamp: Date.now(),\n };\n }\n\n // Verify challenge (ciphertext hash) if provided\n if (expectedChallenge) {\n try {\n const userData = getUserData(attestationDocBase64);\n if (!userData) {\n return {\n valid: false,\n errors: ['No user data found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // Convert user data to string and verify it contains the expected challenge\n const userDataString = new TextDecoder('utf-8').decode(userData);\n\n // The challenge should be the hex-encoded hash of the ciphertext\n // Verify that the attestation document's user data contains this challenge\n if (!userDataString.includes(expectedChallenge)) {\n return {\n valid: false,\n errors: [\n 'Ciphertext hash verification failed - challenge not found in attestation user data',\n ],\n timestamp: Date.now(),\n };\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify ciphertext hash: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n\n // Verify nonce (REQUIRED for security - prevents replay attacks)\n try {\n // Use WASM getNonce function to extract nonce from attestation document\n const extractedNonceRaw = getNonce(attestationDocBase64);\n\n if (!extractedNonceRaw) {\n return {\n valid: false,\n errors: ['No nonce found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // The attestation document stores the nonce as a base64-encoded string\n // We need to decode it back to the original bytes\n let extractedNonce: Uint8Array;\n try {\n // Convert to string and decode from base64 (cross-platform)\n const nonceString = new TextDecoder().decode(extractedNonceRaw);\n\n // Browser-compatible base64 decoding\n if (typeof atob !== 'undefined') {\n // Browser environment\n const binaryString = atob(nonceString);\n extractedNonce = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n extractedNonce[i] = binaryString.charCodeAt(i);\n }\n } else {\n // Node.js environment\n const decodedBuffer = Buffer.from(nonceString, 'base64');\n extractedNonce = new Uint8Array(decodedBuffer);\n }\n } catch (decodeError) {\n return {\n valid: false,\n errors: [\n `Failed to decode nonce from base64: ${decodeError instanceof Error ? decodeError.message : String(decodeError)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n // Compare nonces byte-for-byte\n if (extractedNonce.length !== expectedNonce.length) {\n return {\n valid: false,\n errors: [\n `Nonce length mismatch: expected ${expectedNonce.length} bytes, got ${extractedNonce.length} bytes`,\n ],\n timestamp: Date.now(),\n };\n }\n\n for (let i = 0; i < expectedNonce.length; i++) {\n if (extractedNonce[i] !== expectedNonce[i]) {\n return {\n valid: false,\n errors: ['Nonce verification failed - nonce mismatch'],\n timestamp: Date.now(),\n };\n }\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify nonce: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n return {\n valid: true,\n errors: [],\n timestamp: Date.now(),\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Attestation verification error: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n}\n","// Browser/Node.js compatibility\nimport { EventEmitter } from 'eventemitter3';\nimport * as ws from 'ws';\n\nconst isWindow =\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as any).window !== 'undefined';\nconst WebSocketImpl = isWindow ? (globalThis as any).WebSocket : ws.WebSocket;\n\nimport {\n BaseWebSocketMessage,\n ErrorResponse,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport {\n HandshakeV1RequestMessage,\n SignMessageV1RequestMessage,\n messageRegistry,\n HashAlgorithm,\n generateMlKem768Keypair,\n decapsulateMlKem768,\n encryptKeyshare,\n type SigningAlgorithmName,\n type TraceContext,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport { NitroAttestationVerifier } from './attestation';\nimport { AttestationVerificationConfig } from './attestation/types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { hexToBytes, randomBytes } from '@noble/hashes/utils.js';\nimport { either } from 'fp-ts';\nimport { SigningAlgorithm } from '@dynamic-labs-wallet/core';\n\nexport interface ForwardMPCClientOptions {\n reconnectAttempts?: number;\n reconnectInterval?: number;\n connectionTimeout?: number;\n heartbeatInterval?: number;\n attestationConfig?: AttestationVerificationConfig;\n attestationVerifier?: any; // Allow custom verifier (mock or real)\n bypassAttestation?: boolean; // Default: false. Only for testing!\n}\n\nexport interface ClientEvents {\n connected: () => void;\n disconnected: () => void;\n error: (error: Error) => void;\n message: (message: BaseWebSocketMessage) => void;\n}\n\nexport class ForwardMPCClient extends EventEmitter {\n private ws: any = null;\n private url: string;\n private options: Required<\n Omit<ForwardMPCClientOptions, 'attestationVerifier' | 'attestationConfig'>\n > & {\n attestationVerifier?: any;\n attestationConfig?: AttestationVerificationConfig;\n };\n private attestationVerifier: any | null = null; // Can be NitroAttestationVerifier or mock\n private isConnected = false;\n private messageId = 0;\n private pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timeout: NodeJS.Timeout;\n }\n >();\n private sharedSecret: Uint8Array | null = null;\n private decapsulationKey: Uint8Array | null = null;\n private connectionId: string;\n private handshakeNonce: Uint8Array | null = null;\n private attestationPromise: Promise<void> | null = null;\n\n constructor(url: string, options: ForwardMPCClientOptions = {}) {\n super();\n\n this.url = url;\n this.connectionId = ''; // Will be set by server during handshake\n this.options = {\n reconnectAttempts: options.reconnectAttempts ?? 3,\n reconnectInterval: options.reconnectInterval ?? 1000,\n connectionTimeout: options.connectionTimeout ?? 10000,\n heartbeatInterval: options.heartbeatInterval ?? 30000,\n attestationConfig: options.attestationConfig,\n attestationVerifier: options.attestationVerifier,\n bypassAttestation: options.bypassAttestation ?? false,\n };\n\n // Initialize attestation verifier - use custom verifier if provided, otherwise create from config\n if (options.attestationVerifier) {\n this.attestationVerifier = options.attestationVerifier;\n } else if (this.options.attestationConfig) {\n this.attestationVerifier = new NitroAttestationVerifier(\n this.options.attestationConfig\n );\n }\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.isConnected) {\n resolve();\n return;\n }\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n }, this.options.connectionTimeout);\n\n this.ws = new WebSocketImpl(this.url);\n\n // Handle both browser and Node.js WebSocket APIs\n if (isWindow) {\n // Browser WebSocket API\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n };\n\n this.ws.onerror = (_error: any) => {\n clearTimeout(timeout);\n this.emit('error', new Error('WebSocket error'));\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onmessage = (event: any) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n };\n } else {\n // Node.js WebSocket API\n this.ws.on('open', () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n });\n\n this.ws.on('error', (error: any) => {\n clearTimeout(timeout);\n this.emit('error', error);\n reject(error);\n });\n\n this.ws.on('message', (data: any) => {\n this.handleMessage(data.toString());\n });\n\n this.ws.on('close', () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n });\n }\n });\n }\n\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.cleanup();\n }\n\n private cleanup(): void {\n // Reject all pending requests\n for (const [, request] of this.pendingRequests) {\n clearTimeout(request.timeout);\n request.reject(new Error('Connection closed'));\n }\n this.pendingRequests.clear();\n\n // Clear sensitive cryptographic material\n if (this.sharedSecret) {\n this.sharedSecret.fill(0);\n this.sharedSecret = null;\n }\n if (this.decapsulationKey) {\n this.decapsulationKey.fill(0);\n this.decapsulationKey = null;\n }\n if (this.handshakeNonce) {\n this.handshakeNonce.fill(0);\n this.handshakeNonce = null;\n }\n\n // Clear connection ID\n this.connectionId = '';\n\n // Reset attestation state\n this.attestationPromise = null;\n }\n\n /**\n * Ensures the WebSocket connection is active and handshake is completed.\n * Automatically connects and performs handshake if needed.\n * @returns Object containing the shared secret and connection ID\n * @throws Error if connection or handshake fails\n */\n async ensureWsConnection(): Promise<{\n sharedSecret: Uint8Array;\n connectionId: string;\n }> {\n // Check if we need to connect\n if (!this.isConnected || !this.ws) {\n await this.connect();\n }\n\n // Check if we need to perform handshake\n if (!this.sharedSecret || !this.connectionId) {\n await this.handshake();\n }\n\n // Defensive check: if attestation verifier is configured, promise must exist\n if (\n this.attestationVerifier &&\n !this.options.bypassAttestation &&\n !this.attestationPromise\n ) {\n throw new Error(\n 'Attestation verifier configured but attestation was not performed'\n );\n }\n\n // Await attestation completion (throws if failed)\n if (this.attestationPromise) {\n try {\n await this.attestationPromise;\n } catch (error) {\n // Handle attestation failure by disconnecting\n // Side effect is here in the caller's context, not in the promise\n this.disconnect();\n throw error; // Re-throw for the caller\n }\n }\n\n // Final validation - should never happen but defensive check\n if (!this.sharedSecret || !this.connectionId) {\n throw new Error('Failed to establish connection and handshake');\n }\n\n return {\n sharedSecret: this.sharedSecret,\n connectionId: this.connectionId,\n };\n }\n\n private handleMessage(data: string): void {\n try {\n // Parse the raw message first to extract requestId\n const parsed = JSON.parse(data);\n const requestId = parsed.requestId;\n\n // Remove requestId from the message before deserializing\n if (requestId) {\n delete parsed.requestId;\n }\n\n // Now deserialize the message without requestId\n const message = this.deserializeMessage(JSON.stringify(parsed));\n\n // Check if this is a response to a pending request\n if (requestId && this.pendingRequests.has(requestId)) {\n const request = this.pendingRequests.get(requestId)!;\n this.pendingRequests.delete(requestId);\n clearTimeout(request.timeout);\n\n // Handle unified response format with embedded errors\n if (message.type === 'error') {\n // Legacy error response format\n const errorMsg = message as ErrorResponse;\n request.reject(new Error(errorMsg.error.message));\n } else if (message.type.endsWith('_response')) {\n // Check if the response contains an error field\n const responseData = (message as any).getData\n ? (message as any).getData()\n : message;\n if (responseData.error) {\n request.reject(new Error(responseData.error.message));\n } else {\n request.resolve(message);\n }\n } else {\n request.resolve(message);\n }\n return;\n }\n\n this.emit('message', message);\n } catch (error) {\n this.emit('error', new Error(`Failed to parse message: ${error}`));\n }\n }\n\n private sendRequest<T>(message: any): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected || !this.ws) {\n reject(new Error('Not connected'));\n return;\n }\n\n const requestId = `req_${++this.messageId}_${Date.now()}`;\n // Add requestId to message (works for both objects and Message instances)\n const messageWithId = message;\n messageWithId.requestId = requestId;\n\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(requestId);\n reject(new Error('Request timeout'));\n }, 30000); // 30 second timeout for attestation verification\n\n this.pendingRequests.set(requestId, { resolve, reject, timeout });\n\n try {\n // Use custom serializer that encodes using io-ts schemas\n const serializedMessage = this.serializeMessage(messageWithId);\n this.ws.send(serializedMessage);\n } catch (error) {\n this.pendingRequests.delete(requestId);\n clearTimeout(timeout);\n reject(error);\n }\n });\n }\n\n private serializeMessage(message: any): string {\n try {\n // If it's a Message class instance, use its encode method\n if (message && typeof message.encode === 'function') {\n const encoded = message.encode();\n // Add requestId if present\n if (message.requestId) {\n encoded.requestId = message.requestId;\n }\n return JSON.stringify(encoded);\n }\n\n // Fallback to regular JSON for other objects\n return JSON.stringify(message);\n } catch (error) {\n throw new Error(\n `Failed to serialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n private deserializeMessage(data: string): any {\n try {\n const parsed = JSON.parse(data);\n\n // Check if messageRegistry exists and has decode method\n if (!messageRegistry) {\n throw new Error('messageRegistry is undefined');\n }\n\n if (typeof messageRegistry.decode !== 'function') {\n throw new Error('messageRegistry.decode is not a function');\n }\n\n // Use message registry to decode\n const result = messageRegistry.decode(parsed);\n if (either.isLeft(result)) {\n // If registry can't decode it, return as-is (might be error response, etc.)\n return parsed;\n }\n\n return result.right;\n } catch (error) {\n throw new Error(\n `Failed to deserialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n async handshake(traceContext?: TraceContext): Promise<any> {\n // Generate ML-KEM-768 keypair and use encapsulation key as challenge\n const { encapsulationKey, decapsulationKey } = generateMlKem768Keypair();\n\n // Store decapsulation key for later use\n this.decapsulationKey = decapsulationKey;\n\n // Generate a cryptographically secure nonce for attestation\n const nonceBytes = randomBytes(32); // 256-bit nonce\n\n // Store original bytes for verification\n this.handshakeNonce = nonceBytes;\n\n const request = new HandshakeV1RequestMessage({\n challenge: encapsulationKey, // ML-KEM-768 encapsulation key (will be encoded to hex by the message class)\n nonce: nonceBytes, // User data nonce for attestation document\n traceContext,\n });\n\n const response = await this.sendRequest<any>(request);\n\n // Extract shared secret from response using ML-KEM decapsulation\n const responseData = response.getData();\n if (\n responseData.encapsulatedSharedSecret &&\n responseData.connectionId &&\n this.decapsulationKey\n ) {\n // Use the server's connection ID for consistent key derivation\n this.connectionId = responseData.connectionId;\n\n // Convert hex string back to bytes for decapsulation\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Perform ML-KEM decapsulation to derive shared secret\n this.sharedSecret = decapsulateMlKem768(\n this.decapsulationKey,\n cipherText\n );\n }\n\n // Verify attestation document (store promise for later await)\n if (\n this.attestationVerifier &&\n responseData.attestationDoc &&\n responseData.encapsulatedSharedSecret &&\n !this.options.bypassAttestation\n ) {\n // Convert hex string back to bytes for challenge verification\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Store promise - method already throws on failure\n this.attestationPromise = this.verifyAttestationDocument(\n responseData.attestationDoc,\n cipherText\n );\n }\n\n return response;\n }\n\n async signMessage(params: {\n keyshare: any; // Keyshare object from Dynamic Wallet SDK\n message: Uint8Array | string; // Message to sign (supports hex string or Uint8Array)\n relayDomain: string;\n signingAlgo: SigningAlgorithm;\n hashAlgo?: HashAlgorithm;\n derivationPath?: Uint32Array;\n tweak?: Uint8Array;\n roomUuid: string; // MPC room UUID for signing ceremony\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<any> {\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Convert hex string to Uint8Array if needed\n let messageToSign: Uint8Array;\n if (typeof params.message === 'string') {\n // Handle hex strings (with or without 0x prefix)\n const cleanHex = params.message.startsWith('0x')\n ? params.message.slice(2)\n : params.message;\n messageToSign = hexToBytes(cleanHex);\n } else {\n // Already a Uint8Array\n messageToSign = params.message;\n }\n\n // Encrypt the keyshare using AES-256-GCM\n const encryptedKeyshare = await encryptKeyshare(\n params.keyshare,\n sharedSecret,\n connectionId,\n params.signingAlgo as unknown as SigningAlgorithmName\n );\n\n const request = new SignMessageV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: params.signingAlgo,\n hashAlgo: params.hashAlgo,\n derivationPath: params.derivationPath,\n tweak: params.tweak,\n keyshare: encryptedKeyshare,\n message: messageToSign, // Always pass Uint8Array to the message class\n roomUuid: params.roomUuid,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n return this.sendRequest<any>(request);\n }\n\n get connected(): boolean {\n return this.isConnected;\n }\n\n /**\n * Generate a unique connection ID\n */\n\n /**\n * Verify attestation document from handshake response\n * Uses base64-encoded attestation document directly\n */\n private async verifyAttestationDocument(\n attestationDocBase64: string,\n cipherText: Uint8Array\n ): Promise<void> {\n if (!this.attestationVerifier) {\n return; // No verifier configured\n }\n\n try {\n // Generate the expected challenge (hash of cipher text from ML-KEM encapsulation)\n const challengeHash = sha256(cipherText);\n const expectedChallenge = Array.from(challengeHash)\n .map((b: number) => b.toString(16).padStart(2, '0'))\n .join('');\n\n // Verify the attestation document directly with base64 string (no conversion needed!)\n // Nonce is required for security (prevents replay attacks)\n if (!this.handshakeNonce) {\n throw new Error(\n 'Nonce not found - handshake may not have completed properly'\n );\n }\n\n const result = await this.attestationVerifier.verify(\n attestationDocBase64,\n expectedChallenge,\n this.handshakeNonce\n );\n\n if (!result.valid) {\n const errorMsg = `Attestation verification failed: ${result.errors.join(\n ', '\n )}`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n\n // Emit success event with verification result\n this.emit('message', {\n type: 'attestation-verified',\n timestamp: Date.now(),\n data: result,\n } as any);\n } catch (error) {\n const errorMsg = `Attestation verification error: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/attestation/constants.ts","../src/attestation/verifier.ts","../src/client.ts"],"names":["ATTESTATION_CONSTANTS","MAX_ATTESTATION_AGE","NitroAttestationVerifier","config","wasmInitialized","strictCertValidation","maxAge","ensureWasmInitialized","init","error","Error","message","verify","attestationDocBase64","expectedChallenge","expectedNonce","expectedPcrs","PCRs","empty","pcr8","expectedPcr8","isValid","validateAttestationDocPcrs","valid","errors","timestamp","Date","now","userData","getUserData","userDataString","TextDecoder","decode","includes","String","extractedNonceRaw","getNonce","extractedNonce","nonceString","atob","binaryString","Uint8Array","length","i","charCodeAt","decodedBuffer","Buffer","from","decodeError","isWindow","globalThis","window","WebSocketImpl","WebSocket","ForwardMPCClient","EventEmitter","ws","url","options","attestationVerifier","isConnected","messageId","pendingRequests","Map","sharedSecret","decapsulationKey","connectionId","handshakeNonce","attestationPromise","reconnectAttempts","reconnectInterval","connectionTimeout","heartbeatInterval","attestationConfig","bypassAttestation","connect","Promise","resolve","reject","timeout","setTimeout","onopen","clearTimeout","emit","onerror","_error","onmessage","event","handleMessage","data","onclose","cleanup","on","toString","disconnect","close","request","clear","fill","ensureWsConnection","handshake","parsed","JSON","parse","requestId","deserializeMessage","stringify","has","get","delete","type","errorMsg","endsWith","responseData","getData","sendRequest","messageWithId","set","serializedMessage","serializeMessage","send","encode","encoded","messageRegistry","result","either","isLeft","right","traceContext","encapsulationKey","generateMlKem768Keypair","nonceBytes","randomBytes","HandshakeV1RequestMessage","challenge","nonce","response","encapsulatedSharedSecret","cipherText","hexToBytes","decapsulateMlKem768","attestationDoc","verifyAttestationDocument","signMessage","params","messageToSign","cleanHex","startsWith","slice","encryptedKeyshare","encryptKeyshare","keyshare","signingAlgo","SignMessageV1RequestMessage","relayDomain","hashAlgo","derivationPath","tweak","roomUuid","userId","environmentId","keygen","SigningAlgorithm","ED25519","encryptedKeygenInit","encryptKeygenInit","keygenInit","KeygenV1RequestMessage","numParties","threshold","keygenIds","keygenResult","decryptKeygenResult","receiveKey","ReceiveKeyV1RequestMessage","connected","challengeHash","sha256","Array","map","b","padStart","join"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * AWS Nitro Security Module (NSM) Root Certificate\n * This is the official AWS root certificate used to verify attestation documents\n */\nexport const AWS_NITRO_ROOT_CERTIFICATE = `-----BEGIN CERTIFICATE-----\nMIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL\nMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD\nVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4\nMTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL\nDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb\n48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE\nh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF\nR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC\nMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW\nrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N\nIwLz3/Y=\n-----END CERTIFICATE-----`;\n\n/**\n * Expected PCR values for different environments\n */\nexport const EXPECTED_PCR_VALUES = {\n // Production PCR8 values would be set based on actual enclave builds\n // These would be configured via environment variables in production\n // Development values should be set in the application configuration, not here\n} as const;\n\n/**\n * Attestation document validation constants\n */\nexport const ATTESTATION_CONSTANTS = {\n // Maximum age of attestation document in milliseconds\n MAX_ATTESTATION_AGE: 5 * 60 * 1000, // 5 minutes\n\n // Expected digest algorithm\n EXPECTED_DIGEST: 'SHA384',\n\n // Expected module ID pattern\n MODULE_ID_PATTERN: /^i-[0-9a-f]{8,17}-enc[0-9a-f]{8,17}$/,\n\n // PCR indices that must be present\n REQUIRED_PCRS: [0, 1, 2, 8] as const,\n} as const;\n","import {\n AttestationVerificationResult,\n AttestationVerificationConfig,\n} from './types';\nimport { ATTESTATION_CONSTANTS } from './constants';\n\n// Import Evervault WASM attestation bindings\nimport init, {\n validateAttestationDocPcrs,\n PCRs,\n getUserData,\n getNonce,\n} from '@evervault/wasm-attestation-bindings';\n\n/**\n * Nitro Enclave Attestation Document Verifier\n * Uses Evervault's official WASM attestation bindings\n * Optimized for client-side usage with hex string input\n */\nexport class NitroAttestationVerifier {\n private readonly config: AttestationVerificationConfig;\n private wasmInitialized = false;\n\n constructor(config: AttestationVerificationConfig) {\n this.config = {\n strictCertValidation: true,\n maxAge: ATTESTATION_CONSTANTS.MAX_ATTESTATION_AGE,\n ...config,\n };\n }\n\n /**\n * Initialize WASM module if not already initialized\n */\n private async ensureWasmInitialized(): Promise<void> {\n if (!this.wasmInitialized) {\n try {\n // Initialize WASM module - in browser, this will automatically load the .wasm file\n await init();\n this.wasmInitialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n }\n\n /**\n * Verify an attestation document using Evervault WASM bindings\n * Accepts base64-encoded attestation document directly\n *\n * @param attestationDocBase64 - Base64-encoded attestation document\n * @param expectedChallenge - Expected challenge (ciphertext hash)\n * @param expectedNonce - Expected nonce (REQUIRED for security)\n */\n async verify(\n attestationDocBase64: string,\n expectedChallenge: string,\n expectedNonce: Uint8Array\n ): Promise<AttestationVerificationResult> {\n try {\n // Ensure WASM module is initialized\n await this.ensureWasmInitialized();\n\n // Create PCRs container with expected values\n const expectedPcrs = PCRs.empty();\n expectedPcrs.pcr8 = this.config.expectedPcr8;\n\n // Use Evervault WASM bindings to verify the attestation document (already in base64)\n const isValid = validateAttestationDocPcrs(attestationDocBase64, [\n expectedPcrs,\n ]);\n\n if (!isValid) {\n return {\n valid: false,\n errors: ['Attestation document PCR verification failed'],\n timestamp: Date.now(),\n };\n }\n\n // Verify challenge (ciphertext hash) if provided\n if (expectedChallenge) {\n try {\n const userData = getUserData(attestationDocBase64);\n if (!userData) {\n return {\n valid: false,\n errors: ['No user data found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // Convert user data to string and verify it contains the expected challenge\n const userDataString = new TextDecoder('utf-8').decode(userData);\n\n // The challenge should be the hex-encoded hash of the ciphertext\n // Verify that the attestation document's user data contains this challenge\n if (!userDataString.includes(expectedChallenge)) {\n return {\n valid: false,\n errors: [\n 'Ciphertext hash verification failed - challenge not found in attestation user data',\n ],\n timestamp: Date.now(),\n };\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify ciphertext hash: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n\n // Verify nonce (REQUIRED for security - prevents replay attacks)\n try {\n // Use WASM getNonce function to extract nonce from attestation document\n const extractedNonceRaw = getNonce(attestationDocBase64);\n\n if (!extractedNonceRaw) {\n return {\n valid: false,\n errors: ['No nonce found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // The attestation document stores the nonce as a base64-encoded string\n // We need to decode it back to the original bytes\n let extractedNonce: Uint8Array;\n try {\n // Convert to string and decode from base64 (cross-platform)\n const nonceString = new TextDecoder().decode(extractedNonceRaw);\n\n // Browser-compatible base64 decoding\n if (typeof atob !== 'undefined') {\n // Browser environment\n const binaryString = atob(nonceString);\n extractedNonce = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n extractedNonce[i] = binaryString.charCodeAt(i);\n }\n } else {\n // Node.js environment\n const decodedBuffer = Buffer.from(nonceString, 'base64');\n extractedNonce = new Uint8Array(decodedBuffer);\n }\n } catch (decodeError) {\n return {\n valid: false,\n errors: [\n `Failed to decode nonce from base64: ${decodeError instanceof Error ? decodeError.message : String(decodeError)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n // Compare nonces byte-for-byte\n if (extractedNonce.length !== expectedNonce.length) {\n return {\n valid: false,\n errors: [\n `Nonce length mismatch: expected ${expectedNonce.length} bytes, got ${extractedNonce.length} bytes`,\n ],\n timestamp: Date.now(),\n };\n }\n\n for (let i = 0; i < expectedNonce.length; i++) {\n if (extractedNonce[i] !== expectedNonce[i]) {\n return {\n valid: false,\n errors: ['Nonce verification failed - nonce mismatch'],\n timestamp: Date.now(),\n };\n }\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify nonce: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n return {\n valid: true,\n errors: [],\n timestamp: Date.now(),\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Attestation verification error: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n}\n","// Browser/Node.js compatibility\nimport { EventEmitter } from 'eventemitter3';\nimport * as ws from 'ws';\n\nconst isWindow =\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as any).window !== 'undefined';\nconst WebSocketImpl = isWindow ? (globalThis as any).WebSocket : ws.WebSocket;\n\nimport {\n BaseWebSocketMessage,\n ErrorResponse,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport {\n HandshakeV1RequestMessage,\n SignMessageV1RequestMessage,\n KeygenV1RequestMessage,\n ReceiveKeyV1RequestMessage,\n messageRegistry,\n HashAlgorithm,\n generateMlKem768Keypair,\n decapsulateMlKem768,\n encryptKeyshare,\n encryptKeygenInit,\n decryptKeygenResult,\n type SigningAlgorithmName,\n type TraceContext,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport { NitroAttestationVerifier } from './attestation';\nimport { AttestationVerificationConfig } from './attestation/types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { hexToBytes, randomBytes } from '@noble/hashes/utils.js';\nimport { either } from 'fp-ts';\nimport { SigningAlgorithm } from '@dynamic-labs-wallet/core';\n\nexport interface ForwardMPCClientOptions {\n reconnectAttempts?: number;\n reconnectInterval?: number;\n connectionTimeout?: number;\n heartbeatInterval?: number;\n attestationConfig?: AttestationVerificationConfig;\n attestationVerifier?: any; // Allow custom verifier (mock or real)\n bypassAttestation?: boolean; // Default: false. Only for testing!\n}\n\nexport interface ClientEvents {\n connected: () => void;\n disconnected: () => void;\n error: (error: Error) => void;\n message: (message: BaseWebSocketMessage) => void;\n}\n\nexport class ForwardMPCClient extends EventEmitter {\n private ws: any = null;\n private url: string;\n private options: Required<\n Omit<ForwardMPCClientOptions, 'attestationVerifier' | 'attestationConfig'>\n > & {\n attestationVerifier?: any;\n attestationConfig?: AttestationVerificationConfig;\n };\n private attestationVerifier: any | null = null; // Can be NitroAttestationVerifier or mock\n private isConnected = false;\n private messageId = 0;\n private pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timeout: NodeJS.Timeout;\n }\n >();\n private sharedSecret: Uint8Array | null = null;\n private decapsulationKey: Uint8Array | null = null;\n private connectionId: string;\n private handshakeNonce: Uint8Array | null = null;\n private attestationPromise: Promise<void> | null = null;\n\n constructor(url: string, options: ForwardMPCClientOptions = {}) {\n super();\n\n this.url = url;\n this.connectionId = ''; // Will be set by server during handshake\n this.options = {\n reconnectAttempts: options.reconnectAttempts ?? 3,\n reconnectInterval: options.reconnectInterval ?? 1000,\n connectionTimeout: options.connectionTimeout ?? 10000,\n heartbeatInterval: options.heartbeatInterval ?? 30000,\n attestationConfig: options.attestationConfig,\n attestationVerifier: options.attestationVerifier,\n bypassAttestation: options.bypassAttestation ?? false,\n };\n\n // Initialize attestation verifier - use custom verifier if provided, otherwise create from config\n if (options.attestationVerifier) {\n this.attestationVerifier = options.attestationVerifier;\n } else if (this.options.attestationConfig) {\n this.attestationVerifier = new NitroAttestationVerifier(\n this.options.attestationConfig\n );\n }\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.isConnected) {\n resolve();\n return;\n }\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n }, this.options.connectionTimeout);\n\n this.ws = new WebSocketImpl(this.url);\n\n // Handle both browser and Node.js WebSocket APIs\n if (isWindow) {\n // Browser WebSocket API\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n };\n\n this.ws.onerror = (_error: any) => {\n clearTimeout(timeout);\n this.emit('error', new Error('WebSocket error'));\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onmessage = (event: any) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n };\n } else {\n // Node.js WebSocket API\n this.ws.on('open', () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n });\n\n this.ws.on('error', (error: any) => {\n clearTimeout(timeout);\n this.emit('error', error);\n reject(error);\n });\n\n this.ws.on('message', (data: any) => {\n this.handleMessage(data.toString());\n });\n\n this.ws.on('close', () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n });\n }\n });\n }\n\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.cleanup();\n }\n\n private cleanup(): void {\n // Reject all pending requests\n for (const [, request] of this.pendingRequests) {\n clearTimeout(request.timeout);\n request.reject(new Error('Connection closed'));\n }\n this.pendingRequests.clear();\n\n // Clear sensitive cryptographic material\n if (this.sharedSecret) {\n this.sharedSecret.fill(0);\n this.sharedSecret = null;\n }\n if (this.decapsulationKey) {\n this.decapsulationKey.fill(0);\n this.decapsulationKey = null;\n }\n if (this.handshakeNonce) {\n this.handshakeNonce.fill(0);\n this.handshakeNonce = null;\n }\n\n // Clear connection ID\n this.connectionId = '';\n\n // Reset attestation state\n this.attestationPromise = null;\n }\n\n /**\n * Ensures the WebSocket connection is active and handshake is completed.\n * Automatically connects and performs handshake if needed.\n * @returns Object containing the shared secret and connection ID\n * @throws Error if connection or handshake fails\n */\n async ensureWsConnection(): Promise<{\n sharedSecret: Uint8Array;\n connectionId: string;\n }> {\n // Check if we need to connect\n if (!this.isConnected || !this.ws) {\n await this.connect();\n }\n\n // Check if we need to perform handshake\n if (!this.sharedSecret || !this.connectionId) {\n await this.handshake();\n }\n\n // Defensive check: if attestation verifier is configured, promise must exist\n if (\n this.attestationVerifier &&\n !this.options.bypassAttestation &&\n !this.attestationPromise\n ) {\n throw new Error(\n 'Attestation verifier configured but attestation was not performed'\n );\n }\n\n // Await attestation completion (throws if failed)\n if (this.attestationPromise) {\n try {\n await this.attestationPromise;\n } catch (error) {\n // Handle attestation failure by disconnecting\n // Side effect is here in the caller's context, not in the promise\n this.disconnect();\n throw error; // Re-throw for the caller\n }\n }\n\n // Final validation - should never happen but defensive check\n if (!this.sharedSecret || !this.connectionId) {\n throw new Error('Failed to establish connection and handshake');\n }\n\n return {\n sharedSecret: this.sharedSecret,\n connectionId: this.connectionId,\n };\n }\n\n private handleMessage(data: string): void {\n try {\n // Parse the raw message first to extract requestId\n const parsed = JSON.parse(data);\n const requestId = parsed.requestId;\n\n // Remove requestId from the message before deserializing\n if (requestId) {\n delete parsed.requestId;\n }\n\n // Now deserialize the message without requestId\n const message = this.deserializeMessage(JSON.stringify(parsed));\n\n // Check if this is a response to a pending request\n if (requestId && this.pendingRequests.has(requestId)) {\n const request = this.pendingRequests.get(requestId)!;\n this.pendingRequests.delete(requestId);\n clearTimeout(request.timeout);\n\n // Handle unified response format with embedded errors\n if (message.type === 'error') {\n // Legacy error response format\n const errorMsg = message as ErrorResponse;\n request.reject(new Error(errorMsg.error.message));\n } else if (message.type.endsWith('_response')) {\n // Check if the response contains an error field\n const responseData = (message as any).getData\n ? (message as any).getData()\n : message;\n if (responseData.error) {\n request.reject(new Error(responseData.error.message));\n } else {\n request.resolve(message);\n }\n } else {\n request.resolve(message);\n }\n return;\n }\n\n this.emit('message', message);\n } catch (error) {\n this.emit('error', new Error(`Failed to parse message: ${error}`));\n }\n }\n\n private sendRequest<T>(message: any): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected || !this.ws) {\n reject(new Error('Not connected'));\n return;\n }\n\n const requestId = `req_${++this.messageId}_${Date.now()}`;\n // Add requestId to message (works for both objects and Message instances)\n const messageWithId = message;\n messageWithId.requestId = requestId;\n\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(requestId);\n reject(new Error('Request timeout'));\n }, 30000); // 30 second timeout for attestation verification\n\n this.pendingRequests.set(requestId, { resolve, reject, timeout });\n\n try {\n // Use custom serializer that encodes using io-ts schemas\n const serializedMessage = this.serializeMessage(messageWithId);\n this.ws.send(serializedMessage);\n } catch (error) {\n this.pendingRequests.delete(requestId);\n clearTimeout(timeout);\n reject(error);\n }\n });\n }\n\n private serializeMessage(message: any): string {\n try {\n // If it's a Message class instance, use its encode method\n if (message && typeof message.encode === 'function') {\n const encoded = message.encode();\n // Add requestId if present\n if (message.requestId) {\n encoded.requestId = message.requestId;\n }\n return JSON.stringify(encoded);\n }\n\n // Fallback to regular JSON for other objects\n return JSON.stringify(message);\n } catch (error) {\n throw new Error(\n `Failed to serialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n private deserializeMessage(data: string): any {\n try {\n const parsed = JSON.parse(data);\n\n // Check if messageRegistry exists and has decode method\n if (!messageRegistry) {\n throw new Error('messageRegistry is undefined');\n }\n\n if (typeof messageRegistry.decode !== 'function') {\n throw new Error('messageRegistry.decode is not a function');\n }\n\n // Use message registry to decode\n const result = messageRegistry.decode(parsed);\n if (either.isLeft(result)) {\n // If registry can't decode it, return as-is (might be error response, etc.)\n return parsed;\n }\n\n return result.right;\n } catch (error) {\n throw new Error(\n `Failed to deserialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n async handshake(traceContext?: TraceContext): Promise<any> {\n // Generate ML-KEM-768 keypair and use encapsulation key as challenge\n const { encapsulationKey, decapsulationKey } = generateMlKem768Keypair();\n\n // Store decapsulation key for later use\n this.decapsulationKey = decapsulationKey;\n\n // Generate a cryptographically secure nonce for attestation\n const nonceBytes = randomBytes(32); // 256-bit nonce\n\n // Store original bytes for verification\n this.handshakeNonce = nonceBytes;\n\n const request = new HandshakeV1RequestMessage({\n challenge: encapsulationKey, // ML-KEM-768 encapsulation key (will be encoded to hex by the message class)\n nonce: nonceBytes, // User data nonce for attestation document\n traceContext,\n });\n\n const response = await this.sendRequest<any>(request);\n\n // Extract shared secret from response using ML-KEM decapsulation\n const responseData = response.getData();\n if (\n responseData.encapsulatedSharedSecret &&\n responseData.connectionId &&\n this.decapsulationKey\n ) {\n // Use the server's connection ID for consistent key derivation\n this.connectionId = responseData.connectionId;\n\n // Convert hex string back to bytes for decapsulation\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Perform ML-KEM decapsulation to derive shared secret\n this.sharedSecret = decapsulateMlKem768(\n this.decapsulationKey,\n cipherText\n );\n }\n\n // Verify attestation document (store promise for later await)\n if (\n this.attestationVerifier &&\n responseData.attestationDoc &&\n responseData.encapsulatedSharedSecret &&\n !this.options.bypassAttestation\n ) {\n // Convert hex string back to bytes for challenge verification\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Store promise - method already throws on failure\n this.attestationPromise = this.verifyAttestationDocument(\n responseData.attestationDoc,\n cipherText\n );\n }\n\n return response;\n }\n\n async signMessage(params: {\n keyshare: any; // Keyshare object from Dynamic Wallet SDK\n message: Uint8Array | string; // Message to sign (supports hex string or Uint8Array)\n relayDomain: string;\n signingAlgo: SigningAlgorithm;\n hashAlgo?: HashAlgorithm;\n derivationPath?: Uint32Array;\n tweak?: Uint8Array;\n roomUuid: string; // MPC room UUID for signing ceremony\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<any> {\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Convert hex string to Uint8Array if needed\n let messageToSign: Uint8Array;\n if (typeof params.message === 'string') {\n // Handle hex strings (with or without 0x prefix)\n const cleanHex = params.message.startsWith('0x')\n ? params.message.slice(2)\n : params.message;\n messageToSign = hexToBytes(cleanHex);\n } else {\n // Already a Uint8Array\n messageToSign = params.message;\n }\n\n // Encrypt the keyshare using AES-256-GCM\n const encryptedKeyshare = await encryptKeyshare(\n params.keyshare,\n sharedSecret,\n connectionId,\n params.signingAlgo as unknown as SigningAlgorithmName\n );\n\n const request = new SignMessageV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: params.signingAlgo,\n hashAlgo: params.hashAlgo,\n derivationPath: params.derivationPath,\n tweak: params.tweak,\n keyshare: encryptedKeyshare,\n message: messageToSign, // Always pass Uint8Array to the message class\n roomUuid: params.roomUuid,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n return this.sendRequest<any>(request);\n }\n\n /**\n * Perform MPC keygen for ECDSA and BIP340 algorithms\n * For ED25519, use sampleKey() or receiveKey() methods instead\n */\n async keygen(params: {\n keygenInit: { keygenId: string; keygenSecret: string };\n relayDomain: string;\n signingAlgo: SigningAlgorithm;\n roomUuid: string;\n numParties: number;\n threshold: number;\n keygenIds: string[];\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<{ pubkey: Uint8Array; secretShare: string }> {\n // Validate algorithm (only ECDSA and BIP340 supported)\n if (params.signingAlgo === SigningAlgorithm.ED25519) {\n throw new Error(\n 'ED25519 keygen not supported via keygen() method. Use sampleKey() or receiveKey() instead.'\n );\n }\n\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Encrypt the keygen init data\n const encryptedKeygenInit = encryptKeygenInit(\n params.keygenInit,\n sharedSecret,\n connectionId\n );\n\n // Create ECDSA or BIP340 keygen request\n // The message encoder will convert the enum to lowercase on the wire\n const request = new KeygenV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: params.signingAlgo,\n roomUuid: params.roomUuid,\n numParties: params.numParties,\n threshold: params.threshold,\n keygenInit: encryptedKeygenInit,\n keygenIds: params.keygenIds,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n // Send request and get encrypted response\n const response = await this.sendRequest<any>(request);\n const responseData = response.getData();\n\n // Decrypt the keygen result\n const keygenResult = decryptKeygenResult(\n responseData.keygenResult,\n sharedSecret,\n connectionId\n );\n\n return keygenResult;\n }\n\n /**\n * Receive an ED25519 key (one party receives the key generated by another)\n * Uses ExportableEd25519 - the receiving party gets the key sampled by another party\n */\n async receiveKey(params: {\n keygenInit: { keygenId: string; keygenSecret: string };\n relayDomain: string;\n roomUuid: string;\n numParties: number;\n threshold: number;\n keygenIds: string[];\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<{ pubkey: Uint8Array; secretShare: string }> {\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Encrypt the keygen init data\n const encryptedKeygenInit = encryptKeygenInit(\n params.keygenInit,\n sharedSecret,\n connectionId\n );\n\n // Create receiveKey request\n const request = new ReceiveKeyV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: 'ed25519',\n roomUuid: params.roomUuid,\n numParties: params.numParties,\n threshold: params.threshold,\n keygenInit: encryptedKeygenInit,\n keygenIds: params.keygenIds,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n // Send request and get encrypted response\n const response = await this.sendRequest<any>(request);\n const responseData = response.getData();\n\n // Decrypt the keygen result\n const keygenResult = decryptKeygenResult(\n responseData.keygenResult,\n sharedSecret,\n connectionId\n );\n\n return keygenResult;\n }\n\n get connected(): boolean {\n return this.isConnected;\n }\n\n /**\n * Generate a unique connection ID\n */\n\n /**\n * Verify attestation document from handshake response\n * Uses base64-encoded attestation document directly\n */\n private async verifyAttestationDocument(\n attestationDocBase64: string,\n cipherText: Uint8Array\n ): Promise<void> {\n if (!this.attestationVerifier) {\n return; // No verifier configured\n }\n\n try {\n // Generate the expected challenge (hash of cipher text from ML-KEM encapsulation)\n const challengeHash = sha256(cipherText);\n const expectedChallenge = Array.from(challengeHash)\n .map((b: number) => b.toString(16).padStart(2, '0'))\n .join('');\n\n // Verify the attestation document directly with base64 string (no conversion needed!)\n // Nonce is required for security (prevents replay attacks)\n if (!this.handshakeNonce) {\n throw new Error(\n 'Nonce not found - handshake may not have completed properly'\n );\n }\n\n const result = await this.attestationVerifier.verify(\n attestationDocBase64,\n expectedChallenge,\n this.handshakeNonce\n );\n\n if (!result.valid) {\n const errorMsg = `Attestation verification failed: ${result.errors.join(\n ', '\n )}`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n\n // Emit success event with verification result\n this.emit('message', {\n type: 'attestation-verified',\n timestamp: Date.now(),\n data: result,\n } as any);\n } catch (error) {\n const errorMsg = `Attestation verification error: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -75,6 +75,49 @@ declare class ForwardMPCClient extends EventEmitter {
|
|
|
75
75
|
userId?: string;
|
|
76
76
|
environmentId?: string;
|
|
77
77
|
}): Promise<any>;
|
|
78
|
+
/**
|
|
79
|
+
* Perform MPC keygen for ECDSA and BIP340 algorithms
|
|
80
|
+
* For ED25519, use sampleKey() or receiveKey() methods instead
|
|
81
|
+
*/
|
|
82
|
+
keygen(params: {
|
|
83
|
+
keygenInit: {
|
|
84
|
+
keygenId: string;
|
|
85
|
+
keygenSecret: string;
|
|
86
|
+
};
|
|
87
|
+
relayDomain: string;
|
|
88
|
+
signingAlgo: SigningAlgorithm;
|
|
89
|
+
roomUuid: string;
|
|
90
|
+
numParties: number;
|
|
91
|
+
threshold: number;
|
|
92
|
+
keygenIds: string[];
|
|
93
|
+
traceContext?: TraceContext;
|
|
94
|
+
userId?: string;
|
|
95
|
+
environmentId?: string;
|
|
96
|
+
}): Promise<{
|
|
97
|
+
pubkey: Uint8Array;
|
|
98
|
+
secretShare: string;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Receive an ED25519 key (one party receives the key generated by another)
|
|
102
|
+
* Uses ExportableEd25519 - the receiving party gets the key sampled by another party
|
|
103
|
+
*/
|
|
104
|
+
receiveKey(params: {
|
|
105
|
+
keygenInit: {
|
|
106
|
+
keygenId: string;
|
|
107
|
+
keygenSecret: string;
|
|
108
|
+
};
|
|
109
|
+
relayDomain: string;
|
|
110
|
+
roomUuid: string;
|
|
111
|
+
numParties: number;
|
|
112
|
+
threshold: number;
|
|
113
|
+
keygenIds: string[];
|
|
114
|
+
traceContext?: TraceContext;
|
|
115
|
+
userId?: string;
|
|
116
|
+
environmentId?: string;
|
|
117
|
+
}): Promise<{
|
|
118
|
+
pubkey: Uint8Array;
|
|
119
|
+
secretShare: string;
|
|
120
|
+
}>;
|
|
78
121
|
get connected(): boolean;
|
|
79
122
|
/**
|
|
80
123
|
* Generate a unique connection ID
|
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,49 @@ declare class ForwardMPCClient extends EventEmitter {
|
|
|
75
75
|
userId?: string;
|
|
76
76
|
environmentId?: string;
|
|
77
77
|
}): Promise<any>;
|
|
78
|
+
/**
|
|
79
|
+
* Perform MPC keygen for ECDSA and BIP340 algorithms
|
|
80
|
+
* For ED25519, use sampleKey() or receiveKey() methods instead
|
|
81
|
+
*/
|
|
82
|
+
keygen(params: {
|
|
83
|
+
keygenInit: {
|
|
84
|
+
keygenId: string;
|
|
85
|
+
keygenSecret: string;
|
|
86
|
+
};
|
|
87
|
+
relayDomain: string;
|
|
88
|
+
signingAlgo: SigningAlgorithm;
|
|
89
|
+
roomUuid: string;
|
|
90
|
+
numParties: number;
|
|
91
|
+
threshold: number;
|
|
92
|
+
keygenIds: string[];
|
|
93
|
+
traceContext?: TraceContext;
|
|
94
|
+
userId?: string;
|
|
95
|
+
environmentId?: string;
|
|
96
|
+
}): Promise<{
|
|
97
|
+
pubkey: Uint8Array;
|
|
98
|
+
secretShare: string;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Receive an ED25519 key (one party receives the key generated by another)
|
|
102
|
+
* Uses ExportableEd25519 - the receiving party gets the key sampled by another party
|
|
103
|
+
*/
|
|
104
|
+
receiveKey(params: {
|
|
105
|
+
keygenInit: {
|
|
106
|
+
keygenId: string;
|
|
107
|
+
keygenSecret: string;
|
|
108
|
+
};
|
|
109
|
+
relayDomain: string;
|
|
110
|
+
roomUuid: string;
|
|
111
|
+
numParties: number;
|
|
112
|
+
threshold: number;
|
|
113
|
+
keygenIds: string[];
|
|
114
|
+
traceContext?: TraceContext;
|
|
115
|
+
userId?: string;
|
|
116
|
+
environmentId?: string;
|
|
117
|
+
}): Promise<{
|
|
118
|
+
pubkey: Uint8Array;
|
|
119
|
+
secretShare: string;
|
|
120
|
+
}>;
|
|
78
121
|
get connected(): boolean;
|
|
79
122
|
/**
|
|
80
123
|
* Generate a unique connection ID
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from 'eventemitter3';
|
|
2
2
|
import * as ws from 'ws';
|
|
3
|
-
import { messageRegistry, generateMlKem768Keypair, HandshakeV1RequestMessage, decapsulateMlKem768, encryptKeyshare, SignMessageV1RequestMessage } from '@dynamic-labs-wallet/forward-mpc-shared';
|
|
3
|
+
import { messageRegistry, generateMlKem768Keypair, HandshakeV1RequestMessage, decapsulateMlKem768, encryptKeyshare, SignMessageV1RequestMessage, encryptKeygenInit, KeygenV1RequestMessage, decryptKeygenResult, ReceiveKeyV1RequestMessage } from '@dynamic-labs-wallet/forward-mpc-shared';
|
|
4
4
|
import init, { PCRs, validateAttestationDocPcrs, getUserData, getNonce } from '@evervault/wasm-attestation-bindings';
|
|
5
5
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
6
6
|
import { randomBytes, hexToBytes } from '@noble/hashes/utils.js';
|
|
7
7
|
import { either } from 'fp-ts';
|
|
8
|
+
import { SigningAlgorithm } from '@dynamic-labs-wallet/core';
|
|
8
9
|
|
|
9
10
|
var __defProp = Object.defineProperty;
|
|
10
11
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -464,6 +465,57 @@ var ForwardMPCClient = class extends EventEmitter {
|
|
|
464
465
|
});
|
|
465
466
|
return this.sendRequest(request);
|
|
466
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Perform MPC keygen for ECDSA and BIP340 algorithms
|
|
470
|
+
* For ED25519, use sampleKey() or receiveKey() methods instead
|
|
471
|
+
*/
|
|
472
|
+
async keygen(params) {
|
|
473
|
+
if (params.signingAlgo === SigningAlgorithm.ED25519) {
|
|
474
|
+
throw new Error("ED25519 keygen not supported via keygen() method. Use sampleKey() or receiveKey() instead.");
|
|
475
|
+
}
|
|
476
|
+
const { sharedSecret, connectionId } = await this.ensureWsConnection();
|
|
477
|
+
const encryptedKeygenInit = encryptKeygenInit(params.keygenInit, sharedSecret, connectionId);
|
|
478
|
+
const request = new KeygenV1RequestMessage({
|
|
479
|
+
relayDomain: params.relayDomain,
|
|
480
|
+
signingAlgo: params.signingAlgo,
|
|
481
|
+
roomUuid: params.roomUuid,
|
|
482
|
+
numParties: params.numParties,
|
|
483
|
+
threshold: params.threshold,
|
|
484
|
+
keygenInit: encryptedKeygenInit,
|
|
485
|
+
keygenIds: params.keygenIds,
|
|
486
|
+
traceContext: params.traceContext,
|
|
487
|
+
userId: params.userId,
|
|
488
|
+
environmentId: params.environmentId
|
|
489
|
+
});
|
|
490
|
+
const response = await this.sendRequest(request);
|
|
491
|
+
const responseData = response.getData();
|
|
492
|
+
const keygenResult = decryptKeygenResult(responseData.keygenResult, sharedSecret, connectionId);
|
|
493
|
+
return keygenResult;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Receive an ED25519 key (one party receives the key generated by another)
|
|
497
|
+
* Uses ExportableEd25519 - the receiving party gets the key sampled by another party
|
|
498
|
+
*/
|
|
499
|
+
async receiveKey(params) {
|
|
500
|
+
const { sharedSecret, connectionId } = await this.ensureWsConnection();
|
|
501
|
+
const encryptedKeygenInit = encryptKeygenInit(params.keygenInit, sharedSecret, connectionId);
|
|
502
|
+
const request = new ReceiveKeyV1RequestMessage({
|
|
503
|
+
relayDomain: params.relayDomain,
|
|
504
|
+
signingAlgo: "ed25519",
|
|
505
|
+
roomUuid: params.roomUuid,
|
|
506
|
+
numParties: params.numParties,
|
|
507
|
+
threshold: params.threshold,
|
|
508
|
+
keygenInit: encryptedKeygenInit,
|
|
509
|
+
keygenIds: params.keygenIds,
|
|
510
|
+
traceContext: params.traceContext,
|
|
511
|
+
userId: params.userId,
|
|
512
|
+
environmentId: params.environmentId
|
|
513
|
+
});
|
|
514
|
+
const response = await this.sendRequest(request);
|
|
515
|
+
const responseData = response.getData();
|
|
516
|
+
const keygenResult = decryptKeygenResult(responseData.keygenResult, sharedSecret, connectionId);
|
|
517
|
+
return keygenResult;
|
|
518
|
+
}
|
|
467
519
|
get connected() {
|
|
468
520
|
return this.isConnected;
|
|
469
521
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/attestation/constants.ts","../src/attestation/verifier.ts","../src/client.ts"],"names":["ATTESTATION_CONSTANTS","MAX_ATTESTATION_AGE","NitroAttestationVerifier","config","wasmInitialized","strictCertValidation","maxAge","ensureWasmInitialized","init","error","Error","message","verify","attestationDocBase64","expectedChallenge","expectedNonce","expectedPcrs","PCRs","empty","pcr8","expectedPcr8","isValid","validateAttestationDocPcrs","valid","errors","timestamp","Date","now","userData","getUserData","userDataString","TextDecoder","decode","includes","String","extractedNonceRaw","getNonce","extractedNonce","nonceString","atob","binaryString","Uint8Array","length","i","charCodeAt","decodedBuffer","Buffer","from","decodeError","isWindow","globalThis","window","WebSocketImpl","WebSocket","ForwardMPCClient","EventEmitter","ws","url","options","attestationVerifier","isConnected","messageId","pendingRequests","Map","sharedSecret","decapsulationKey","connectionId","handshakeNonce","attestationPromise","reconnectAttempts","reconnectInterval","connectionTimeout","heartbeatInterval","attestationConfig","bypassAttestation","connect","Promise","resolve","reject","timeout","setTimeout","onopen","clearTimeout","emit","onerror","_error","onmessage","event","handleMessage","data","onclose","cleanup","on","toString","disconnect","close","request","clear","fill","ensureWsConnection","handshake","parsed","JSON","parse","requestId","deserializeMessage","stringify","has","get","delete","type","errorMsg","endsWith","responseData","getData","sendRequest","messageWithId","set","serializedMessage","serializeMessage","send","encode","encoded","messageRegistry","result","either","isLeft","right","traceContext","encapsulationKey","generateMlKem768Keypair","nonceBytes","randomBytes","HandshakeV1RequestMessage","challenge","nonce","response","encapsulatedSharedSecret","cipherText","hexToBytes","decapsulateMlKem768","attestationDoc","verifyAttestationDocument","signMessage","params","messageToSign","cleanHex","startsWith","slice","encryptedKeyshare","encryptKeyshare","keyshare","signingAlgo","SignMessageV1RequestMessage","relayDomain","hashAlgo","derivationPath","tweak","roomUuid","userId","environmentId","connected","challengeHash","sha256","Array","map","b","padStart","join"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * AWS Nitro Security Module (NSM) Root Certificate\n * This is the official AWS root certificate used to verify attestation documents\n */\nexport const AWS_NITRO_ROOT_CERTIFICATE = `-----BEGIN CERTIFICATE-----\nMIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL\nMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD\nVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4\nMTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL\nDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb\n48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE\nh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF\nR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC\nMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW\nrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N\nIwLz3/Y=\n-----END CERTIFICATE-----`;\n\n/**\n * Expected PCR values for different environments\n */\nexport const EXPECTED_PCR_VALUES = {\n // Production PCR8 values would be set based on actual enclave builds\n // These would be configured via environment variables in production\n // Development values should be set in the application configuration, not here\n} as const;\n\n/**\n * Attestation document validation constants\n */\nexport const ATTESTATION_CONSTANTS = {\n // Maximum age of attestation document in milliseconds\n MAX_ATTESTATION_AGE: 5 * 60 * 1000, // 5 minutes\n\n // Expected digest algorithm\n EXPECTED_DIGEST: 'SHA384',\n\n // Expected module ID pattern\n MODULE_ID_PATTERN: /^i-[0-9a-f]{8,17}-enc[0-9a-f]{8,17}$/,\n\n // PCR indices that must be present\n REQUIRED_PCRS: [0, 1, 2, 8] as const,\n} as const;\n","import {\n AttestationVerificationResult,\n AttestationVerificationConfig,\n} from './types';\nimport { ATTESTATION_CONSTANTS } from './constants';\n\n// Import Evervault WASM attestation bindings\nimport init, {\n validateAttestationDocPcrs,\n PCRs,\n getUserData,\n getNonce,\n} from '@evervault/wasm-attestation-bindings';\n\n/**\n * Nitro Enclave Attestation Document Verifier\n * Uses Evervault's official WASM attestation bindings\n * Optimized for client-side usage with hex string input\n */\nexport class NitroAttestationVerifier {\n private readonly config: AttestationVerificationConfig;\n private wasmInitialized = false;\n\n constructor(config: AttestationVerificationConfig) {\n this.config = {\n strictCertValidation: true,\n maxAge: ATTESTATION_CONSTANTS.MAX_ATTESTATION_AGE,\n ...config,\n };\n }\n\n /**\n * Initialize WASM module if not already initialized\n */\n private async ensureWasmInitialized(): Promise<void> {\n if (!this.wasmInitialized) {\n try {\n // Initialize WASM module - in browser, this will automatically load the .wasm file\n await init();\n this.wasmInitialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n }\n\n /**\n * Verify an attestation document using Evervault WASM bindings\n * Accepts base64-encoded attestation document directly\n *\n * @param attestationDocBase64 - Base64-encoded attestation document\n * @param expectedChallenge - Expected challenge (ciphertext hash)\n * @param expectedNonce - Expected nonce (REQUIRED for security)\n */\n async verify(\n attestationDocBase64: string,\n expectedChallenge: string,\n expectedNonce: Uint8Array\n ): Promise<AttestationVerificationResult> {\n try {\n // Ensure WASM module is initialized\n await this.ensureWasmInitialized();\n\n // Create PCRs container with expected values\n const expectedPcrs = PCRs.empty();\n expectedPcrs.pcr8 = this.config.expectedPcr8;\n\n // Use Evervault WASM bindings to verify the attestation document (already in base64)\n const isValid = validateAttestationDocPcrs(attestationDocBase64, [\n expectedPcrs,\n ]);\n\n if (!isValid) {\n return {\n valid: false,\n errors: ['Attestation document PCR verification failed'],\n timestamp: Date.now(),\n };\n }\n\n // Verify challenge (ciphertext hash) if provided\n if (expectedChallenge) {\n try {\n const userData = getUserData(attestationDocBase64);\n if (!userData) {\n return {\n valid: false,\n errors: ['No user data found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // Convert user data to string and verify it contains the expected challenge\n const userDataString = new TextDecoder('utf-8').decode(userData);\n\n // The challenge should be the hex-encoded hash of the ciphertext\n // Verify that the attestation document's user data contains this challenge\n if (!userDataString.includes(expectedChallenge)) {\n return {\n valid: false,\n errors: [\n 'Ciphertext hash verification failed - challenge not found in attestation user data',\n ],\n timestamp: Date.now(),\n };\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify ciphertext hash: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n\n // Verify nonce (REQUIRED for security - prevents replay attacks)\n try {\n // Use WASM getNonce function to extract nonce from attestation document\n const extractedNonceRaw = getNonce(attestationDocBase64);\n\n if (!extractedNonceRaw) {\n return {\n valid: false,\n errors: ['No nonce found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // The attestation document stores the nonce as a base64-encoded string\n // We need to decode it back to the original bytes\n let extractedNonce: Uint8Array;\n try {\n // Convert to string and decode from base64 (cross-platform)\n const nonceString = new TextDecoder().decode(extractedNonceRaw);\n\n // Browser-compatible base64 decoding\n if (typeof atob !== 'undefined') {\n // Browser environment\n const binaryString = atob(nonceString);\n extractedNonce = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n extractedNonce[i] = binaryString.charCodeAt(i);\n }\n } else {\n // Node.js environment\n const decodedBuffer = Buffer.from(nonceString, 'base64');\n extractedNonce = new Uint8Array(decodedBuffer);\n }\n } catch (decodeError) {\n return {\n valid: false,\n errors: [\n `Failed to decode nonce from base64: ${decodeError instanceof Error ? decodeError.message : String(decodeError)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n // Compare nonces byte-for-byte\n if (extractedNonce.length !== expectedNonce.length) {\n return {\n valid: false,\n errors: [\n `Nonce length mismatch: expected ${expectedNonce.length} bytes, got ${extractedNonce.length} bytes`,\n ],\n timestamp: Date.now(),\n };\n }\n\n for (let i = 0; i < expectedNonce.length; i++) {\n if (extractedNonce[i] !== expectedNonce[i]) {\n return {\n valid: false,\n errors: ['Nonce verification failed - nonce mismatch'],\n timestamp: Date.now(),\n };\n }\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify nonce: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n return {\n valid: true,\n errors: [],\n timestamp: Date.now(),\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Attestation verification error: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n}\n","// Browser/Node.js compatibility\nimport { EventEmitter } from 'eventemitter3';\nimport * as ws from 'ws';\n\nconst isWindow =\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as any).window !== 'undefined';\nconst WebSocketImpl = isWindow ? (globalThis as any).WebSocket : ws.WebSocket;\n\nimport {\n BaseWebSocketMessage,\n ErrorResponse,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport {\n HandshakeV1RequestMessage,\n SignMessageV1RequestMessage,\n messageRegistry,\n HashAlgorithm,\n generateMlKem768Keypair,\n decapsulateMlKem768,\n encryptKeyshare,\n type SigningAlgorithmName,\n type TraceContext,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport { NitroAttestationVerifier } from './attestation';\nimport { AttestationVerificationConfig } from './attestation/types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { hexToBytes, randomBytes } from '@noble/hashes/utils.js';\nimport { either } from 'fp-ts';\nimport { SigningAlgorithm } from '@dynamic-labs-wallet/core';\n\nexport interface ForwardMPCClientOptions {\n reconnectAttempts?: number;\n reconnectInterval?: number;\n connectionTimeout?: number;\n heartbeatInterval?: number;\n attestationConfig?: AttestationVerificationConfig;\n attestationVerifier?: any; // Allow custom verifier (mock or real)\n bypassAttestation?: boolean; // Default: false. Only for testing!\n}\n\nexport interface ClientEvents {\n connected: () => void;\n disconnected: () => void;\n error: (error: Error) => void;\n message: (message: BaseWebSocketMessage) => void;\n}\n\nexport class ForwardMPCClient extends EventEmitter {\n private ws: any = null;\n private url: string;\n private options: Required<\n Omit<ForwardMPCClientOptions, 'attestationVerifier' | 'attestationConfig'>\n > & {\n attestationVerifier?: any;\n attestationConfig?: AttestationVerificationConfig;\n };\n private attestationVerifier: any | null = null; // Can be NitroAttestationVerifier or mock\n private isConnected = false;\n private messageId = 0;\n private pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timeout: NodeJS.Timeout;\n }\n >();\n private sharedSecret: Uint8Array | null = null;\n private decapsulationKey: Uint8Array | null = null;\n private connectionId: string;\n private handshakeNonce: Uint8Array | null = null;\n private attestationPromise: Promise<void> | null = null;\n\n constructor(url: string, options: ForwardMPCClientOptions = {}) {\n super();\n\n this.url = url;\n this.connectionId = ''; // Will be set by server during handshake\n this.options = {\n reconnectAttempts: options.reconnectAttempts ?? 3,\n reconnectInterval: options.reconnectInterval ?? 1000,\n connectionTimeout: options.connectionTimeout ?? 10000,\n heartbeatInterval: options.heartbeatInterval ?? 30000,\n attestationConfig: options.attestationConfig,\n attestationVerifier: options.attestationVerifier,\n bypassAttestation: options.bypassAttestation ?? false,\n };\n\n // Initialize attestation verifier - use custom verifier if provided, otherwise create from config\n if (options.attestationVerifier) {\n this.attestationVerifier = options.attestationVerifier;\n } else if (this.options.attestationConfig) {\n this.attestationVerifier = new NitroAttestationVerifier(\n this.options.attestationConfig\n );\n }\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.isConnected) {\n resolve();\n return;\n }\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n }, this.options.connectionTimeout);\n\n this.ws = new WebSocketImpl(this.url);\n\n // Handle both browser and Node.js WebSocket APIs\n if (isWindow) {\n // Browser WebSocket API\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n };\n\n this.ws.onerror = (_error: any) => {\n clearTimeout(timeout);\n this.emit('error', new Error('WebSocket error'));\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onmessage = (event: any) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n };\n } else {\n // Node.js WebSocket API\n this.ws.on('open', () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n });\n\n this.ws.on('error', (error: any) => {\n clearTimeout(timeout);\n this.emit('error', error);\n reject(error);\n });\n\n this.ws.on('message', (data: any) => {\n this.handleMessage(data.toString());\n });\n\n this.ws.on('close', () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n });\n }\n });\n }\n\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.cleanup();\n }\n\n private cleanup(): void {\n // Reject all pending requests\n for (const [, request] of this.pendingRequests) {\n clearTimeout(request.timeout);\n request.reject(new Error('Connection closed'));\n }\n this.pendingRequests.clear();\n\n // Clear sensitive cryptographic material\n if (this.sharedSecret) {\n this.sharedSecret.fill(0);\n this.sharedSecret = null;\n }\n if (this.decapsulationKey) {\n this.decapsulationKey.fill(0);\n this.decapsulationKey = null;\n }\n if (this.handshakeNonce) {\n this.handshakeNonce.fill(0);\n this.handshakeNonce = null;\n }\n\n // Clear connection ID\n this.connectionId = '';\n\n // Reset attestation state\n this.attestationPromise = null;\n }\n\n /**\n * Ensures the WebSocket connection is active and handshake is completed.\n * Automatically connects and performs handshake if needed.\n * @returns Object containing the shared secret and connection ID\n * @throws Error if connection or handshake fails\n */\n async ensureWsConnection(): Promise<{\n sharedSecret: Uint8Array;\n connectionId: string;\n }> {\n // Check if we need to connect\n if (!this.isConnected || !this.ws) {\n await this.connect();\n }\n\n // Check if we need to perform handshake\n if (!this.sharedSecret || !this.connectionId) {\n await this.handshake();\n }\n\n // Defensive check: if attestation verifier is configured, promise must exist\n if (\n this.attestationVerifier &&\n !this.options.bypassAttestation &&\n !this.attestationPromise\n ) {\n throw new Error(\n 'Attestation verifier configured but attestation was not performed'\n );\n }\n\n // Await attestation completion (throws if failed)\n if (this.attestationPromise) {\n try {\n await this.attestationPromise;\n } catch (error) {\n // Handle attestation failure by disconnecting\n // Side effect is here in the caller's context, not in the promise\n this.disconnect();\n throw error; // Re-throw for the caller\n }\n }\n\n // Final validation - should never happen but defensive check\n if (!this.sharedSecret || !this.connectionId) {\n throw new Error('Failed to establish connection and handshake');\n }\n\n return {\n sharedSecret: this.sharedSecret,\n connectionId: this.connectionId,\n };\n }\n\n private handleMessage(data: string): void {\n try {\n // Parse the raw message first to extract requestId\n const parsed = JSON.parse(data);\n const requestId = parsed.requestId;\n\n // Remove requestId from the message before deserializing\n if (requestId) {\n delete parsed.requestId;\n }\n\n // Now deserialize the message without requestId\n const message = this.deserializeMessage(JSON.stringify(parsed));\n\n // Check if this is a response to a pending request\n if (requestId && this.pendingRequests.has(requestId)) {\n const request = this.pendingRequests.get(requestId)!;\n this.pendingRequests.delete(requestId);\n clearTimeout(request.timeout);\n\n // Handle unified response format with embedded errors\n if (message.type === 'error') {\n // Legacy error response format\n const errorMsg = message as ErrorResponse;\n request.reject(new Error(errorMsg.error.message));\n } else if (message.type.endsWith('_response')) {\n // Check if the response contains an error field\n const responseData = (message as any).getData\n ? (message as any).getData()\n : message;\n if (responseData.error) {\n request.reject(new Error(responseData.error.message));\n } else {\n request.resolve(message);\n }\n } else {\n request.resolve(message);\n }\n return;\n }\n\n this.emit('message', message);\n } catch (error) {\n this.emit('error', new Error(`Failed to parse message: ${error}`));\n }\n }\n\n private sendRequest<T>(message: any): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected || !this.ws) {\n reject(new Error('Not connected'));\n return;\n }\n\n const requestId = `req_${++this.messageId}_${Date.now()}`;\n // Add requestId to message (works for both objects and Message instances)\n const messageWithId = message;\n messageWithId.requestId = requestId;\n\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(requestId);\n reject(new Error('Request timeout'));\n }, 30000); // 30 second timeout for attestation verification\n\n this.pendingRequests.set(requestId, { resolve, reject, timeout });\n\n try {\n // Use custom serializer that encodes using io-ts schemas\n const serializedMessage = this.serializeMessage(messageWithId);\n this.ws.send(serializedMessage);\n } catch (error) {\n this.pendingRequests.delete(requestId);\n clearTimeout(timeout);\n reject(error);\n }\n });\n }\n\n private serializeMessage(message: any): string {\n try {\n // If it's a Message class instance, use its encode method\n if (message && typeof message.encode === 'function') {\n const encoded = message.encode();\n // Add requestId if present\n if (message.requestId) {\n encoded.requestId = message.requestId;\n }\n return JSON.stringify(encoded);\n }\n\n // Fallback to regular JSON for other objects\n return JSON.stringify(message);\n } catch (error) {\n throw new Error(\n `Failed to serialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n private deserializeMessage(data: string): any {\n try {\n const parsed = JSON.parse(data);\n\n // Check if messageRegistry exists and has decode method\n if (!messageRegistry) {\n throw new Error('messageRegistry is undefined');\n }\n\n if (typeof messageRegistry.decode !== 'function') {\n throw new Error('messageRegistry.decode is not a function');\n }\n\n // Use message registry to decode\n const result = messageRegistry.decode(parsed);\n if (either.isLeft(result)) {\n // If registry can't decode it, return as-is (might be error response, etc.)\n return parsed;\n }\n\n return result.right;\n } catch (error) {\n throw new Error(\n `Failed to deserialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n async handshake(traceContext?: TraceContext): Promise<any> {\n // Generate ML-KEM-768 keypair and use encapsulation key as challenge\n const { encapsulationKey, decapsulationKey } = generateMlKem768Keypair();\n\n // Store decapsulation key for later use\n this.decapsulationKey = decapsulationKey;\n\n // Generate a cryptographically secure nonce for attestation\n const nonceBytes = randomBytes(32); // 256-bit nonce\n\n // Store original bytes for verification\n this.handshakeNonce = nonceBytes;\n\n const request = new HandshakeV1RequestMessage({\n challenge: encapsulationKey, // ML-KEM-768 encapsulation key (will be encoded to hex by the message class)\n nonce: nonceBytes, // User data nonce for attestation document\n traceContext,\n });\n\n const response = await this.sendRequest<any>(request);\n\n // Extract shared secret from response using ML-KEM decapsulation\n const responseData = response.getData();\n if (\n responseData.encapsulatedSharedSecret &&\n responseData.connectionId &&\n this.decapsulationKey\n ) {\n // Use the server's connection ID for consistent key derivation\n this.connectionId = responseData.connectionId;\n\n // Convert hex string back to bytes for decapsulation\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Perform ML-KEM decapsulation to derive shared secret\n this.sharedSecret = decapsulateMlKem768(\n this.decapsulationKey,\n cipherText\n );\n }\n\n // Verify attestation document (store promise for later await)\n if (\n this.attestationVerifier &&\n responseData.attestationDoc &&\n responseData.encapsulatedSharedSecret &&\n !this.options.bypassAttestation\n ) {\n // Convert hex string back to bytes for challenge verification\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Store promise - method already throws on failure\n this.attestationPromise = this.verifyAttestationDocument(\n responseData.attestationDoc,\n cipherText\n );\n }\n\n return response;\n }\n\n async signMessage(params: {\n keyshare: any; // Keyshare object from Dynamic Wallet SDK\n message: Uint8Array | string; // Message to sign (supports hex string or Uint8Array)\n relayDomain: string;\n signingAlgo: SigningAlgorithm;\n hashAlgo?: HashAlgorithm;\n derivationPath?: Uint32Array;\n tweak?: Uint8Array;\n roomUuid: string; // MPC room UUID for signing ceremony\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<any> {\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Convert hex string to Uint8Array if needed\n let messageToSign: Uint8Array;\n if (typeof params.message === 'string') {\n // Handle hex strings (with or without 0x prefix)\n const cleanHex = params.message.startsWith('0x')\n ? params.message.slice(2)\n : params.message;\n messageToSign = hexToBytes(cleanHex);\n } else {\n // Already a Uint8Array\n messageToSign = params.message;\n }\n\n // Encrypt the keyshare using AES-256-GCM\n const encryptedKeyshare = await encryptKeyshare(\n params.keyshare,\n sharedSecret,\n connectionId,\n params.signingAlgo as unknown as SigningAlgorithmName\n );\n\n const request = new SignMessageV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: params.signingAlgo,\n hashAlgo: params.hashAlgo,\n derivationPath: params.derivationPath,\n tweak: params.tweak,\n keyshare: encryptedKeyshare,\n message: messageToSign, // Always pass Uint8Array to the message class\n roomUuid: params.roomUuid,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n return this.sendRequest<any>(request);\n }\n\n get connected(): boolean {\n return this.isConnected;\n }\n\n /**\n * Generate a unique connection ID\n */\n\n /**\n * Verify attestation document from handshake response\n * Uses base64-encoded attestation document directly\n */\n private async verifyAttestationDocument(\n attestationDocBase64: string,\n cipherText: Uint8Array\n ): Promise<void> {\n if (!this.attestationVerifier) {\n return; // No verifier configured\n }\n\n try {\n // Generate the expected challenge (hash of cipher text from ML-KEM encapsulation)\n const challengeHash = sha256(cipherText);\n const expectedChallenge = Array.from(challengeHash)\n .map((b: number) => b.toString(16).padStart(2, '0'))\n .join('');\n\n // Verify the attestation document directly with base64 string (no conversion needed!)\n // Nonce is required for security (prevents replay attacks)\n if (!this.handshakeNonce) {\n throw new Error(\n 'Nonce not found - handshake may not have completed properly'\n );\n }\n\n const result = await this.attestationVerifier.verify(\n attestationDocBase64,\n expectedChallenge,\n this.handshakeNonce\n );\n\n if (!result.valid) {\n const errorMsg = `Attestation verification failed: ${result.errors.join(\n ', '\n )}`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n\n // Emit success event with verification result\n this.emit('message', {\n type: 'attestation-verified',\n timestamp: Date.now(),\n data: result,\n } as any);\n } catch (error) {\n const errorMsg = `Attestation verification error: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/attestation/constants.ts","../src/attestation/verifier.ts","../src/client.ts"],"names":["ATTESTATION_CONSTANTS","MAX_ATTESTATION_AGE","NitroAttestationVerifier","config","wasmInitialized","strictCertValidation","maxAge","ensureWasmInitialized","init","error","Error","message","verify","attestationDocBase64","expectedChallenge","expectedNonce","expectedPcrs","PCRs","empty","pcr8","expectedPcr8","isValid","validateAttestationDocPcrs","valid","errors","timestamp","Date","now","userData","getUserData","userDataString","TextDecoder","decode","includes","String","extractedNonceRaw","getNonce","extractedNonce","nonceString","atob","binaryString","Uint8Array","length","i","charCodeAt","decodedBuffer","Buffer","from","decodeError","isWindow","globalThis","window","WebSocketImpl","WebSocket","ForwardMPCClient","EventEmitter","ws","url","options","attestationVerifier","isConnected","messageId","pendingRequests","Map","sharedSecret","decapsulationKey","connectionId","handshakeNonce","attestationPromise","reconnectAttempts","reconnectInterval","connectionTimeout","heartbeatInterval","attestationConfig","bypassAttestation","connect","Promise","resolve","reject","timeout","setTimeout","onopen","clearTimeout","emit","onerror","_error","onmessage","event","handleMessage","data","onclose","cleanup","on","toString","disconnect","close","request","clear","fill","ensureWsConnection","handshake","parsed","JSON","parse","requestId","deserializeMessage","stringify","has","get","delete","type","errorMsg","endsWith","responseData","getData","sendRequest","messageWithId","set","serializedMessage","serializeMessage","send","encode","encoded","messageRegistry","result","either","isLeft","right","traceContext","encapsulationKey","generateMlKem768Keypair","nonceBytes","randomBytes","HandshakeV1RequestMessage","challenge","nonce","response","encapsulatedSharedSecret","cipherText","hexToBytes","decapsulateMlKem768","attestationDoc","verifyAttestationDocument","signMessage","params","messageToSign","cleanHex","startsWith","slice","encryptedKeyshare","encryptKeyshare","keyshare","signingAlgo","SignMessageV1RequestMessage","relayDomain","hashAlgo","derivationPath","tweak","roomUuid","userId","environmentId","keygen","SigningAlgorithm","ED25519","encryptedKeygenInit","encryptKeygenInit","keygenInit","KeygenV1RequestMessage","numParties","threshold","keygenIds","keygenResult","decryptKeygenResult","receiveKey","ReceiveKeyV1RequestMessage","connected","challengeHash","sha256","Array","map","b","padStart","join"],"mappings":";;;;;;;;;;;;;AA+BO,IAAMA,qBAAAA,GAAwB;;AAEnCC,EAAAA,mBAAAA,EAAqB,IAAI,EAAA,GAAK,GAUhC,CAAA;ACxBO,IAAMC,2BAAN,MAAMA;EAfb;;;AAgBmBC,EAAAA,MAAAA;EACTC,eAAAA,GAAkB,KAAA;AAE1B,EAAA,WAAA,CAAYD,MAAAA,EAAuC;AACjD,IAAA,IAAA,CAAKA,MAAAA,GAAS;MACZE,oBAAAA,EAAsB,IAAA;AACtBC,MAAAA,MAAAA,EAAQN,qBAAAA,CAAsBC,mBAAAA;MAC9B,GAAGE;AACL,KAAA;AACF,EAAA;;;;AAKA,EAAA,MAAcI,qBAAAA,GAAuC;AACnD,IAAA,IAAI,CAAC,KAAKH,eAAAA,EAAiB;AACzB,MAAA,IAAI;AAEF,QAAA,MAAMI,IAAAA,EAAAA;AACN,QAAA,IAAA,CAAKJ,eAAAA,GAAkB,IAAA;AACzB,MAAA,CAAA,CAAA,OAASK,KAAAA,EAAO;AACd,QAAA,MAAM,IAAIC,MACR,CAAA,kCAAA,EAAqCD,KAAAA,YAAiBC,QAAQD,KAAAA,CAAME,OAAAA,GAAU,eAAA,CAAA,CAAiB,CAAA;AAEnG,MAAA;AACF,IAAA;AACF,EAAA;;;;;;;;;EAUA,MAAMC,MAAAA,CACJC,oBAAAA,EACAC,iBAAAA,EACAC,aAAAA,EACwC;AACxC,IAAA,IAAI;AAEF,MAAA,MAAM,KAAKR,qBAAAA,EAAqB;AAGhC,MAAA,MAAMS,YAAAA,GAAeC,KAAKC,KAAAA,EAAK;AAC/BF,MAAAA,YAAAA,CAAaG,IAAAA,GAAO,KAAKhB,MAAAA,CAAOiB,YAAAA;AAGhC,MAAA,MAAMC,OAAAA,GAAUC,2BAA2BT,oBAAAA,EAAsB;AAC/DG,QAAAA;AACD,OAAA,CAAA;AAED,MAAA,IAAI,CAACK,OAAAA,EAAS;AACZ,QAAA,OAAO;UACLE,KAAAA,EAAO,KAAA;UACPC,MAAAA,EAAQ;AAAC,YAAA;;AACTC,UAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,SAAA;AACF,MAAA;AAGA,MAAA,IAAIb,iBAAAA,EAAmB;AACrB,QAAA,IAAI;AACF,UAAA,MAAMc,QAAAA,GAAWC,YAAYhB,oBAAAA,CAAAA;AAC7B,UAAA,IAAI,CAACe,QAAAA,EAAU;AACb,YAAA,OAAO;cACLL,KAAAA,EAAO,KAAA;cACPC,MAAAA,EAAQ;AAAC,gBAAA;;AACTC,cAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,aAAA;AACF,UAAA;AAGA,UAAA,MAAMG,iBAAiB,IAAIC,WAAAA,CAAY,OAAA,CAAA,CAASC,OAAOJ,QAAAA,CAAAA;AAIvD,UAAA,IAAI,CAACE,cAAAA,CAAeG,QAAAA,CAASnB,iBAAAA,CAAAA,EAAoB;AAC/C,YAAA,OAAO;cACLS,KAAAA,EAAO,KAAA;cACPC,MAAAA,EAAQ;AACN,gBAAA;;AAEFC,cAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,aAAA;AACF,UAAA;AACF,QAAA,CAAA,CAAA,OAASlB,KAAAA,EAAO;AACd,UAAA,OAAO;YACLc,KAAAA,EAAO,KAAA;YACPC,MAAAA,EAAQ;AACN,cAAA,CAAA,6CAAA,EAAgDf,iBAAiBC,KAAAA,GAAQD,KAAAA,CAAME,OAAAA,GAAUuB,MAAAA,CAAOzB,KAAAA,CAAAA,CAAAA;;AAElGgB,YAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,WAAA;AACF,QAAA;AACF,MAAA;AAGA,MAAA,IAAI;AAEF,QAAA,MAAMQ,iBAAAA,GAAoBC,SAASvB,oBAAAA,CAAAA;AAEnC,QAAA,IAAI,CAACsB,iBAAAA,EAAmB;AACtB,UAAA,OAAO;YACLZ,KAAAA,EAAO,KAAA;YACPC,MAAAA,EAAQ;AAAC,cAAA;;AACTC,YAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,WAAA;AACF,QAAA;AAIA,QAAA,IAAIU,cAAAA;AACJ,QAAA,IAAI;AAEF,UAAA,MAAMC,WAAAA,GAAc,IAAIP,WAAAA,EAAAA,CAAcC,OAAOG,iBAAAA,CAAAA;AAG7C,UAAA,IAAI,OAAOI,SAAS,WAAA,EAAa;AAE/B,YAAA,MAAMC,YAAAA,GAAeD,KAAKD,WAAAA,CAAAA;AAC1BD,YAAAA,cAAAA,GAAiB,IAAII,UAAAA,CAAWD,YAAAA,CAAaE,MAAM,CAAA;AACnD,YAAA,KAAA,IAASC,CAAAA,GAAI,CAAA,EAAGA,CAAAA,GAAIH,YAAAA,CAAaE,QAAQC,CAAAA,EAAAA,EAAK;AAC5CN,cAAAA,cAAAA,CAAeM,CAAAA,CAAAA,GAAKH,YAAAA,CAAaI,UAAAA,CAAWD,CAAAA,CAAAA;AAC9C,YAAA;UACF,CAAA,MAAO;AAEL,YAAA,MAAME,aAAAA,GAAgBC,MAAAA,CAAOC,IAAAA,CAAKT,WAAAA,EAAa,QAAA,CAAA;AAC/CD,YAAAA,cAAAA,GAAiB,IAAII,WAAWI,aAAAA,CAAAA;AAClC,UAAA;AACF,QAAA,CAAA,CAAA,OAASG,WAAAA,EAAa;AACpB,UAAA,OAAO;YACLzB,KAAAA,EAAO,KAAA;YACPC,MAAAA,EAAQ;AACN,cAAA,CAAA,oCAAA,EAAuCwB,uBAAuBtC,KAAAA,GAAQsC,WAAAA,CAAYrC,OAAAA,GAAUuB,MAAAA,CAAOc,WAAAA,CAAAA,CAAAA;;AAErGvB,YAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,WAAA;AACF,QAAA;AAGA,QAAA,IAAIU,cAAAA,CAAeK,MAAAA,KAAW3B,aAAAA,CAAc2B,MAAAA,EAAQ;AAClD,UAAA,OAAO;YACLnB,KAAAA,EAAO,KAAA;YACPC,MAAAA,EAAQ;AACN,cAAA,CAAA,gCAAA,EAAmCT,aAAAA,CAAc2B,MAAM,CAAA,YAAA,EAAeL,cAAAA,CAAeK,MAAM,CAAA,MAAA;;AAE7FjB,YAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,WAAA;AACF,QAAA;AAEA,QAAA,KAAA,IAASgB,CAAAA,GAAI,CAAA,EAAGA,CAAAA,GAAI5B,aAAAA,CAAc2B,QAAQC,CAAAA,EAAAA,EAAK;AAC7C,UAAA,IAAIN,cAAAA,CAAeM,CAAAA,CAAAA,KAAO5B,aAAAA,CAAc4B,CAAAA,CAAAA,EAAI;AAC1C,YAAA,OAAO;cACLpB,KAAAA,EAAO,KAAA;cACPC,MAAAA,EAAQ;AAAC,gBAAA;;AACTC,cAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,aAAA;AACF,UAAA;AACF,QAAA;AACF,MAAA,CAAA,CAAA,OAASlB,KAAAA,EAAO;AACd,QAAA,OAAO;UACLc,KAAAA,EAAO,KAAA;UACPC,MAAAA,EAAQ;AACN,YAAA,CAAA,mCAAA,EAAsCf,iBAAiBC,KAAAA,GAAQD,KAAAA,CAAME,OAAAA,GAAUuB,MAAAA,CAAOzB,KAAAA,CAAAA,CAAAA;;AAExFgB,UAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,SAAA;AACF,MAAA;AAEA,MAAA,OAAO;QACLJ,KAAAA,EAAO,IAAA;AACPC,QAAAA,MAAAA,EAAQ,EAAA;AACRC,QAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,OAAA;AACF,IAAA,CAAA,CAAA,OAASlB,KAAAA,EAAO;AACd,MAAA,OAAO;QACLc,KAAAA,EAAO,KAAA;QACPC,MAAAA,EAAQ;AACN,UAAA,CAAA,gCAAA,EAAmCf,iBAAiBC,KAAAA,GAAQD,KAAAA,CAAME,OAAAA,GAAUuB,MAAAA,CAAOzB,KAAAA,CAAAA,CAAAA;;AAErFgB,QAAAA,SAAAA,EAAWC,KAAKC,GAAAA;AAClB,OAAA;AACF,IAAA;AACF,EAAA;AACF,CAAA;AC3MA,IAAMsB,WACJ,OAAOC,UAAAA,KAAe,WAAA,IACtB,OAAQA,WAAmBC,MAAAA,KAAW,WAAA;AACxC,IAAMC,aAAAA,GAAgBH,QAAAA,GAAYC,UAAAA,CAAmBG,SAAAA,GAAeA,EAAAA,CAAAA,SAAAA;AA6C7D,IAAMC,gBAAAA,GAAN,cAA+BC,YAAAA,CAAAA;EApDtC;;;EAqDUC,EAAAA,GAAU,IAAA;AACVC,EAAAA,GAAAA;AACAC,EAAAA,OAAAA;EAMAC,mBAAAA,GAAkC,IAAA;EAClCC,WAAAA,GAAc,KAAA;EACdC,SAAAA,GAAY,CAAA;AACZC,EAAAA,eAAAA,uBAAsBC,GAAAA,EAAAA;EAQtBC,YAAAA,GAAkC,IAAA;EAClCC,gBAAAA,GAAsC,IAAA;AACtCC,EAAAA,YAAAA;EACAC,cAAAA,GAAoC,IAAA;EACpCC,kBAAAA,GAA2C,IAAA;EAEnD,WAAA,CAAYX,GAAAA,EAAaC,OAAAA,GAAmC,EAAC,EAAG;AAC9D,IAAA,KAAA,EAAK;AAEL,IAAA,IAAA,CAAKD,GAAAA,GAAMA,GAAAA;AACX,IAAA,IAAA,CAAKS,YAAAA,GAAe,EAAA;AACpB,IAAA,IAAA,CAAKR,OAAAA,GAAU;AACbW,MAAAA,iBAAAA,EAAmBX,QAAQW,iBAAAA,IAAqB,CAAA;AAChDC,MAAAA,iBAAAA,EAAmBZ,QAAQY,iBAAAA,IAAqB,GAAA;AAChDC,MAAAA,iBAAAA,EAAmBb,QAAQa,iBAAAA,IAAqB,GAAA;AAChDC,MAAAA,iBAAAA,EAAmBd,QAAQc,iBAAAA,IAAqB,GAAA;AAChDC,MAAAA,iBAAAA,EAAmBf,OAAAA,CAAQe,iBAAAA;AAC3Bd,MAAAA,mBAAAA,EAAqBD,OAAAA,CAAQC,mBAAAA;AAC7Be,MAAAA,iBAAAA,EAAmBhB,QAAQgB,iBAAAA,IAAqB;AAClD,KAAA;AAGA,IAAA,IAAIhB,QAAQC,mBAAAA,EAAqB;AAC/B,MAAA,IAAA,CAAKA,sBAAsBD,OAAAA,CAAQC,mBAAAA;IACrC,CAAA,MAAA,IAAW,IAAA,CAAKD,QAAQe,iBAAAA,EAAmB;AACzC,MAAA,IAAA,CAAKd,mBAAAA,GAAsB,IAAIzD,wBAAAA,CAC7B,IAAA,CAAKwD,QAAQe,iBAAiB,CAAA;AAElC,IAAA;AACF,EAAA;AAEA,EAAA,MAAME,OAAAA,GAAyB;AAC7B,IAAA,OAAO,IAAIC,OAAAA,CAAQ,CAACC,OAAAA,EAASC,MAAAA,KAAAA;AAC3B,MAAA,IAAI,KAAKlB,WAAAA,EAAa;AACpBiB,QAAAA,OAAAA,EAAAA;AACA,QAAA;AACF,MAAA;AAEA,MAAA,MAAME,OAAAA,GAAUC,WAAW,MAAA;AACzBF,QAAAA,MAAAA,CAAO,IAAIpE,KAAAA,CAAM,oBAAA,CAAA,CAAA;MACnB,CAAA,EAAG,IAAA,CAAKgD,QAAQa,iBAAiB,CAAA;AAEjC,MAAA,IAAA,CAAKf,EAAAA,GAAK,IAAIJ,aAAAA,CAAc,IAAA,CAAKK,GAAG,CAAA;AAGpC,MAAA,IAAIR,QAAAA,EAAU;AAEZ,QAAA,IAAA,CAAKO,EAAAA,CAAGyB,SAAS,MAAA;AACfC,UAAAA,YAAAA,CAAaH,OAAAA,CAAAA;AACb,UAAA,IAAA,CAAKnB,WAAAA,GAAc,IAAA;AACnB,UAAA,IAAA,CAAKuB,KAAK,WAAA,CAAA;AACVN,UAAAA,OAAAA,EAAAA;AACF,QAAA,CAAA;AAEA,QAAA,IAAA,CAAKrB,EAAAA,CAAG4B,OAAAA,GAAU,CAACC,MAAAA,KAAAA;AACjBH,UAAAA,YAAAA,CAAaH,OAAAA,CAAAA;AACb,UAAA,IAAA,CAAKI,IAAAA,CAAK,OAAA,EAAS,IAAIzE,KAAAA,CAAM,iBAAA,CAAA,CAAA;AAC7BoE,UAAAA,MAAAA,CAAO,IAAIpE,KAAAA,CAAM,iBAAA,CAAA,CAAA;AACnB,QAAA,CAAA;AAEA,QAAA,IAAA,CAAK8C,EAAAA,CAAG8B,SAAAA,GAAY,CAACC,KAAAA,KAAAA;AACnB,UAAA,IAAA,CAAKC,aAAAA,CAAcD,MAAME,IAAI,CAAA;AAC/B,QAAA,CAAA;AAEA,QAAA,IAAA,CAAKjC,EAAAA,CAAGkC,UAAU,MAAA;AAChB,UAAA,IAAA,CAAK9B,WAAAA,GAAc,KAAA;AACnB,UAAA,IAAA,CAAKuB,KAAK,cAAA,CAAA;AACV,UAAA,IAAA,CAAKQ,OAAAA,EAAO;AACd,QAAA,CAAA;MACF,CAAA,MAAO;AAEL,QAAA,IAAA,CAAKnC,EAAAA,CAAGoC,EAAAA,CAAG,MAAA,EAAQ,MAAA;AACjBV,UAAAA,YAAAA,CAAaH,OAAAA,CAAAA;AACb,UAAA,IAAA,CAAKnB,WAAAA,GAAc,IAAA;AACnB,UAAA,IAAA,CAAKuB,KAAK,WAAA,CAAA;AACVN,UAAAA,OAAAA,EAAAA;QACF,CAAA,CAAA;AAEA,QAAA,IAAA,CAAKrB,EAAAA,CAAGoC,EAAAA,CAAG,OAAA,EAAS,CAACnF,KAAAA,KAAAA;AACnByE,UAAAA,YAAAA,CAAaH,OAAAA,CAAAA;AACb,UAAA,IAAA,CAAKI,IAAAA,CAAK,SAAS1E,KAAAA,CAAAA;AACnBqE,UAAAA,MAAAA,CAAOrE,KAAAA,CAAAA;QACT,CAAA,CAAA;AAEA,QAAA,IAAA,CAAK+C,EAAAA,CAAGoC,EAAAA,CAAG,SAAA,EAAW,CAACH,IAAAA,KAAAA;AACrB,UAAA,IAAA,CAAKD,aAAAA,CAAcC,IAAAA,CAAKI,QAAAA,EAAQ,CAAA;QAClC,CAAA,CAAA;AAEA,QAAA,IAAA,CAAKrC,EAAAA,CAAGoC,EAAAA,CAAG,OAAA,EAAS,MAAA;AAClB,UAAA,IAAA,CAAKhC,WAAAA,GAAc,KAAA;AACnB,UAAA,IAAA,CAAKuB,KAAK,cAAA,CAAA;AACV,UAAA,IAAA,CAAKQ,OAAAA,EAAO;QACd,CAAA,CAAA;AACF,MAAA;IACF,CAAA,CAAA;AACF,EAAA;EAEAG,UAAAA,GAAmB;AACjB,IAAA,IAAI,KAAKtC,EAAAA,EAAI;AACX,MAAA,IAAA,CAAKA,GAAGuC,KAAAA,EAAK;AACb,MAAA,IAAA,CAAKvC,EAAAA,GAAK,IAAA;AACZ,IAAA;AACA,IAAA,IAAA,CAAKmC,OAAAA,EAAO;AACd,EAAA;EAEQA,OAAAA,GAAgB;AAEtB,IAAA,KAAA,MAAW,GAAGK,OAAAA,CAAAA,IAAY,KAAKlC,eAAAA,EAAiB;AAC9CoB,MAAAA,YAAAA,CAAac,QAAQjB,OAAO,CAAA;AAC5BiB,MAAAA,OAAAA,CAAQlB,MAAAA,CAAO,IAAIpE,KAAAA,CAAM,mBAAA,CAAA,CAAA;AAC3B,IAAA;AACA,IAAA,IAAA,CAAKoD,gBAAgBmC,KAAAA,EAAK;AAG1B,IAAA,IAAI,KAAKjC,YAAAA,EAAc;AACrB,MAAA,IAAA,CAAKA,YAAAA,CAAakC,KAAK,CAAA,CAAA;AACvB,MAAA,IAAA,CAAKlC,YAAAA,GAAe,IAAA;AACtB,IAAA;AACA,IAAA,IAAI,KAAKC,gBAAAA,EAAkB;AACzB,MAAA,IAAA,CAAKA,gBAAAA,CAAiBiC,KAAK,CAAA,CAAA;AAC3B,MAAA,IAAA,CAAKjC,gBAAAA,GAAmB,IAAA;AAC1B,IAAA;AACA,IAAA,IAAI,KAAKE,cAAAA,EAAgB;AACvB,MAAA,IAAA,CAAKA,cAAAA,CAAe+B,KAAK,CAAA,CAAA;AACzB,MAAA,IAAA,CAAK/B,cAAAA,GAAiB,IAAA;AACxB,IAAA;AAGA,IAAA,IAAA,CAAKD,YAAAA,GAAe,EAAA;AAGpB,IAAA,IAAA,CAAKE,kBAAAA,GAAqB,IAAA;AAC5B,EAAA;;;;;;;AAQA,EAAA,MAAM+B,kBAAAA,GAGH;AAED,IAAA,IAAI,CAAC,IAAA,CAAKvC,WAAAA,IAAe,CAAC,KAAKJ,EAAAA,EAAI;AACjC,MAAA,MAAM,KAAKmB,OAAAA,EAAO;AACpB,IAAA;AAGA,IAAA,IAAI,CAAC,IAAA,CAAKX,YAAAA,IAAgB,CAAC,KAAKE,YAAAA,EAAc;AAC5C,MAAA,MAAM,KAAKkC,SAAAA,EAAS;AACtB,IAAA;AAGA,IAAA,IACE,IAAA,CAAKzC,uBACL,CAAC,IAAA,CAAKD,QAAQgB,iBAAAA,IACd,CAAC,KAAKN,kBAAAA,EACN;AACA,MAAA,MAAM,IAAI1D,MACR,mEAAA,CAAA;AAEJ,IAAA;AAGA,IAAA,IAAI,KAAK0D,kBAAAA,EAAoB;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAKA,kBAAAA;AACb,MAAA,CAAA,CAAA,OAAS3D,KAAAA,EAAO;AAGd,QAAA,IAAA,CAAKqF,UAAAA,EAAU;AACf,QAAA,MAAMrF,KAAAA;AACR,MAAA;AACF,IAAA;AAGA,IAAA,IAAI,CAAC,IAAA,CAAKuD,YAAAA,IAAgB,CAAC,KAAKE,YAAAA,EAAc;AAC5C,MAAA,MAAM,IAAIxD,MAAM,8CAAA,CAAA;AAClB,IAAA;AAEA,IAAA,OAAO;AACLsD,MAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnBE,MAAAA,YAAAA,EAAc,IAAA,CAAKA;AACrB,KAAA;AACF,EAAA;AAEQsB,EAAAA,aAAAA,CAAcC,IAAAA,EAAoB;AACxC,IAAA,IAAI;AAEF,MAAA,MAAMY,MAAAA,GAASC,IAAAA,CAAKC,KAAAA,CAAMd,IAAAA,CAAAA;AAC1B,MAAA,MAAMe,YAAYH,MAAAA,CAAOG,SAAAA;AAGzB,MAAA,IAAIA,SAAAA,EAAW;AACb,QAAA,OAAOH,MAAAA,CAAOG,SAAAA;AAChB,MAAA;AAGA,MAAA,MAAM7F,UAAU,IAAA,CAAK8F,kBAAAA,CAAmBH,IAAAA,CAAKI,SAAAA,CAAUL,MAAAA,CAAAA,CAAAA;AAGvD,MAAA,IAAIG,SAAAA,IAAa,IAAA,CAAK1C,eAAAA,CAAgB6C,GAAAA,CAAIH,SAAAA,CAAAA,EAAY;AACpD,QAAA,MAAMR,OAAAA,GAAU,IAAA,CAAKlC,eAAAA,CAAgB8C,GAAAA,CAAIJ,SAAAA,CAAAA;AACzC,QAAA,IAAA,CAAK1C,eAAAA,CAAgB+C,OAAOL,SAAAA,CAAAA;AAC5BtB,QAAAA,YAAAA,CAAac,QAAQjB,OAAO,CAAA;AAG5B,QAAA,IAAIpE,OAAAA,CAAQmG,SAAS,OAAA,EAAS;AAE5B,UAAA,MAAMC,QAAAA,GAAWpG,OAAAA;AACjBqF,UAAAA,OAAAA,CAAQlB,OAAO,IAAIpE,KAAAA,CAAMqG,QAAAA,CAAStG,KAAAA,CAAME,OAAO,CAAA,CAAA;AACjD,QAAA,CAAA,MAAA,IAAWA,OAAAA,CAAQmG,IAAAA,CAAKE,QAAAA,CAAS,WAAA,CAAA,EAAc;AAE7C,UAAA,MAAMC,YAAAA,GAAgBtG,OAAAA,CAAgBuG,OAAAA,GACjCvG,OAAAA,CAAgBuG,SAAO,GACxBvG,OAAAA;AACJ,UAAA,IAAIsG,aAAaxG,KAAAA,EAAO;AACtBuF,YAAAA,OAAAA,CAAQlB,OAAO,IAAIpE,KAAAA,CAAMuG,YAAAA,CAAaxG,KAAAA,CAAME,OAAO,CAAA,CAAA;UACrD,CAAA,MAAO;AACLqF,YAAAA,OAAAA,CAAQnB,QAAQlE,OAAAA,CAAAA;AAClB,UAAA;QACF,CAAA,MAAO;AACLqF,UAAAA,OAAAA,CAAQnB,QAAQlE,OAAAA,CAAAA;AAClB,QAAA;AACA,QAAA;AACF,MAAA;AAEA,MAAA,IAAA,CAAKwE,IAAAA,CAAK,WAAWxE,OAAAA,CAAAA;AACvB,IAAA,CAAA,CAAA,OAASF,KAAAA,EAAO;AACd,MAAA,IAAA,CAAK0E,KAAK,OAAA,EAAS,IAAIzE,MAAM,CAAA,yBAAA,EAA4BD,KAAAA,EAAO,CAAA,CAAA;AAClE,IAAA;AACF,EAAA;AAEQ0G,EAAAA,WAAAA,CAAexG,OAAAA,EAA0B;AAC/C,IAAA,OAAO,IAAIiE,OAAAA,CAAQ,CAACC,OAAAA,EAASC,MAAAA,KAAAA;AAC3B,MAAA,IAAI,CAAC,IAAA,CAAKlB,WAAAA,IAAe,CAAC,KAAKJ,EAAAA,EAAI;AACjCsB,QAAAA,MAAAA,CAAO,IAAIpE,KAAAA,CAAM,eAAA,CAAA,CAAA;AACjB,QAAA;AACF,MAAA;AAEA,MAAA,MAAM8F,SAAAA,GAAY,OAAO,EAAE,IAAA,CAAK3C,SAAS,CAAA,CAAA,EAAInC,IAAAA,CAAKC,KAAG,CAAA,CAAA;AAErD,MAAA,MAAMyF,aAAAA,GAAgBzG,OAAAA;AACtByG,MAAAA,aAAAA,CAAcZ,SAAAA,GAAYA,SAAAA;AAE1B,MAAA,MAAMzB,OAAAA,GAAUC,WAAW,MAAA;AACzB,QAAA,IAAA,CAAKlB,eAAAA,CAAgB+C,OAAOL,SAAAA,CAAAA;AAC5B1B,QAAAA,MAAAA,CAAO,IAAIpE,KAAAA,CAAM,iBAAA,CAAA,CAAA;AACnB,MAAA,CAAA,EAAG,GAAA,CAAA;AAEH,MAAA,IAAA,CAAKoD,eAAAA,CAAgBuD,IAAIb,SAAAA,EAAW;AAAE3B,QAAAA,OAAAA;AAASC,QAAAA,MAAAA;AAAQC,QAAAA;OAAQ,CAAA;AAE/D,MAAA,IAAI;AAEF,QAAA,MAAMuC,iBAAAA,GAAoB,IAAA,CAAKC,gBAAAA,CAAiBH,aAAAA,CAAAA;AAChD,QAAA,IAAA,CAAK5D,EAAAA,CAAGgE,KAAKF,iBAAAA,CAAAA;AACf,MAAA,CAAA,CAAA,OAAS7G,KAAAA,EAAO;AACd,QAAA,IAAA,CAAKqD,eAAAA,CAAgB+C,OAAOL,SAAAA,CAAAA;AAC5BtB,QAAAA,YAAAA,CAAaH,OAAAA,CAAAA;AACbD,QAAAA,MAAAA,CAAOrE,KAAAA,CAAAA;AACT,MAAA;IACF,CAAA,CAAA;AACF,EAAA;AAEQ8G,EAAAA,gBAAAA,CAAiB5G,OAAAA,EAAsB;AAC7C,IAAA,IAAI;AAEF,MAAA,IAAIA,OAAAA,IAAW,OAAOA,OAAAA,CAAQ8G,MAAAA,KAAW,UAAA,EAAY;AACnD,QAAA,MAAMC,OAAAA,GAAU/G,QAAQ8G,MAAAA,EAAM;AAE9B,QAAA,IAAI9G,QAAQ6F,SAAAA,EAAW;AACrBkB,UAAAA,OAAAA,CAAQlB,YAAY7F,OAAAA,CAAQ6F,SAAAA;AAC9B,QAAA;AACA,QAAA,OAAOF,IAAAA,CAAKI,UAAUgB,OAAAA,CAAAA;AACxB,MAAA;AAGA,MAAA,OAAOpB,IAAAA,CAAKI,UAAU/F,OAAAA,CAAAA;AACxB,IAAA,CAAA,CAAA,OAASF,KAAAA,EAAO;AACd,MAAA,MAAM,IAAIC,KAAAA,CACR,CAAA,6BAAA,EACED,KAAAA,YAAiBC,KAAAA,GAAQD,MAAME,OAAAA,GAAUuB,MAAAA,CAAOzB,KAAAA,CAAAA,CAAAA,CAChD,CAAA;AAEN,IAAA;AACF,EAAA;AAEQgG,EAAAA,kBAAAA,CAAmBhB,IAAAA,EAAmB;AAC5C,IAAA,IAAI;AACF,MAAA,MAAMY,MAAAA,GAASC,IAAAA,CAAKC,KAAAA,CAAMd,IAAAA,CAAAA;AAG1B,MAAA,IAAI,CAACkC,eAAAA,EAAiB;AACpB,QAAA,MAAM,IAAIjH,MAAM,8BAAA,CAAA;AAClB,MAAA;AAEA,MAAA,IAAI,OAAOiH,eAAAA,CAAgB3F,MAAAA,KAAW,UAAA,EAAY;AAChD,QAAA,MAAM,IAAItB,MAAM,0CAAA,CAAA;AAClB,MAAA;AAGA,MAAA,MAAMkH,MAAAA,GAASD,eAAAA,CAAgB3F,MAAAA,CAAOqE,MAAAA,CAAAA;AACtC,MAAA,IAAIwB,MAAAA,CAAOC,MAAAA,CAAOF,MAAAA,CAAAA,EAAS;AAEzB,QAAA,OAAOvB,MAAAA;AACT,MAAA;AAEA,MAAA,OAAOuB,MAAAA,CAAOG,KAAAA;AAChB,IAAA,CAAA,CAAA,OAAStH,KAAAA,EAAO;AACd,MAAA,MAAM,IAAIC,KAAAA,CACR,CAAA,+BAAA,EACED,KAAAA,YAAiBC,KAAAA,GAAQD,MAAME,OAAAA,GAAUuB,MAAAA,CAAOzB,KAAAA,CAAAA,CAAAA,CAChD,CAAA;AAEN,IAAA;AACF,EAAA;AAEA,EAAA,MAAM2F,UAAU4B,YAAAA,EAA2C;AAEzD,IAAA,MAAM,EAAEC,gBAAAA,EAAkBhE,gBAAAA,EAAgB,GAAKiE,uBAAAA,EAAAA;AAG/C,IAAA,IAAA,CAAKjE,gBAAAA,GAAmBA,gBAAAA;AAGxB,IAAA,MAAMkE,UAAAA,GAAaC,YAAY,EAAA,CAAA;AAG/B,IAAA,IAAA,CAAKjE,cAAAA,GAAiBgE,UAAAA;AAEtB,IAAA,MAAMnC,OAAAA,GAAU,IAAIqC,yBAAAA,CAA0B;MAC5CC,SAAAA,EAAWL,gBAAAA;MACXM,KAAAA,EAAOJ,UAAAA;AACPH,MAAAA;KACF,CAAA;AAEA,IAAA,MAAMQ,QAAAA,GAAW,MAAM,IAAA,CAAKrB,WAAAA,CAAiBnB,OAAAA,CAAAA;AAG7C,IAAA,MAAMiB,YAAAA,GAAeuB,SAAStB,OAAAA,EAAO;AACrC,IAAA,IACED,YAAAA,CAAawB,wBAAAA,IACbxB,YAAAA,CAAa/C,YAAAA,IACb,KAAKD,gBAAAA,EACL;AAEA,MAAA,IAAA,CAAKC,eAAe+C,YAAAA,CAAa/C,YAAAA;AAGjC,MAAA,MAAMwE,UAAAA,GAAaC,UAAAA,CAAW1B,YAAAA,CAAawB,wBAAwB,CAAA;AAGnE,MAAA,IAAA,CAAKzE,YAAAA,GAAe4E,mBAAAA,CAClB,IAAA,CAAK3E,gBAAAA,EACLyE,UAAAA,CAAAA;AAEJ,IAAA;AAGA,IAAA,IACE,IAAA,CAAK/E,uBACLsD,YAAAA,CAAa4B,cAAAA,IACb5B,aAAawB,wBAAAA,IACb,CAAC,IAAA,CAAK/E,OAAAA,CAAQgB,iBAAAA,EACd;AAEA,MAAA,MAAMgE,UAAAA,GAAaC,UAAAA,CAAW1B,YAAAA,CAAawB,wBAAwB,CAAA;AAGnE,MAAA,IAAA,CAAKrE,kBAAAA,GAAqB,IAAA,CAAK0E,yBAAAA,CAC7B7B,YAAAA,CAAa4B,gBACbH,UAAAA,CAAAA;AAEJ,IAAA;AAEA,IAAA,OAAOF,QAAAA;AACT,EAAA;AAEA,EAAA,MAAMO,YAAYC,MAAAA,EAYD;AAEf,IAAA,MAAM,EAAEhF,YAAAA,EAAcE,YAAAA,EAAY,GAAK,MAAM,KAAKiC,kBAAAA,EAAkB;AAGpE,IAAA,IAAI8C,aAAAA;AACJ,IAAA,IAAI,OAAOD,MAAAA,CAAOrI,OAAAA,KAAY,QAAA,EAAU;AAEtC,MAAA,MAAMuI,QAAAA,GAAWF,MAAAA,CAAOrI,OAAAA,CAAQwI,UAAAA,CAAW,IAAA,CAAA,GACvCH,MAAAA,CAAOrI,OAAAA,CAAQyI,KAAAA,CAAM,CAAA,CAAA,GACrBJ,MAAAA,CAAOrI,OAAAA;AACXsI,MAAAA,aAAAA,GAAgBN,WAAWO,QAAAA,CAAAA;IAC7B,CAAA,MAAO;AAELD,MAAAA,aAAAA,GAAgBD,MAAAA,CAAOrI,OAAAA;AACzB,IAAA;AAGA,IAAA,MAAM0I,iBAAAA,GAAoB,MAAMC,eAAAA,CAC9BN,MAAAA,CAAOO,UACPvF,YAAAA,EACAE,YAAAA,EACA8E,OAAOQ,WAAW,CAAA;AAGpB,IAAA,MAAMxD,OAAAA,GAAU,IAAIyD,2BAAAA,CAA4B;AAC9CC,MAAAA,WAAAA,EAAaV,MAAAA,CAAOU,WAAAA;AACpBF,MAAAA,WAAAA,EAAaR,MAAAA,CAAOQ,WAAAA;AACpBG,MAAAA,QAAAA,EAAUX,MAAAA,CAAOW,QAAAA;AACjBC,MAAAA,cAAAA,EAAgBZ,MAAAA,CAAOY,cAAAA;AACvBC,MAAAA,KAAAA,EAAOb,MAAAA,CAAOa,KAAAA;MACdN,QAAAA,EAAUF,iBAAAA;MACV1I,OAAAA,EAASsI,aAAAA;AACTa,MAAAA,QAAAA,EAAUd,MAAAA,CAAOc,QAAAA;AACjB9B,MAAAA,YAAAA,EAAcgB,MAAAA,CAAOhB,YAAAA;AACrB+B,MAAAA,MAAAA,EAAQf,MAAAA,CAAOe,MAAAA;AACfC,MAAAA,aAAAA,EAAehB,MAAAA,CAAOgB;KACxB,CAAA;AAEA,IAAA,OAAO,IAAA,CAAK7C,YAAiBnB,OAAAA,CAAAA;AAC/B,EAAA;;;;;AAMA,EAAA,MAAMiE,OAAOjB,MAAAA,EAW4C;AAEvD,IAAA,IAAIA,MAAAA,CAAOQ,WAAAA,KAAgBU,gBAAAA,CAAiBC,OAAAA,EAAS;AACnD,MAAA,MAAM,IAAIzJ,MACR,4FAAA,CAAA;AAEJ,IAAA;AAGA,IAAA,MAAM,EAAEsD,YAAAA,EAAcE,YAAAA,EAAY,GAAK,MAAM,KAAKiC,kBAAAA,EAAkB;AAGpE,IAAA,MAAMiE,mBAAAA,GAAsBC,iBAAAA,CAC1BrB,MAAAA,CAAOsB,UAAAA,EACPtG,cACAE,YAAAA,CAAAA;AAKF,IAAA,MAAM8B,OAAAA,GAAU,IAAIuE,sBAAAA,CAAuB;AACzCb,MAAAA,WAAAA,EAAaV,MAAAA,CAAOU,WAAAA;AACpBF,MAAAA,WAAAA,EAAaR,MAAAA,CAAOQ,WAAAA;AACpBM,MAAAA,QAAAA,EAAUd,MAAAA,CAAOc,QAAAA;AACjBU,MAAAA,UAAAA,EAAYxB,MAAAA,CAAOwB,UAAAA;AACnBC,MAAAA,SAAAA,EAAWzB,MAAAA,CAAOyB,SAAAA;MAClBH,UAAAA,EAAYF,mBAAAA;AACZM,MAAAA,SAAAA,EAAW1B,MAAAA,CAAO0B,SAAAA;AAClB1C,MAAAA,YAAAA,EAAcgB,MAAAA,CAAOhB,YAAAA;AACrB+B,MAAAA,MAAAA,EAAQf,MAAAA,CAAOe,MAAAA;AACfC,MAAAA,aAAAA,EAAehB,MAAAA,CAAOgB;KACxB,CAAA;AAGA,IAAA,MAAMxB,QAAAA,GAAW,MAAM,IAAA,CAAKrB,WAAAA,CAAiBnB,OAAAA,CAAAA;AAC7C,IAAA,MAAMiB,YAAAA,GAAeuB,SAAStB,OAAAA,EAAO;AAGrC,IAAA,MAAMyD,YAAAA,GAAeC,mBAAAA,CACnB3D,YAAAA,CAAa0D,YAAAA,EACb3G,cACAE,YAAAA,CAAAA;AAGF,IAAA,OAAOyG,YAAAA;AACT,EAAA;;;;;AAMA,EAAA,MAAME,WAAW7B,MAAAA,EAUwC;AAEvD,IAAA,MAAM,EAAEhF,YAAAA,EAAcE,YAAAA,EAAY,GAAK,MAAM,KAAKiC,kBAAAA,EAAkB;AAGpE,IAAA,MAAMiE,mBAAAA,GAAsBC,iBAAAA,CAC1BrB,MAAAA,CAAOsB,UAAAA,EACPtG,cACAE,YAAAA,CAAAA;AAIF,IAAA,MAAM8B,OAAAA,GAAU,IAAI8E,0BAAAA,CAA2B;AAC7CpB,MAAAA,WAAAA,EAAaV,MAAAA,CAAOU,WAAAA;MACpBF,WAAAA,EAAa,SAAA;AACbM,MAAAA,QAAAA,EAAUd,MAAAA,CAAOc,QAAAA;AACjBU,MAAAA,UAAAA,EAAYxB,MAAAA,CAAOwB,UAAAA;AACnBC,MAAAA,SAAAA,EAAWzB,MAAAA,CAAOyB,SAAAA;MAClBH,UAAAA,EAAYF,mBAAAA;AACZM,MAAAA,SAAAA,EAAW1B,MAAAA,CAAO0B,SAAAA;AAClB1C,MAAAA,YAAAA,EAAcgB,MAAAA,CAAOhB,YAAAA;AACrB+B,MAAAA,MAAAA,EAAQf,MAAAA,CAAOe,MAAAA;AACfC,MAAAA,aAAAA,EAAehB,MAAAA,CAAOgB;KACxB,CAAA;AAGA,IAAA,MAAMxB,QAAAA,GAAW,MAAM,IAAA,CAAKrB,WAAAA,CAAiBnB,OAAAA,CAAAA;AAC7C,IAAA,MAAMiB,YAAAA,GAAeuB,SAAStB,OAAAA,EAAO;AAGrC,IAAA,MAAMyD,YAAAA,GAAeC,mBAAAA,CACnB3D,YAAAA,CAAa0D,YAAAA,EACb3G,cACAE,YAAAA,CAAAA;AAGF,IAAA,OAAOyG,YAAAA;AACT,EAAA;AAEA,EAAA,IAAII,SAAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAKnH,WAAAA;AACd,EAAA;;;;;;;;EAUA,MAAckF,yBAAAA,CACZjI,sBACA6H,UAAAA,EACe;AACf,IAAA,IAAI,CAAC,KAAK/E,mBAAAA,EAAqB;AAC7B,MAAA;AACF,IAAA;AAEA,IAAA,IAAI;AAEF,MAAA,MAAMqH,aAAAA,GAAgBC,OAAOvC,UAAAA,CAAAA;AAC7B,MAAA,MAAM5H,oBAAoBoK,KAAAA,CAAMnI,IAAAA,CAAKiI,aAAAA,CAAAA,CAClCG,GAAAA,CAAI,CAACC,CAAAA,KAAcA,CAAAA,CAAEvF,QAAAA,CAAS,EAAA,EAAIwF,QAAAA,CAAS,CAAA,EAAG,GAAA,CAAA,CAAA,CAC9CC,KAAK,EAAA,CAAA;AAIR,MAAA,IAAI,CAAC,KAAKnH,cAAAA,EAAgB;AACxB,QAAA,MAAM,IAAIzD,MACR,6DAAA,CAAA;AAEJ,MAAA;AAEA,MAAA,MAAMkH,MAAAA,GAAS,MAAM,IAAA,CAAKjE,mBAAAA,CAAoB/C,OAC5CC,oBAAAA,EACAC,iBAAAA,EACA,KAAKqD,cAAc,CAAA;AAGrB,MAAA,IAAI,CAACyD,OAAOrG,KAAAA,EAAO;AACjB,QAAA,MAAMwF,WAAW,CAAA,iCAAA,EAAoCa,MAAAA,CAAOpG,MAAAA,CAAO8J,IAAAA,CACjE,IAAA,CAAA,CAAA,CAAA;AAEF,QAAA,IAAA,CAAKnG,IAAAA,CAAK,OAAA,EAAS,IAAIzE,KAAAA,CAAMqG,QAAAA,CAAAA,CAAAA;AAC7B,QAAA,MAAM,IAAIrG,MAAMqG,QAAAA,CAAAA;AAClB,MAAA;AAGA,MAAA,IAAA,CAAK5B,KAAK,SAAA,EAAW;QACnB2B,IAAAA,EAAM,sBAAA;AACNrF,QAAAA,SAAAA,EAAWC,KAAKC,GAAAA,EAAG;QACnB8D,IAAAA,EAAMmC;OACR,CAAA;AACF,IAAA,CAAA,CAAA,OAASnH,KAAAA,EAAO;AACd,MAAA,MAAMsG,QAAAA,GAAW,mCACftG,KAAAA,YAAiBC,KAAAA,GAAQD,MAAME,OAAAA,GAAUuB,MAAAA,CAAOzB,KAAAA,CAAAA,CAAAA,CAAAA;AAElD,MAAA,IAAA,CAAK0E,IAAAA,CAAK,OAAA,EAAS,IAAIzE,KAAAA,CAAMqG,QAAAA,CAAAA,CAAAA;AAC7B,MAAA,MAAM,IAAIrG,MAAMqG,QAAAA,CAAAA;AAClB,IAAA;AACF,EAAA;AACF","file":"index.js","sourcesContent":["/**\n * AWS Nitro Security Module (NSM) Root Certificate\n * This is the official AWS root certificate used to verify attestation documents\n */\nexport const AWS_NITRO_ROOT_CERTIFICATE = `-----BEGIN CERTIFICATE-----\nMIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL\nMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD\nVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4\nMTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL\nDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb\n48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE\nh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF\nR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC\nMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW\nrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N\nIwLz3/Y=\n-----END CERTIFICATE-----`;\n\n/**\n * Expected PCR values for different environments\n */\nexport const EXPECTED_PCR_VALUES = {\n // Production PCR8 values would be set based on actual enclave builds\n // These would be configured via environment variables in production\n // Development values should be set in the application configuration, not here\n} as const;\n\n/**\n * Attestation document validation constants\n */\nexport const ATTESTATION_CONSTANTS = {\n // Maximum age of attestation document in milliseconds\n MAX_ATTESTATION_AGE: 5 * 60 * 1000, // 5 minutes\n\n // Expected digest algorithm\n EXPECTED_DIGEST: 'SHA384',\n\n // Expected module ID pattern\n MODULE_ID_PATTERN: /^i-[0-9a-f]{8,17}-enc[0-9a-f]{8,17}$/,\n\n // PCR indices that must be present\n REQUIRED_PCRS: [0, 1, 2, 8] as const,\n} as const;\n","import {\n AttestationVerificationResult,\n AttestationVerificationConfig,\n} from './types';\nimport { ATTESTATION_CONSTANTS } from './constants';\n\n// Import Evervault WASM attestation bindings\nimport init, {\n validateAttestationDocPcrs,\n PCRs,\n getUserData,\n getNonce,\n} from '@evervault/wasm-attestation-bindings';\n\n/**\n * Nitro Enclave Attestation Document Verifier\n * Uses Evervault's official WASM attestation bindings\n * Optimized for client-side usage with hex string input\n */\nexport class NitroAttestationVerifier {\n private readonly config: AttestationVerificationConfig;\n private wasmInitialized = false;\n\n constructor(config: AttestationVerificationConfig) {\n this.config = {\n strictCertValidation: true,\n maxAge: ATTESTATION_CONSTANTS.MAX_ATTESTATION_AGE,\n ...config,\n };\n }\n\n /**\n * Initialize WASM module if not already initialized\n */\n private async ensureWasmInitialized(): Promise<void> {\n if (!this.wasmInitialized) {\n try {\n // Initialize WASM module - in browser, this will automatically load the .wasm file\n await init();\n this.wasmInitialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n }\n }\n\n /**\n * Verify an attestation document using Evervault WASM bindings\n * Accepts base64-encoded attestation document directly\n *\n * @param attestationDocBase64 - Base64-encoded attestation document\n * @param expectedChallenge - Expected challenge (ciphertext hash)\n * @param expectedNonce - Expected nonce (REQUIRED for security)\n */\n async verify(\n attestationDocBase64: string,\n expectedChallenge: string,\n expectedNonce: Uint8Array\n ): Promise<AttestationVerificationResult> {\n try {\n // Ensure WASM module is initialized\n await this.ensureWasmInitialized();\n\n // Create PCRs container with expected values\n const expectedPcrs = PCRs.empty();\n expectedPcrs.pcr8 = this.config.expectedPcr8;\n\n // Use Evervault WASM bindings to verify the attestation document (already in base64)\n const isValid = validateAttestationDocPcrs(attestationDocBase64, [\n expectedPcrs,\n ]);\n\n if (!isValid) {\n return {\n valid: false,\n errors: ['Attestation document PCR verification failed'],\n timestamp: Date.now(),\n };\n }\n\n // Verify challenge (ciphertext hash) if provided\n if (expectedChallenge) {\n try {\n const userData = getUserData(attestationDocBase64);\n if (!userData) {\n return {\n valid: false,\n errors: ['No user data found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // Convert user data to string and verify it contains the expected challenge\n const userDataString = new TextDecoder('utf-8').decode(userData);\n\n // The challenge should be the hex-encoded hash of the ciphertext\n // Verify that the attestation document's user data contains this challenge\n if (!userDataString.includes(expectedChallenge)) {\n return {\n valid: false,\n errors: [\n 'Ciphertext hash verification failed - challenge not found in attestation user data',\n ],\n timestamp: Date.now(),\n };\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify ciphertext hash: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n\n // Verify nonce (REQUIRED for security - prevents replay attacks)\n try {\n // Use WASM getNonce function to extract nonce from attestation document\n const extractedNonceRaw = getNonce(attestationDocBase64);\n\n if (!extractedNonceRaw) {\n return {\n valid: false,\n errors: ['No nonce found in attestation document'],\n timestamp: Date.now(),\n };\n }\n\n // The attestation document stores the nonce as a base64-encoded string\n // We need to decode it back to the original bytes\n let extractedNonce: Uint8Array;\n try {\n // Convert to string and decode from base64 (cross-platform)\n const nonceString = new TextDecoder().decode(extractedNonceRaw);\n\n // Browser-compatible base64 decoding\n if (typeof atob !== 'undefined') {\n // Browser environment\n const binaryString = atob(nonceString);\n extractedNonce = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n extractedNonce[i] = binaryString.charCodeAt(i);\n }\n } else {\n // Node.js environment\n const decodedBuffer = Buffer.from(nonceString, 'base64');\n extractedNonce = new Uint8Array(decodedBuffer);\n }\n } catch (decodeError) {\n return {\n valid: false,\n errors: [\n `Failed to decode nonce from base64: ${decodeError instanceof Error ? decodeError.message : String(decodeError)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n // Compare nonces byte-for-byte\n if (extractedNonce.length !== expectedNonce.length) {\n return {\n valid: false,\n errors: [\n `Nonce length mismatch: expected ${expectedNonce.length} bytes, got ${extractedNonce.length} bytes`,\n ],\n timestamp: Date.now(),\n };\n }\n\n for (let i = 0; i < expectedNonce.length; i++) {\n if (extractedNonce[i] !== expectedNonce[i]) {\n return {\n valid: false,\n errors: ['Nonce verification failed - nonce mismatch'],\n timestamp: Date.now(),\n };\n }\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Failed to extract or verify nonce: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n\n return {\n valid: true,\n errors: [],\n timestamp: Date.now(),\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n `Attestation verification error: ${error instanceof Error ? error.message : String(error)}`,\n ],\n timestamp: Date.now(),\n };\n }\n }\n}\n","// Browser/Node.js compatibility\nimport { EventEmitter } from 'eventemitter3';\nimport * as ws from 'ws';\n\nconst isWindow =\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as any).window !== 'undefined';\nconst WebSocketImpl = isWindow ? (globalThis as any).WebSocket : ws.WebSocket;\n\nimport {\n BaseWebSocketMessage,\n ErrorResponse,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport {\n HandshakeV1RequestMessage,\n SignMessageV1RequestMessage,\n KeygenV1RequestMessage,\n ReceiveKeyV1RequestMessage,\n messageRegistry,\n HashAlgorithm,\n generateMlKem768Keypair,\n decapsulateMlKem768,\n encryptKeyshare,\n encryptKeygenInit,\n decryptKeygenResult,\n type SigningAlgorithmName,\n type TraceContext,\n} from '@dynamic-labs-wallet/forward-mpc-shared';\nimport { NitroAttestationVerifier } from './attestation';\nimport { AttestationVerificationConfig } from './attestation/types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { hexToBytes, randomBytes } from '@noble/hashes/utils.js';\nimport { either } from 'fp-ts';\nimport { SigningAlgorithm } from '@dynamic-labs-wallet/core';\n\nexport interface ForwardMPCClientOptions {\n reconnectAttempts?: number;\n reconnectInterval?: number;\n connectionTimeout?: number;\n heartbeatInterval?: number;\n attestationConfig?: AttestationVerificationConfig;\n attestationVerifier?: any; // Allow custom verifier (mock or real)\n bypassAttestation?: boolean; // Default: false. Only for testing!\n}\n\nexport interface ClientEvents {\n connected: () => void;\n disconnected: () => void;\n error: (error: Error) => void;\n message: (message: BaseWebSocketMessage) => void;\n}\n\nexport class ForwardMPCClient extends EventEmitter {\n private ws: any = null;\n private url: string;\n private options: Required<\n Omit<ForwardMPCClientOptions, 'attestationVerifier' | 'attestationConfig'>\n > & {\n attestationVerifier?: any;\n attestationConfig?: AttestationVerificationConfig;\n };\n private attestationVerifier: any | null = null; // Can be NitroAttestationVerifier or mock\n private isConnected = false;\n private messageId = 0;\n private pendingRequests = new Map<\n string,\n {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n timeout: NodeJS.Timeout;\n }\n >();\n private sharedSecret: Uint8Array | null = null;\n private decapsulationKey: Uint8Array | null = null;\n private connectionId: string;\n private handshakeNonce: Uint8Array | null = null;\n private attestationPromise: Promise<void> | null = null;\n\n constructor(url: string, options: ForwardMPCClientOptions = {}) {\n super();\n\n this.url = url;\n this.connectionId = ''; // Will be set by server during handshake\n this.options = {\n reconnectAttempts: options.reconnectAttempts ?? 3,\n reconnectInterval: options.reconnectInterval ?? 1000,\n connectionTimeout: options.connectionTimeout ?? 10000,\n heartbeatInterval: options.heartbeatInterval ?? 30000,\n attestationConfig: options.attestationConfig,\n attestationVerifier: options.attestationVerifier,\n bypassAttestation: options.bypassAttestation ?? false,\n };\n\n // Initialize attestation verifier - use custom verifier if provided, otherwise create from config\n if (options.attestationVerifier) {\n this.attestationVerifier = options.attestationVerifier;\n } else if (this.options.attestationConfig) {\n this.attestationVerifier = new NitroAttestationVerifier(\n this.options.attestationConfig\n );\n }\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.isConnected) {\n resolve();\n return;\n }\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n }, this.options.connectionTimeout);\n\n this.ws = new WebSocketImpl(this.url);\n\n // Handle both browser and Node.js WebSocket APIs\n if (isWindow) {\n // Browser WebSocket API\n this.ws.onopen = () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n };\n\n this.ws.onerror = (_error: any) => {\n clearTimeout(timeout);\n this.emit('error', new Error('WebSocket error'));\n reject(new Error('WebSocket error'));\n };\n\n this.ws.onmessage = (event: any) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n };\n } else {\n // Node.js WebSocket API\n this.ws.on('open', () => {\n clearTimeout(timeout);\n this.isConnected = true;\n this.emit('connected');\n resolve();\n });\n\n this.ws.on('error', (error: any) => {\n clearTimeout(timeout);\n this.emit('error', error);\n reject(error);\n });\n\n this.ws.on('message', (data: any) => {\n this.handleMessage(data.toString());\n });\n\n this.ws.on('close', () => {\n this.isConnected = false;\n this.emit('disconnected');\n this.cleanup();\n });\n }\n });\n }\n\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.cleanup();\n }\n\n private cleanup(): void {\n // Reject all pending requests\n for (const [, request] of this.pendingRequests) {\n clearTimeout(request.timeout);\n request.reject(new Error('Connection closed'));\n }\n this.pendingRequests.clear();\n\n // Clear sensitive cryptographic material\n if (this.sharedSecret) {\n this.sharedSecret.fill(0);\n this.sharedSecret = null;\n }\n if (this.decapsulationKey) {\n this.decapsulationKey.fill(0);\n this.decapsulationKey = null;\n }\n if (this.handshakeNonce) {\n this.handshakeNonce.fill(0);\n this.handshakeNonce = null;\n }\n\n // Clear connection ID\n this.connectionId = '';\n\n // Reset attestation state\n this.attestationPromise = null;\n }\n\n /**\n * Ensures the WebSocket connection is active and handshake is completed.\n * Automatically connects and performs handshake if needed.\n * @returns Object containing the shared secret and connection ID\n * @throws Error if connection or handshake fails\n */\n async ensureWsConnection(): Promise<{\n sharedSecret: Uint8Array;\n connectionId: string;\n }> {\n // Check if we need to connect\n if (!this.isConnected || !this.ws) {\n await this.connect();\n }\n\n // Check if we need to perform handshake\n if (!this.sharedSecret || !this.connectionId) {\n await this.handshake();\n }\n\n // Defensive check: if attestation verifier is configured, promise must exist\n if (\n this.attestationVerifier &&\n !this.options.bypassAttestation &&\n !this.attestationPromise\n ) {\n throw new Error(\n 'Attestation verifier configured but attestation was not performed'\n );\n }\n\n // Await attestation completion (throws if failed)\n if (this.attestationPromise) {\n try {\n await this.attestationPromise;\n } catch (error) {\n // Handle attestation failure by disconnecting\n // Side effect is here in the caller's context, not in the promise\n this.disconnect();\n throw error; // Re-throw for the caller\n }\n }\n\n // Final validation - should never happen but defensive check\n if (!this.sharedSecret || !this.connectionId) {\n throw new Error('Failed to establish connection and handshake');\n }\n\n return {\n sharedSecret: this.sharedSecret,\n connectionId: this.connectionId,\n };\n }\n\n private handleMessage(data: string): void {\n try {\n // Parse the raw message first to extract requestId\n const parsed = JSON.parse(data);\n const requestId = parsed.requestId;\n\n // Remove requestId from the message before deserializing\n if (requestId) {\n delete parsed.requestId;\n }\n\n // Now deserialize the message without requestId\n const message = this.deserializeMessage(JSON.stringify(parsed));\n\n // Check if this is a response to a pending request\n if (requestId && this.pendingRequests.has(requestId)) {\n const request = this.pendingRequests.get(requestId)!;\n this.pendingRequests.delete(requestId);\n clearTimeout(request.timeout);\n\n // Handle unified response format with embedded errors\n if (message.type === 'error') {\n // Legacy error response format\n const errorMsg = message as ErrorResponse;\n request.reject(new Error(errorMsg.error.message));\n } else if (message.type.endsWith('_response')) {\n // Check if the response contains an error field\n const responseData = (message as any).getData\n ? (message as any).getData()\n : message;\n if (responseData.error) {\n request.reject(new Error(responseData.error.message));\n } else {\n request.resolve(message);\n }\n } else {\n request.resolve(message);\n }\n return;\n }\n\n this.emit('message', message);\n } catch (error) {\n this.emit('error', new Error(`Failed to parse message: ${error}`));\n }\n }\n\n private sendRequest<T>(message: any): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected || !this.ws) {\n reject(new Error('Not connected'));\n return;\n }\n\n const requestId = `req_${++this.messageId}_${Date.now()}`;\n // Add requestId to message (works for both objects and Message instances)\n const messageWithId = message;\n messageWithId.requestId = requestId;\n\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(requestId);\n reject(new Error('Request timeout'));\n }, 30000); // 30 second timeout for attestation verification\n\n this.pendingRequests.set(requestId, { resolve, reject, timeout });\n\n try {\n // Use custom serializer that encodes using io-ts schemas\n const serializedMessage = this.serializeMessage(messageWithId);\n this.ws.send(serializedMessage);\n } catch (error) {\n this.pendingRequests.delete(requestId);\n clearTimeout(timeout);\n reject(error);\n }\n });\n }\n\n private serializeMessage(message: any): string {\n try {\n // If it's a Message class instance, use its encode method\n if (message && typeof message.encode === 'function') {\n const encoded = message.encode();\n // Add requestId if present\n if (message.requestId) {\n encoded.requestId = message.requestId;\n }\n return JSON.stringify(encoded);\n }\n\n // Fallback to regular JSON for other objects\n return JSON.stringify(message);\n } catch (error) {\n throw new Error(\n `Failed to serialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n private deserializeMessage(data: string): any {\n try {\n const parsed = JSON.parse(data);\n\n // Check if messageRegistry exists and has decode method\n if (!messageRegistry) {\n throw new Error('messageRegistry is undefined');\n }\n\n if (typeof messageRegistry.decode !== 'function') {\n throw new Error('messageRegistry.decode is not a function');\n }\n\n // Use message registry to decode\n const result = messageRegistry.decode(parsed);\n if (either.isLeft(result)) {\n // If registry can't decode it, return as-is (might be error response, etc.)\n return parsed;\n }\n\n return result.right;\n } catch (error) {\n throw new Error(\n `Failed to deserialize message: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n async handshake(traceContext?: TraceContext): Promise<any> {\n // Generate ML-KEM-768 keypair and use encapsulation key as challenge\n const { encapsulationKey, decapsulationKey } = generateMlKem768Keypair();\n\n // Store decapsulation key for later use\n this.decapsulationKey = decapsulationKey;\n\n // Generate a cryptographically secure nonce for attestation\n const nonceBytes = randomBytes(32); // 256-bit nonce\n\n // Store original bytes for verification\n this.handshakeNonce = nonceBytes;\n\n const request = new HandshakeV1RequestMessage({\n challenge: encapsulationKey, // ML-KEM-768 encapsulation key (will be encoded to hex by the message class)\n nonce: nonceBytes, // User data nonce for attestation document\n traceContext,\n });\n\n const response = await this.sendRequest<any>(request);\n\n // Extract shared secret from response using ML-KEM decapsulation\n const responseData = response.getData();\n if (\n responseData.encapsulatedSharedSecret &&\n responseData.connectionId &&\n this.decapsulationKey\n ) {\n // Use the server's connection ID for consistent key derivation\n this.connectionId = responseData.connectionId;\n\n // Convert hex string back to bytes for decapsulation\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Perform ML-KEM decapsulation to derive shared secret\n this.sharedSecret = decapsulateMlKem768(\n this.decapsulationKey,\n cipherText\n );\n }\n\n // Verify attestation document (store promise for later await)\n if (\n this.attestationVerifier &&\n responseData.attestationDoc &&\n responseData.encapsulatedSharedSecret &&\n !this.options.bypassAttestation\n ) {\n // Convert hex string back to bytes for challenge verification\n const cipherText = hexToBytes(responseData.encapsulatedSharedSecret);\n\n // Store promise - method already throws on failure\n this.attestationPromise = this.verifyAttestationDocument(\n responseData.attestationDoc,\n cipherText\n );\n }\n\n return response;\n }\n\n async signMessage(params: {\n keyshare: any; // Keyshare object from Dynamic Wallet SDK\n message: Uint8Array | string; // Message to sign (supports hex string or Uint8Array)\n relayDomain: string;\n signingAlgo: SigningAlgorithm;\n hashAlgo?: HashAlgorithm;\n derivationPath?: Uint32Array;\n tweak?: Uint8Array;\n roomUuid: string; // MPC room UUID for signing ceremony\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<any> {\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Convert hex string to Uint8Array if needed\n let messageToSign: Uint8Array;\n if (typeof params.message === 'string') {\n // Handle hex strings (with or without 0x prefix)\n const cleanHex = params.message.startsWith('0x')\n ? params.message.slice(2)\n : params.message;\n messageToSign = hexToBytes(cleanHex);\n } else {\n // Already a Uint8Array\n messageToSign = params.message;\n }\n\n // Encrypt the keyshare using AES-256-GCM\n const encryptedKeyshare = await encryptKeyshare(\n params.keyshare,\n sharedSecret,\n connectionId,\n params.signingAlgo as unknown as SigningAlgorithmName\n );\n\n const request = new SignMessageV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: params.signingAlgo,\n hashAlgo: params.hashAlgo,\n derivationPath: params.derivationPath,\n tweak: params.tweak,\n keyshare: encryptedKeyshare,\n message: messageToSign, // Always pass Uint8Array to the message class\n roomUuid: params.roomUuid,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n return this.sendRequest<any>(request);\n }\n\n /**\n * Perform MPC keygen for ECDSA and BIP340 algorithms\n * For ED25519, use sampleKey() or receiveKey() methods instead\n */\n async keygen(params: {\n keygenInit: { keygenId: string; keygenSecret: string };\n relayDomain: string;\n signingAlgo: SigningAlgorithm;\n roomUuid: string;\n numParties: number;\n threshold: number;\n keygenIds: string[];\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<{ pubkey: Uint8Array; secretShare: string }> {\n // Validate algorithm (only ECDSA and BIP340 supported)\n if (params.signingAlgo === SigningAlgorithm.ED25519) {\n throw new Error(\n 'ED25519 keygen not supported via keygen() method. Use sampleKey() or receiveKey() instead.'\n );\n }\n\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Encrypt the keygen init data\n const encryptedKeygenInit = encryptKeygenInit(\n params.keygenInit,\n sharedSecret,\n connectionId\n );\n\n // Create ECDSA or BIP340 keygen request\n // The message encoder will convert the enum to lowercase on the wire\n const request = new KeygenV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: params.signingAlgo,\n roomUuid: params.roomUuid,\n numParties: params.numParties,\n threshold: params.threshold,\n keygenInit: encryptedKeygenInit,\n keygenIds: params.keygenIds,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n // Send request and get encrypted response\n const response = await this.sendRequest<any>(request);\n const responseData = response.getData();\n\n // Decrypt the keygen result\n const keygenResult = decryptKeygenResult(\n responseData.keygenResult,\n sharedSecret,\n connectionId\n );\n\n return keygenResult;\n }\n\n /**\n * Receive an ED25519 key (one party receives the key generated by another)\n * Uses ExportableEd25519 - the receiving party gets the key sampled by another party\n */\n async receiveKey(params: {\n keygenInit: { keygenId: string; keygenSecret: string };\n relayDomain: string;\n roomUuid: string;\n numParties: number;\n threshold: number;\n keygenIds: string[];\n traceContext?: TraceContext;\n userId?: string;\n environmentId?: string;\n }): Promise<{ pubkey: Uint8Array; secretShare: string }> {\n // Ensure connection is active and handshake is completed (auto-connect if needed)\n const { sharedSecret, connectionId } = await this.ensureWsConnection();\n\n // Encrypt the keygen init data\n const encryptedKeygenInit = encryptKeygenInit(\n params.keygenInit,\n sharedSecret,\n connectionId\n );\n\n // Create receiveKey request\n const request = new ReceiveKeyV1RequestMessage({\n relayDomain: params.relayDomain,\n signingAlgo: 'ed25519',\n roomUuid: params.roomUuid,\n numParties: params.numParties,\n threshold: params.threshold,\n keygenInit: encryptedKeygenInit,\n keygenIds: params.keygenIds,\n traceContext: params.traceContext,\n userId: params.userId,\n environmentId: params.environmentId,\n });\n\n // Send request and get encrypted response\n const response = await this.sendRequest<any>(request);\n const responseData = response.getData();\n\n // Decrypt the keygen result\n const keygenResult = decryptKeygenResult(\n responseData.keygenResult,\n sharedSecret,\n connectionId\n );\n\n return keygenResult;\n }\n\n get connected(): boolean {\n return this.isConnected;\n }\n\n /**\n * Generate a unique connection ID\n */\n\n /**\n * Verify attestation document from handshake response\n * Uses base64-encoded attestation document directly\n */\n private async verifyAttestationDocument(\n attestationDocBase64: string,\n cipherText: Uint8Array\n ): Promise<void> {\n if (!this.attestationVerifier) {\n return; // No verifier configured\n }\n\n try {\n // Generate the expected challenge (hash of cipher text from ML-KEM encapsulation)\n const challengeHash = sha256(cipherText);\n const expectedChallenge = Array.from(challengeHash)\n .map((b: number) => b.toString(16).padStart(2, '0'))\n .join('');\n\n // Verify the attestation document directly with base64 string (no conversion needed!)\n // Nonce is required for security (prevents replay attacks)\n if (!this.handshakeNonce) {\n throw new Error(\n 'Nonce not found - handshake may not have completed properly'\n );\n }\n\n const result = await this.attestationVerifier.verify(\n attestationDocBase64,\n expectedChallenge,\n this.handshakeNonce\n );\n\n if (!result.valid) {\n const errorMsg = `Attestation verification failed: ${result.errors.join(\n ', '\n )}`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n\n // Emit success event with verification result\n this.emit('message', {\n type: 'attestation-verified',\n timestamp: Date.now(),\n data: result,\n } as any);\n } catch (error) {\n const errorMsg = `Attestation verification error: ${\n error instanceof Error ? error.message : String(error)\n }`;\n this.emit('error', new Error(errorMsg));\n throw new Error(errorMsg);\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/forward-mpc-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "WebSocket client for Forward MPC operations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -31,21 +31,22 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@dynamic-labs-wallet/core": "^0.0.
|
|
34
|
+
"@dynamic-labs-wallet/core": "^0.0.259",
|
|
35
35
|
"@evervault/wasm-attestation-bindings": "^0.3.1",
|
|
36
36
|
"@noble/hashes": "^2.0.0",
|
|
37
37
|
"@noble/post-quantum": "^0.5.1",
|
|
38
38
|
"eventemitter3": "^5.0.1",
|
|
39
39
|
"fp-ts": "^2.16.11",
|
|
40
40
|
"ws": "^8.18.3",
|
|
41
|
-
"@dynamic-labs-wallet/forward-mpc-shared": "0.
|
|
41
|
+
"@dynamic-labs-wallet/forward-mpc-shared": "0.3.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^24.5.1",
|
|
45
45
|
"@types/ws": "^8.18.1",
|
|
46
46
|
"rimraf": "^6.0.1",
|
|
47
47
|
"tsup": "^8.3.5",
|
|
48
|
-
"typescript": "^5.9.2"
|
|
48
|
+
"typescript": "^5.9.2",
|
|
49
|
+
"vitest": "^4.0.10"
|
|
49
50
|
},
|
|
50
51
|
"keywords": [
|
|
51
52
|
"websocket",
|
|
@@ -57,6 +58,9 @@
|
|
|
57
58
|
"build": "tsup",
|
|
58
59
|
"dev": "tsup --watch",
|
|
59
60
|
"clean": "rimraf dist .tsbuildinfo",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"test:watch": "vitest",
|
|
63
|
+
"test:coverage": "vitest run --coverage",
|
|
60
64
|
"typecheck": "tsc --noEmit",
|
|
61
65
|
"lint": "eslint src --ext .ts,.tsx",
|
|
62
66
|
"lint:fix": "eslint src --ext .ts,.tsx --fix"
|