SparkSigner interface to enable flexible implementation of signing operations. This abstraction allows you to customize how cryptographic operations are performed, enabling support for secure enclaves, hardware wallets, remote signing services, and other specialized key management systems.
The SDK includes
DefaultSparkSigner which handles standard single-signature operations and stores nonces internally for security. For server-side enclave integrations, UnsafeStatelessSparkSigner is available.Core Concepts
Key Types
Spark wallets derive 5 key types from a master seed using BIP32:The KeyDerivation System
The signer uses a discriminated union type to specify how to derive or retrieve a private key for signing operations:signFrost() and getPublicKeyFromDerivation().
Security Model
- All private keys are derived from a master seed using BIP32 hierarchical deterministic key derivation
- Private keys never leave the signer. Only signatures and public keys are returned.
DefaultSparkSignerstores nonces internally to prevent reuse attacks- For enclave integrations,
UnsafeStatelessSparkSignerexposes nonces externally
Implementations
DefaultSparkSigner
The recommended implementation for client-side applications. It stores signing nonces internally to prevent reuse attacks.UnsafeStatelessSparkSigner
For server-side enclave integrations where nonces need to be managed externally. This signer returns nonces ingetRandomSigningCommitment() instead of storing them internally.
Custom Signer Implementation
You can extendDefaultSparkSigner to implement custom signing logic, such as forwarding requests to a secure enclave:
Custom Key Derivation Paths
If you need a non-standard derivation scheme, you can pass a customsparkKeysGenerator to DefaultSparkSigner.
This example shows a simple generator that replaces ? with the accountNumber and then derives the five Spark key roots under that account:
Wallet Initialization
Generate Mnemonic
generateMnemonic()
Generates a new BIP39 mnemonic phrase for wallet creation.
Convert Mnemonic to Seed
mnemonicToSeed(mnemonic)
Converts a BIP39 mnemonic phrase to a cryptographic seed.
Initialize from Seed
createSparkWalletFromSeed(seed, accountNumber?)
Initializes the signer with a master seed and derives all necessary keys.
Key Management
Get Identity Public Key
getIdentityPublicKey()
Retrieves the wallet’s identity public key.
Get Deposit Signing Key
getDepositSigningKey()
Retrieves the deposit signing public key used for L1 Bitcoin deposits.
Get Static Deposit Signing Key
getStaticDepositSigningKey(idx)
Retrieves a static deposit signing public key by index.
Get Static Deposit Secret Key
getStaticDepositSecretKey(idx)
Retrieves a static deposit private key by index. Used when the private key needs to be shared with the SSP for static deposit flows.
Get Public Key from Derivation
getPublicKeyFromDerivation(keyDerivation)
Derives a public key based on a KeyDerivation specification.
Digital Signatures
Sign with Identity Key
signMessageWithIdentityKey(message, compact?)
Signs a message using the wallet’s identity key with ECDSA.
Validate Signature
validateMessageWithIdentityKey(message, signature)
Validates an ECDSA signature against the identity key.
Sign with Schnorr (Identity Key)
signSchnorrWithIdentityKey(message)
Creates a Schnorr signature using the identity key.
Sign Transaction Index
signTransactionIndex(tx, index, publicKey)
Signs a specific input of a Bitcoin transaction. The method looks up the private key based on the provided public key (must be either identity or deposit key).
FROST Protocol (Threshold Signatures)
Spark uses FROST (Flexible Round-Optimized Schnorr Threshold) signatures for collaborative signing between users and Signing Operators.Get Random Signing Commitment
getRandomSigningCommitment()
Generates a random signing commitment for FROST protocol. In DefaultSparkSigner, the nonce is stored internally. In UnsafeStatelessSparkSigner, the nonce is returned in the response.
Get Nonce for Commitment
getNonceForSelfCommitment(selfCommitment)
Retrieves the nonce associated with a previously generated commitment. In DefaultSparkSigner, this looks up the internally stored nonce. In UnsafeStatelessSparkSigner, this returns the nonce from the commitment object.
FROST Signing
signFrost(params)
Performs FROST signing operation. This produces the user’s signature share that will be combined with Signing Operator shares.
Aggregate FROST Signatures
aggregateFrost(params)
Aggregates FROST signature shares (user’s + Signing Operators’) into a final Schnorr signature.
Secret Sharing
These methods implement Shamir’s Secret Sharing with verifiable proofs, used internally for key splitting operations.Split Secret with Proofs
splitSecretWithProofs(params)
Splits a secret into shares using Shamir’s Secret Sharing with verifiable proofs.
Subtract and Split with Proofs
subtractAndSplitSecretWithProofsGivenDerivations(params)
Subtracts two derived private keys and splits the result into verifiable shares. Used in transfer flows.
Subtract, Split, and Encrypt
subtractSplitAndEncrypt(params)
Subtracts keys, splits into shares, and encrypts the second key for the receiver. Used in transfer operations.
Encryption
Decrypt ECIES
decryptEcies(ciphertext)
Decrypts ECIES-encrypted data using the identity key. Returns the public key corresponding to the decrypted private key.
HTLC Operations
Generate HTLC HMAC
htlcHMAC(transferID)
Generates an HMAC for HTLC (Hash Time-Locked Contract) operations using the HTLC preimage key.
Complete Example
Integration Patterns
Remote Signer (Enclave Pattern)
For wallet providers that need to keep keys in a secure enclave:Multi-User Wallet Pattern
For services managing wallets for multiple users:For multi-user wallets, consider the trust model carefully. See the Alby architecture blog post for a trust-minimized approach using NWC.