@entros/pulse-sdk 3.2.0 → 3.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.d.mts +182 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +641 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +628 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
|
|
1
3
|
declare const FINGERPRINT_BITS = 256;
|
|
2
4
|
declare const DEFAULT_THRESHOLD = 96;
|
|
3
5
|
declare const DEFAULT_MIN_DISTANCE = 3;
|
|
@@ -511,6 +513,15 @@ declare function submitViaWallet(proof: SolanaProof, commitment: Uint8Array, opt
|
|
|
511
513
|
* VerificationResult PDA instead.
|
|
512
514
|
*/
|
|
513
515
|
signedReceipt?: SignedReceiptDto;
|
|
516
|
+
/**
|
|
517
|
+
* Encrypted baseline blob (master-list #98). When present, the SDK
|
|
518
|
+
* appends a `set_encrypted_baseline` instruction at the end of the
|
|
519
|
+
* atomic transaction so the wallet's on-chain baseline is rewritten
|
|
520
|
+
* to reflect the new fingerprint in the same wallet prompt as the
|
|
521
|
+
* mint / re-verify. Omitted when the wallet adapter lacks
|
|
522
|
+
* `signMessage` (the SDK can't derive the AES key without it).
|
|
523
|
+
*/
|
|
524
|
+
encryptedBaselineBlob?: Uint8Array;
|
|
514
525
|
}): Promise<SubmissionResult>;
|
|
515
526
|
/**
|
|
516
527
|
* Submit a baseline reset on-chain via a connected wallet.
|
|
@@ -532,6 +543,15 @@ declare function submitResetViaWallet(commitment: Uint8Array, options: {
|
|
|
532
543
|
connection: any;
|
|
533
544
|
relayerUrl?: string;
|
|
534
545
|
relayerApiKey?: string;
|
|
546
|
+
/**
|
|
547
|
+
* Encrypted baseline blob (master-list #98). When present, the SDK
|
|
548
|
+
* appends a `set_encrypted_baseline` instruction so the wallet's
|
|
549
|
+
* on-chain baseline is rewritten under the NEW post-reset commitment
|
|
550
|
+
* in the same atomic transaction. Without this, the prior blob would
|
|
551
|
+
* be stale on the next recovery attempt (auth-tag mismatch under the
|
|
552
|
+
* new commitment in AAD) and recovery would fall back to fresh capture.
|
|
553
|
+
*/
|
|
554
|
+
encryptedBaselineBlob?: Uint8Array;
|
|
535
555
|
}): Promise<SubmissionResult>;
|
|
536
556
|
|
|
537
557
|
/**
|
|
@@ -630,6 +650,125 @@ interface StoredVerificationData {
|
|
|
630
650
|
timestamp: number;
|
|
631
651
|
}
|
|
632
652
|
|
|
653
|
+
/**
|
|
654
|
+
* Wallet-keyed encrypted baseline storage (master-list #98).
|
|
655
|
+
*
|
|
656
|
+
* Architecture: the user's previous SimHash + salt (private witnesses for
|
|
657
|
+
* the Hamming-distance ZK proof) are encrypted with AES-256-GCM under a
|
|
658
|
+
* key derived from a deterministic `signMessage` on a domain-separated
|
|
659
|
+
* payload. The 96-byte ciphertext blob is stored on chain in a per-wallet
|
|
660
|
+
* `EncryptedBaseline` PDA, making the baseline wallet-portable across
|
|
661
|
+
* devices and recoverable after a cache wipe.
|
|
662
|
+
*
|
|
663
|
+
* The GCM AAD binds (version, algorithm, wallet, baselinePda, current on-
|
|
664
|
+
* chain commitment). After `reset_identity_state` cycles the commitment,
|
|
665
|
+
* the old blob's auth-tag fails to verify under the new commitment — that
|
|
666
|
+
* mismatch IS the staleness signal. No explicit version tracking needed.
|
|
667
|
+
*
|
|
668
|
+
* Plaintext biometric data never reaches chain at any point. This module
|
|
669
|
+
* is the only place wallet-derived key material flows; it never leaves
|
|
670
|
+
* memory and the key is non-extractable.
|
|
671
|
+
*/
|
|
672
|
+
|
|
673
|
+
/** Layout: version(1) + algo(1) + reserved(2) + IV(12) + ct+tag(80) */
|
|
674
|
+
declare const ENCRYPTED_BASELINE_BLOB_BYTES = 96;
|
|
675
|
+
/**
|
|
676
|
+
* Pack a 256-bit fingerprint into 32 bytes. LSB-first within each byte —
|
|
677
|
+
* the convention is internal to the encrypted-baseline blob; the only
|
|
678
|
+
* requirement is that `bytesToFingerprint` is its exact inverse.
|
|
679
|
+
*/
|
|
680
|
+
declare function fingerprintToBytes(bits: number[]): Uint8Array;
|
|
681
|
+
/** Inverse of `fingerprintToBytes`. */
|
|
682
|
+
declare function bytesToFingerprint(bytes: Uint8Array): number[];
|
|
683
|
+
/** Big-endian 32-byte → BigInt. Inverse of `bigintToBytes32` in hashing/poseidon. */
|
|
684
|
+
declare function bytes32ToBigint(bytes: Uint8Array): bigint;
|
|
685
|
+
/**
|
|
686
|
+
* The per-wallet `EncryptedBaseline` PDA address. Owned by entros-anchor.
|
|
687
|
+
* Seeds: `[b"encrypted_baseline", walletPubkey.toBuffer()]`.
|
|
688
|
+
*/
|
|
689
|
+
declare function deriveEncryptedBaselinePda(walletPubkey: PublicKey): Promise<[PublicKey, number]>;
|
|
690
|
+
/**
|
|
691
|
+
* Wallet adapter shape needed for key derivation.
|
|
692
|
+
* Compatible with `@solana/wallet-adapter-base` `WalletAdapter`.
|
|
693
|
+
*/
|
|
694
|
+
interface BaselineWallet {
|
|
695
|
+
publicKey: PublicKey;
|
|
696
|
+
signMessage: (msg: Uint8Array) => Promise<Uint8Array>;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Derive an AES-256 key from the wallet's deterministic signature over
|
|
700
|
+
* the domain-separated payload, via HKDF-SHA256.
|
|
701
|
+
*
|
|
702
|
+
* IKM = Ed25519 signature (64 bytes, pseudorandom under RoM)
|
|
703
|
+
* salt = wallet pubkey bytes (32 bytes — wallet-binding salt)
|
|
704
|
+
* info = "entros-protocol/identity-baseline/v1"
|
|
705
|
+
* L = 32 bytes (AES-256 key length)
|
|
706
|
+
*
|
|
707
|
+
* Determinism follows from RFC 8032 Ed25519 signature determinism. Same
|
|
708
|
+
* wallet + same message → same signature → same key, across any device.
|
|
709
|
+
*
|
|
710
|
+
* The derived `CryptoKey` is non-extractable; only WebCrypto can use it
|
|
711
|
+
* for AES-GCM encrypt/decrypt.
|
|
712
|
+
*
|
|
713
|
+
* Throws if the wallet doesn't implement `signMessage` (e.g., some Ledger
|
|
714
|
+
* firmware versions). Callers should catch and fall back gracefully.
|
|
715
|
+
*/
|
|
716
|
+
declare function deriveBaselineKey(wallet: BaselineWallet): Promise<CryptoKey>;
|
|
717
|
+
/**
|
|
718
|
+
* Derive the baseline AES key for `wallet`, reusing the cached derivation
|
|
719
|
+
* when one is in-flight or resolved for this wallet pubkey in the current
|
|
720
|
+
* page lifetime. The key is deterministic per wallet, so caching is purely
|
|
721
|
+
* a UX optimization (avoids re-prompting `signMessage` on every verification
|
|
722
|
+
* within a session). Cache survives a single page load and is dropped on
|
|
723
|
+
* reload or via `clearBaselineKeyCache`.
|
|
724
|
+
*
|
|
725
|
+
* Concurrent calls for the same wallet share one `signMessage` prompt; a
|
|
726
|
+
* failed derivation evicts the cache entry so subsequent calls re-derive.
|
|
727
|
+
*/
|
|
728
|
+
declare function getOrDeriveBaselineKey(wallet: BaselineWallet): Promise<CryptoKey>;
|
|
729
|
+
/** Drop all cached baseline keys. Test hook + emergency wipe. */
|
|
730
|
+
declare function clearBaselineKeyCache(): void;
|
|
731
|
+
/**
|
|
732
|
+
* Encrypt (simhash || salt) into a 96-byte versioned envelope.
|
|
733
|
+
*
|
|
734
|
+
* @param simhash 32-byte SimHash fingerprint (packed 256 bits)
|
|
735
|
+
* @param salt 32-byte Poseidon commitment salt
|
|
736
|
+
* @param key AES-256-GCM key from `deriveBaselineKey`
|
|
737
|
+
* @param walletPubkey wallet that owns the EncryptedBaseline PDA
|
|
738
|
+
* @param baselinePda the EncryptedBaseline PDA address (bound in AAD)
|
|
739
|
+
* @param commitment the on-chain `current_commitment` at encryption time
|
|
740
|
+
* (bound in AAD for staleness detection)
|
|
741
|
+
*/
|
|
742
|
+
declare function encryptBaselineBlob(simhash: Uint8Array, salt: Uint8Array, key: CryptoKey, walletPubkey: PublicKey, baselinePda: PublicKey, commitment: Uint8Array): Promise<Uint8Array>;
|
|
743
|
+
/**
|
|
744
|
+
* Thrown when the on-chain blob's auth tag fails to verify under the
|
|
745
|
+
* current on-chain commitment. Indicates the blob was sealed against a
|
|
746
|
+
* different commitment (e.g., before a `reset_identity_state`), or the
|
|
747
|
+
* AAD-binding is otherwise broken. The SDK should fall back to a fresh-
|
|
748
|
+
* capture flow rather than attempting to recover.
|
|
749
|
+
*/
|
|
750
|
+
declare class StaleEncryptedBaselineError extends Error {
|
|
751
|
+
constructor(message: string);
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Decrypt a 96-byte versioned envelope back to (simhash, salt).
|
|
755
|
+
*
|
|
756
|
+
* Throws `StaleEncryptedBaselineError` on auth-tag mismatch — this is the
|
|
757
|
+
* cryptographic staleness signal. Other errors indicate a malformed blob.
|
|
758
|
+
*/
|
|
759
|
+
declare function decryptBaselineBlob(blob: Uint8Array, key: CryptoKey, walletPubkey: PublicKey, baselinePda: PublicKey, commitment: Uint8Array): Promise<{
|
|
760
|
+
simhash: Uint8Array;
|
|
761
|
+
salt: Uint8Array;
|
|
762
|
+
}>;
|
|
763
|
+
/**
|
|
764
|
+
* Fetch the user's `EncryptedBaseline` PDA from chain. Returns `null` if
|
|
765
|
+
* the account has never been initialized (user hasn't called
|
|
766
|
+
* `set_encrypted_baseline` yet).
|
|
767
|
+
*/
|
|
768
|
+
declare function fetchEncryptedBaseline(walletPubkey: PublicKey, connection: {
|
|
769
|
+
getAccountInfo: (k: PublicKey) => Promise<unknown>;
|
|
770
|
+
}): Promise<Uint8Array | null>;
|
|
771
|
+
|
|
633
772
|
/**
|
|
634
773
|
* Fetch identity state from the on-chain IdentityState PDA.
|
|
635
774
|
*
|
|
@@ -664,6 +803,48 @@ declare function storeVerificationData(data: StoredVerificationData): Promise<vo
|
|
|
664
803
|
* Decrypts if encrypted, migrates plaintext to encrypted on first load.
|
|
665
804
|
*/
|
|
666
805
|
declare function loadVerificationData(): Promise<StoredVerificationData | null>;
|
|
806
|
+
/**
|
|
807
|
+
* Outcome of an attempt to recover the local baseline from the on-chain
|
|
808
|
+
* encrypted blob (master-list #98 cache-clear / cross-device path).
|
|
809
|
+
*
|
|
810
|
+
* Reasons distinguish recoverable from terminal failures:
|
|
811
|
+
* - `no-on-chain-identity`: caller should treat as first-verification.
|
|
812
|
+
* - `no-encrypted-baseline`: identity exists but user has never written
|
|
813
|
+
* an encrypted baseline (pre-3.3.0 SDK or pre-#98 deploy). UX should
|
|
814
|
+
* surface the existing baseline-missing copy and offer reset.
|
|
815
|
+
* - `signing-unavailable`: AES key derivation failed because the wallet
|
|
816
|
+
* can't `signMessage` (no method on the adapter, e.g., older Ledger
|
|
817
|
+
* firmware) OR the user cancelled the prompt OR the wallet erred. The
|
|
818
|
+
* `detail` field carries the specific cause when present.
|
|
819
|
+
* - `stale-baseline`: blob predates a `reset_identity_state` cycle.
|
|
820
|
+
* Treat as terminal recovery failure; route to fresh-capture flow.
|
|
821
|
+
* - `unknown-error`: catch-all (RPC failure, malformed blob, etc.).
|
|
822
|
+
*/
|
|
823
|
+
type BaselineRecoveryReason = "no-on-chain-identity" | "no-encrypted-baseline" | "signing-unavailable" | "stale-baseline" | "unknown-error";
|
|
824
|
+
interface BaselineRecoveryResult {
|
|
825
|
+
recovered: boolean;
|
|
826
|
+
reason?: BaselineRecoveryReason;
|
|
827
|
+
detail?: string;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Attempt to recover this wallet's local baseline from the on-chain
|
|
831
|
+
* `EncryptedBaseline` PDA. On success, writes the recovered fingerprint /
|
|
832
|
+
* salt / commitment / timestamp into the SDK's normal local storage tier
|
|
833
|
+
* so the next `loadVerificationData()` call returns it transparently.
|
|
834
|
+
*
|
|
835
|
+
* Wallet flow on success: ONE `signMessage` prompt (for the AES key
|
|
836
|
+
* derivation). The wallet's currently-cached key — if `getOrDeriveBaselineKey`
|
|
837
|
+
* has been called earlier in the session — short-circuits the prompt.
|
|
838
|
+
*
|
|
839
|
+
* No-op when:
|
|
840
|
+
* - The on-chain `IdentityState` PDA does not exist (treat as first-verify).
|
|
841
|
+
* - The on-chain `EncryptedBaseline` PDA does not exist (pre-#98 or wallet
|
|
842
|
+
* never had `set_encrypted_baseline` written — UX should offer reset).
|
|
843
|
+
* - The wallet lacks `signMessage` (some Ledger firmware versions).
|
|
844
|
+
* - The blob's auth tag doesn't verify under the current on-chain
|
|
845
|
+
* commitment (stale blob from a prior reset cycle).
|
|
846
|
+
*/
|
|
847
|
+
declare function recoverBaselineFromChain(wallet: BaselineWallet, connection: any): Promise<BaselineRecoveryResult>;
|
|
667
848
|
|
|
668
849
|
/**
|
|
669
850
|
* FALLBACK challenge-phrase generator. Used only when the executor's
|
|
@@ -770,4 +951,4 @@ declare function fetchChallenge(executorUrl: string, walletAddress: string, apiK
|
|
|
770
951
|
*/
|
|
771
952
|
declare function encodeAudioAsBase64(samples: Float32Array): string;
|
|
772
953
|
|
|
773
|
-
export { type AgentHumanOperator, type AudioCapture, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_AUDIO_SAMPLES, MIN_CAPTURE_MS, MIN_MOTION_SAMPLES, MIN_TOUCH_SAMPLES, MOTION_FEATURE_COUNT, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, TOUCH_FEATURE_COUNT, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, bigintToBytes32, computeCommitment, encodeAudioAsBase64, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchIdentityState, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, hammingDistance, loadVerificationData, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, verifyEntrosAttestation };
|
|
954
|
+
export { type AgentHumanOperator, type AudioCapture, type BaselineRecoveryReason, type BaselineRecoveryResult, type BaselineWallet, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, ENCRYPTED_BASELINE_BLOB_BYTES, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_AUDIO_SAMPLES, MIN_CAPTURE_MS, MIN_MOTION_SAMPLES, MIN_TOUCH_SAMPLES, MOTION_FEATURE_COUNT, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, StaleEncryptedBaselineError, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, TOUCH_FEATURE_COUNT, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, bigintToBytes32, bytes32ToBigint, bytesToFingerprint, clearBaselineKeyCache, computeCommitment, decryptBaselineBlob, deriveBaselineKey, deriveEncryptedBaselinePda, encodeAudioAsBase64, encryptBaselineBlob, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchEncryptedBaseline, fetchIdentityState, fingerprintToBytes, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, getOrDeriveBaselineKey, hammingDistance, loadVerificationData, packBits, prepareCircuitInput, randomLissajousParams, recoverBaselineFromChain, serializeProof, simhash, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, verifyEntrosAttestation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
|
|
1
3
|
declare const FINGERPRINT_BITS = 256;
|
|
2
4
|
declare const DEFAULT_THRESHOLD = 96;
|
|
3
5
|
declare const DEFAULT_MIN_DISTANCE = 3;
|
|
@@ -511,6 +513,15 @@ declare function submitViaWallet(proof: SolanaProof, commitment: Uint8Array, opt
|
|
|
511
513
|
* VerificationResult PDA instead.
|
|
512
514
|
*/
|
|
513
515
|
signedReceipt?: SignedReceiptDto;
|
|
516
|
+
/**
|
|
517
|
+
* Encrypted baseline blob (master-list #98). When present, the SDK
|
|
518
|
+
* appends a `set_encrypted_baseline` instruction at the end of the
|
|
519
|
+
* atomic transaction so the wallet's on-chain baseline is rewritten
|
|
520
|
+
* to reflect the new fingerprint in the same wallet prompt as the
|
|
521
|
+
* mint / re-verify. Omitted when the wallet adapter lacks
|
|
522
|
+
* `signMessage` (the SDK can't derive the AES key without it).
|
|
523
|
+
*/
|
|
524
|
+
encryptedBaselineBlob?: Uint8Array;
|
|
514
525
|
}): Promise<SubmissionResult>;
|
|
515
526
|
/**
|
|
516
527
|
* Submit a baseline reset on-chain via a connected wallet.
|
|
@@ -532,6 +543,15 @@ declare function submitResetViaWallet(commitment: Uint8Array, options: {
|
|
|
532
543
|
connection: any;
|
|
533
544
|
relayerUrl?: string;
|
|
534
545
|
relayerApiKey?: string;
|
|
546
|
+
/**
|
|
547
|
+
* Encrypted baseline blob (master-list #98). When present, the SDK
|
|
548
|
+
* appends a `set_encrypted_baseline` instruction so the wallet's
|
|
549
|
+
* on-chain baseline is rewritten under the NEW post-reset commitment
|
|
550
|
+
* in the same atomic transaction. Without this, the prior blob would
|
|
551
|
+
* be stale on the next recovery attempt (auth-tag mismatch under the
|
|
552
|
+
* new commitment in AAD) and recovery would fall back to fresh capture.
|
|
553
|
+
*/
|
|
554
|
+
encryptedBaselineBlob?: Uint8Array;
|
|
535
555
|
}): Promise<SubmissionResult>;
|
|
536
556
|
|
|
537
557
|
/**
|
|
@@ -630,6 +650,125 @@ interface StoredVerificationData {
|
|
|
630
650
|
timestamp: number;
|
|
631
651
|
}
|
|
632
652
|
|
|
653
|
+
/**
|
|
654
|
+
* Wallet-keyed encrypted baseline storage (master-list #98).
|
|
655
|
+
*
|
|
656
|
+
* Architecture: the user's previous SimHash + salt (private witnesses for
|
|
657
|
+
* the Hamming-distance ZK proof) are encrypted with AES-256-GCM under a
|
|
658
|
+
* key derived from a deterministic `signMessage` on a domain-separated
|
|
659
|
+
* payload. The 96-byte ciphertext blob is stored on chain in a per-wallet
|
|
660
|
+
* `EncryptedBaseline` PDA, making the baseline wallet-portable across
|
|
661
|
+
* devices and recoverable after a cache wipe.
|
|
662
|
+
*
|
|
663
|
+
* The GCM AAD binds (version, algorithm, wallet, baselinePda, current on-
|
|
664
|
+
* chain commitment). After `reset_identity_state` cycles the commitment,
|
|
665
|
+
* the old blob's auth-tag fails to verify under the new commitment — that
|
|
666
|
+
* mismatch IS the staleness signal. No explicit version tracking needed.
|
|
667
|
+
*
|
|
668
|
+
* Plaintext biometric data never reaches chain at any point. This module
|
|
669
|
+
* is the only place wallet-derived key material flows; it never leaves
|
|
670
|
+
* memory and the key is non-extractable.
|
|
671
|
+
*/
|
|
672
|
+
|
|
673
|
+
/** Layout: version(1) + algo(1) + reserved(2) + IV(12) + ct+tag(80) */
|
|
674
|
+
declare const ENCRYPTED_BASELINE_BLOB_BYTES = 96;
|
|
675
|
+
/**
|
|
676
|
+
* Pack a 256-bit fingerprint into 32 bytes. LSB-first within each byte —
|
|
677
|
+
* the convention is internal to the encrypted-baseline blob; the only
|
|
678
|
+
* requirement is that `bytesToFingerprint` is its exact inverse.
|
|
679
|
+
*/
|
|
680
|
+
declare function fingerprintToBytes(bits: number[]): Uint8Array;
|
|
681
|
+
/** Inverse of `fingerprintToBytes`. */
|
|
682
|
+
declare function bytesToFingerprint(bytes: Uint8Array): number[];
|
|
683
|
+
/** Big-endian 32-byte → BigInt. Inverse of `bigintToBytes32` in hashing/poseidon. */
|
|
684
|
+
declare function bytes32ToBigint(bytes: Uint8Array): bigint;
|
|
685
|
+
/**
|
|
686
|
+
* The per-wallet `EncryptedBaseline` PDA address. Owned by entros-anchor.
|
|
687
|
+
* Seeds: `[b"encrypted_baseline", walletPubkey.toBuffer()]`.
|
|
688
|
+
*/
|
|
689
|
+
declare function deriveEncryptedBaselinePda(walletPubkey: PublicKey): Promise<[PublicKey, number]>;
|
|
690
|
+
/**
|
|
691
|
+
* Wallet adapter shape needed for key derivation.
|
|
692
|
+
* Compatible with `@solana/wallet-adapter-base` `WalletAdapter`.
|
|
693
|
+
*/
|
|
694
|
+
interface BaselineWallet {
|
|
695
|
+
publicKey: PublicKey;
|
|
696
|
+
signMessage: (msg: Uint8Array) => Promise<Uint8Array>;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Derive an AES-256 key from the wallet's deterministic signature over
|
|
700
|
+
* the domain-separated payload, via HKDF-SHA256.
|
|
701
|
+
*
|
|
702
|
+
* IKM = Ed25519 signature (64 bytes, pseudorandom under RoM)
|
|
703
|
+
* salt = wallet pubkey bytes (32 bytes — wallet-binding salt)
|
|
704
|
+
* info = "entros-protocol/identity-baseline/v1"
|
|
705
|
+
* L = 32 bytes (AES-256 key length)
|
|
706
|
+
*
|
|
707
|
+
* Determinism follows from RFC 8032 Ed25519 signature determinism. Same
|
|
708
|
+
* wallet + same message → same signature → same key, across any device.
|
|
709
|
+
*
|
|
710
|
+
* The derived `CryptoKey` is non-extractable; only WebCrypto can use it
|
|
711
|
+
* for AES-GCM encrypt/decrypt.
|
|
712
|
+
*
|
|
713
|
+
* Throws if the wallet doesn't implement `signMessage` (e.g., some Ledger
|
|
714
|
+
* firmware versions). Callers should catch and fall back gracefully.
|
|
715
|
+
*/
|
|
716
|
+
declare function deriveBaselineKey(wallet: BaselineWallet): Promise<CryptoKey>;
|
|
717
|
+
/**
|
|
718
|
+
* Derive the baseline AES key for `wallet`, reusing the cached derivation
|
|
719
|
+
* when one is in-flight or resolved for this wallet pubkey in the current
|
|
720
|
+
* page lifetime. The key is deterministic per wallet, so caching is purely
|
|
721
|
+
* a UX optimization (avoids re-prompting `signMessage` on every verification
|
|
722
|
+
* within a session). Cache survives a single page load and is dropped on
|
|
723
|
+
* reload or via `clearBaselineKeyCache`.
|
|
724
|
+
*
|
|
725
|
+
* Concurrent calls for the same wallet share one `signMessage` prompt; a
|
|
726
|
+
* failed derivation evicts the cache entry so subsequent calls re-derive.
|
|
727
|
+
*/
|
|
728
|
+
declare function getOrDeriveBaselineKey(wallet: BaselineWallet): Promise<CryptoKey>;
|
|
729
|
+
/** Drop all cached baseline keys. Test hook + emergency wipe. */
|
|
730
|
+
declare function clearBaselineKeyCache(): void;
|
|
731
|
+
/**
|
|
732
|
+
* Encrypt (simhash || salt) into a 96-byte versioned envelope.
|
|
733
|
+
*
|
|
734
|
+
* @param simhash 32-byte SimHash fingerprint (packed 256 bits)
|
|
735
|
+
* @param salt 32-byte Poseidon commitment salt
|
|
736
|
+
* @param key AES-256-GCM key from `deriveBaselineKey`
|
|
737
|
+
* @param walletPubkey wallet that owns the EncryptedBaseline PDA
|
|
738
|
+
* @param baselinePda the EncryptedBaseline PDA address (bound in AAD)
|
|
739
|
+
* @param commitment the on-chain `current_commitment` at encryption time
|
|
740
|
+
* (bound in AAD for staleness detection)
|
|
741
|
+
*/
|
|
742
|
+
declare function encryptBaselineBlob(simhash: Uint8Array, salt: Uint8Array, key: CryptoKey, walletPubkey: PublicKey, baselinePda: PublicKey, commitment: Uint8Array): Promise<Uint8Array>;
|
|
743
|
+
/**
|
|
744
|
+
* Thrown when the on-chain blob's auth tag fails to verify under the
|
|
745
|
+
* current on-chain commitment. Indicates the blob was sealed against a
|
|
746
|
+
* different commitment (e.g., before a `reset_identity_state`), or the
|
|
747
|
+
* AAD-binding is otherwise broken. The SDK should fall back to a fresh-
|
|
748
|
+
* capture flow rather than attempting to recover.
|
|
749
|
+
*/
|
|
750
|
+
declare class StaleEncryptedBaselineError extends Error {
|
|
751
|
+
constructor(message: string);
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Decrypt a 96-byte versioned envelope back to (simhash, salt).
|
|
755
|
+
*
|
|
756
|
+
* Throws `StaleEncryptedBaselineError` on auth-tag mismatch — this is the
|
|
757
|
+
* cryptographic staleness signal. Other errors indicate a malformed blob.
|
|
758
|
+
*/
|
|
759
|
+
declare function decryptBaselineBlob(blob: Uint8Array, key: CryptoKey, walletPubkey: PublicKey, baselinePda: PublicKey, commitment: Uint8Array): Promise<{
|
|
760
|
+
simhash: Uint8Array;
|
|
761
|
+
salt: Uint8Array;
|
|
762
|
+
}>;
|
|
763
|
+
/**
|
|
764
|
+
* Fetch the user's `EncryptedBaseline` PDA from chain. Returns `null` if
|
|
765
|
+
* the account has never been initialized (user hasn't called
|
|
766
|
+
* `set_encrypted_baseline` yet).
|
|
767
|
+
*/
|
|
768
|
+
declare function fetchEncryptedBaseline(walletPubkey: PublicKey, connection: {
|
|
769
|
+
getAccountInfo: (k: PublicKey) => Promise<unknown>;
|
|
770
|
+
}): Promise<Uint8Array | null>;
|
|
771
|
+
|
|
633
772
|
/**
|
|
634
773
|
* Fetch identity state from the on-chain IdentityState PDA.
|
|
635
774
|
*
|
|
@@ -664,6 +803,48 @@ declare function storeVerificationData(data: StoredVerificationData): Promise<vo
|
|
|
664
803
|
* Decrypts if encrypted, migrates plaintext to encrypted on first load.
|
|
665
804
|
*/
|
|
666
805
|
declare function loadVerificationData(): Promise<StoredVerificationData | null>;
|
|
806
|
+
/**
|
|
807
|
+
* Outcome of an attempt to recover the local baseline from the on-chain
|
|
808
|
+
* encrypted blob (master-list #98 cache-clear / cross-device path).
|
|
809
|
+
*
|
|
810
|
+
* Reasons distinguish recoverable from terminal failures:
|
|
811
|
+
* - `no-on-chain-identity`: caller should treat as first-verification.
|
|
812
|
+
* - `no-encrypted-baseline`: identity exists but user has never written
|
|
813
|
+
* an encrypted baseline (pre-3.3.0 SDK or pre-#98 deploy). UX should
|
|
814
|
+
* surface the existing baseline-missing copy and offer reset.
|
|
815
|
+
* - `signing-unavailable`: AES key derivation failed because the wallet
|
|
816
|
+
* can't `signMessage` (no method on the adapter, e.g., older Ledger
|
|
817
|
+
* firmware) OR the user cancelled the prompt OR the wallet erred. The
|
|
818
|
+
* `detail` field carries the specific cause when present.
|
|
819
|
+
* - `stale-baseline`: blob predates a `reset_identity_state` cycle.
|
|
820
|
+
* Treat as terminal recovery failure; route to fresh-capture flow.
|
|
821
|
+
* - `unknown-error`: catch-all (RPC failure, malformed blob, etc.).
|
|
822
|
+
*/
|
|
823
|
+
type BaselineRecoveryReason = "no-on-chain-identity" | "no-encrypted-baseline" | "signing-unavailable" | "stale-baseline" | "unknown-error";
|
|
824
|
+
interface BaselineRecoveryResult {
|
|
825
|
+
recovered: boolean;
|
|
826
|
+
reason?: BaselineRecoveryReason;
|
|
827
|
+
detail?: string;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Attempt to recover this wallet's local baseline from the on-chain
|
|
831
|
+
* `EncryptedBaseline` PDA. On success, writes the recovered fingerprint /
|
|
832
|
+
* salt / commitment / timestamp into the SDK's normal local storage tier
|
|
833
|
+
* so the next `loadVerificationData()` call returns it transparently.
|
|
834
|
+
*
|
|
835
|
+
* Wallet flow on success: ONE `signMessage` prompt (for the AES key
|
|
836
|
+
* derivation). The wallet's currently-cached key — if `getOrDeriveBaselineKey`
|
|
837
|
+
* has been called earlier in the session — short-circuits the prompt.
|
|
838
|
+
*
|
|
839
|
+
* No-op when:
|
|
840
|
+
* - The on-chain `IdentityState` PDA does not exist (treat as first-verify).
|
|
841
|
+
* - The on-chain `EncryptedBaseline` PDA does not exist (pre-#98 or wallet
|
|
842
|
+
* never had `set_encrypted_baseline` written — UX should offer reset).
|
|
843
|
+
* - The wallet lacks `signMessage` (some Ledger firmware versions).
|
|
844
|
+
* - The blob's auth tag doesn't verify under the current on-chain
|
|
845
|
+
* commitment (stale blob from a prior reset cycle).
|
|
846
|
+
*/
|
|
847
|
+
declare function recoverBaselineFromChain(wallet: BaselineWallet, connection: any): Promise<BaselineRecoveryResult>;
|
|
667
848
|
|
|
668
849
|
/**
|
|
669
850
|
* FALLBACK challenge-phrase generator. Used only when the executor's
|
|
@@ -770,4 +951,4 @@ declare function fetchChallenge(executorUrl: string, walletAddress: string, apiK
|
|
|
770
951
|
*/
|
|
771
952
|
declare function encodeAudioAsBase64(samples: Float32Array): string;
|
|
772
953
|
|
|
773
|
-
export { type AgentHumanOperator, type AudioCapture, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_AUDIO_SAMPLES, MIN_CAPTURE_MS, MIN_MOTION_SAMPLES, MIN_TOUCH_SAMPLES, MOTION_FEATURE_COUNT, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, TOUCH_FEATURE_COUNT, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, bigintToBytes32, computeCommitment, encodeAudioAsBase64, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchIdentityState, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, hammingDistance, loadVerificationData, packBits, prepareCircuitInput, randomLissajousParams, serializeProof, simhash, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, verifyEntrosAttestation };
|
|
954
|
+
export { type AgentHumanOperator, type AudioCapture, type BaselineRecoveryReason, type BaselineRecoveryResult, type BaselineWallet, type CaptureOptions, type CaptureStage, type ChallengeResponse, type CircuitInput, DEFAULT_CAPTURE_MS, DEFAULT_MIN_DISTANCE, DEFAULT_THRESHOLD, ENCRYPTED_BASELINE_BLOB_BYTES, type EntrosAttestation, FINGERPRINT_BITS, type FeatureVector, type FusedFeatureVector, type IdentityState, type LissajousParams, MAX_CAPTURE_MS, MIN_AUDIO_SAMPLES, MIN_CAPTURE_MS, MIN_MOTION_SAMPLES, MIN_TOUCH_SAMPLES, MOTION_FEATURE_COUNT, type MotionSample, PROGRAM_IDS, type PackedFingerprint, type Point2D, type ProofResult, type PulseConfig, PulseSDK, PulseSession, SPEAKER_FEATURE_COUNT, type SensorData, type SolanaProof, type StageState, StaleEncryptedBaselineError, type StatsSummary, type StoredVerificationData, type SubmissionResult, type TBH, TOUCH_FEATURE_COUNT, type TemporalFingerprint, type TouchSample, type VerificationResult, attestAgentOperator, bigintToBytes32, bytes32ToBigint, bytesToFingerprint, clearBaselineKeyCache, computeCommitment, decryptBaselineBlob, deriveBaselineKey, deriveEncryptedBaselinePda, encodeAudioAsBase64, encryptBaselineBlob, extractAccelerationMagnitude, extractMotionFeatures, extractMouseDynamics, extractSpeakerFeatures, extractSpeakerFeaturesDetailed, extractTouchFeatures, fetchChallenge, fetchEncryptedBaseline, fetchIdentityState, fingerprintToBytes, fuseFeatures, fuseRawFeatures, generateLissajousPoints, generateLissajousSequence, generatePhrase, generatePhraseSequence, generateProof, generateSalt, generateSolanaProof, generateTBH, getAgentHumanOperator, getOrDeriveBaselineKey, hammingDistance, loadVerificationData, packBits, prepareCircuitInput, randomLissajousParams, recoverBaselineFromChain, serializeProof, simhash, storeVerificationData, submitResetViaWallet, submitViaRelayer, submitViaWallet, toBigEndian32, verifyEntrosAttestation };
|