Skip to main content
Learn how to implement and use the Spark Signer interface for cryptographic operations. This guide covers the complete SparkSigner interface, key management, and advanced cryptographic features. The Spark SDK provides the SparkSigner interface to enable flexible implementation of signing operations. This abstraction allows you to customize how cryptographic operations are performed and enables support for different signing strategies including multisig configurations, hardware wallets, and other specialized key management systems.
The SDK includes a default implementation (DefaultSparkSigner) that handles standard single-signature operations. This can serve as a reference for implementing custom signers that support multisig, hardware wallets, or other advanced signing schemes.

Core Concepts

Key Types

Identity Key

Primary wallet identifier used for authentication and Spark Address generation

Signing Keys

Derived keys for specific transaction outputs and operations

Deposit Keys

Keys for receiving L1 Bitcoin deposits

Static Deposit Keys

Reusable keys for deposit operations

Security Model

All private keys are derived from a master seed using BIP32 hierarchical deterministic key derivation. The signer maintains an internal mapping between public keys and their corresponding private keys, ensuring secure access control.

Wallet Initialization

Generate Mnemonic

generateMnemonic() Generates a new BIP39 mnemonic phrase for wallet creation.
const mnemonic = await signer.generateMnemonic();
console.log(mnemonic); // "abandon ability able about above absent..."

Convert Mnemonic to Seed

mnemonicToSeed(mnemonic) Converts a BIP39 mnemonic phrase to a cryptographic seed.
const seed = await signer.mnemonicToSeed(mnemonic);
console.log("Seed length:", seed.length); // 64 bytes

Initialize from Seed

createSparkWalletFromSeed(seed, accountNumber?) Initializes the signer with a master seed and derives all necessary keys.
const seed = await signer.mnemonicToSeed(mnemonic);
const identityPubKey = await signer.createSparkWalletFromSeed(seed, 0);
console.log("Identity public key:", identityPubKey);

Key Management

Get Identity Public Key

getIdentityPublicKey() Retrieves the wallet’s identity public key.
const identityKey = await signer.getIdentityPublicKey();
console.log("Identity key:", identityKey);

Get Master Public Key

getMasterPublicKey() Retrieves the master public key.
const masterKey = await signer.getMasterPublicKey();
console.log("Master public key:", masterKey);

Generate Public Key

generatePublicKey(hash?) Generates a new signing key pair and returns the public key.
const publicKey = await signer.generatePublicKey();
console.log("Generated public key:", publicKey);

// With deterministic hash
const hash = new Uint8Array(32);
const deterministicKey = await signer.generatePublicKey(hash);

Remove Public Key

removePublicKey(publicKey) Removes a public key from the signer’s tracked keys.
await signer.removePublicKey(publicKey);
console.log("Public key removed");

Get Tracked Public Keys

getTrackedPublicKeys() Returns all currently tracked public keys.
const trackedKeys = await signer.getTrackedPublicKeys();
console.log("Tracked keys:", trackedKeys.length);

Deposit Address Management

Get Deposit Signing Key

getDepositSigningKey() Retrieves the deposit signing public key.
const depositKey = await signer.getDepositSigningKey();
console.log("Deposit signing key:", depositKey);

Generate Static Deposit Key

generateStaticDepositKey(idx) Generates or retrieves a static deposit key by index.
const staticDepositKey = await signer.generateStaticDepositKey(0);
console.log("Static deposit key:", staticDepositKey);

Get Static Deposit Signing Key

getStaticDepositSigningKey(idx) Retrieves a static deposit signing key by index.
const signingKey = await signer.getStaticDepositSigningKey(0);
console.log("Static deposit signing key:", signingKey);

Get Static Deposit Secret Key

getStaticDepositSecretKey(idx) Retrieves a static deposit private key by index.
const secretKey = await signer.getStaticDepositSecretKey(0);
console.log("Static deposit secret key:", secretKey);

Digital Signatures

Sign with Identity Key

signMessageWithIdentityKey(message, compact?) Signs a message using the wallet’s identity key.
const message = new TextEncoder().encode("Hello, Spark!");
const signature = await signer.signMessageWithIdentityKey(message);
console.log("Signature:", signature);

// With compact format
const compactSignature = await signer.signMessageWithIdentityKey(message, true);

Sign with Public Key

signMessageWithPublicKey(message, publicKey, compact?) Signs a message using a specific public key.
const message = new TextEncoder().encode("Hello, Spark!");
const publicKey = await signer.generatePublicKey();
const signature = await signer.signMessageWithPublicKey(message, publicKey);
console.log("Signature:", signature);

Validate Signature

validateMessageWithIdentityKey(message, signature) Validates a signature against the identity key.
const message = new TextEncoder().encode("Hello, Spark!");
const signature = await signer.signMessageWithIdentityKey(message);
const isValid = await signer.validateMessageWithIdentityKey(message, signature);
console.log("Signature valid:", isValid);

Schnorr Signatures

Get Schnorr Public Key

getSchnorrPublicKey(publicKey) Converts a secp256k1 public key to Schnorr format.
const publicKey = await signer.generatePublicKey();
const schnorrKey = await signer.getSchnorrPublicKey(publicKey);
console.log("Schnorr public key:", schnorrKey);

Sign with Schnorr

signSchnorr(message, publicKey) Creates a Schnorr signature for a message.
const message = new TextEncoder().encode("Hello, Spark!");
const publicKey = await signer.generatePublicKey();
const schnorrSignature = await signer.signSchnorr(message, publicKey);
console.log("Schnorr signature:", schnorrSignature);

Sign with Identity Key (Schnorr)

signSchnorrWithIdentityKey(message) Creates a Schnorr signature using the identity key.
const message = new TextEncoder().encode("Hello, Spark!");
const schnorrSignature = await signer.signSchnorrWithIdentityKey(message);
console.log("Schnorr signature:", schnorrSignature);

Advanced Cryptographic Operations

Restore Signing Keys

restoreSigningKeysFromLeafs(leafs) Restores signing keys from a set of tree leaf nodes.
const leafs = [/* TreeNode array */];
await signer.restoreSigningKeysFromLeafs(leafs);
console.log("Signing keys restored");

Private Key Subtraction

subtractPrivateKeysGivenPublicKeys(first, second) Performs private key subtraction and returns the resulting public key.
const firstKey = await signer.generatePublicKey();
const secondKey = await signer.generatePublicKey();
const resultKey = await signer.subtractPrivateKeysGivenPublicKeys(firstKey, secondKey);
console.log("Result key:", resultKey);

Secret Sharing

splitSecretWithProofs(params) Implements Shamir’s Secret Sharing with verifiable proofs.
const params = {
  secret: new Uint8Array(32),
  curveOrder: BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"),
  threshold: 3,
  numShares: 5,
  isSecretPubkey: false
};

const shares = await signer.splitSecretWithProofs(params);
console.log("Secret shares:", shares.length);

FROST Protocol (Threshold Signatures)

Get Random Signing Commitment

getRandomSigningCommitment() Generates a random signing commitment for FROST protocol.
const commitment = await signer.getRandomSigningCommitment();
console.log("Signing commitment:", commitment);

FROST Signing

signFrost(params) Performs FROST signing operation.
const params = {
  message: new TextEncoder().encode("Hello, FROST!"),
  privateAsPubKey: await signer.generatePublicKey(),
  publicKey: await signer.generatePublicKey(),
  verifyingKey: await signer.generatePublicKey(),
  selfCommitment: await signer.getRandomSigningCommitment(),
  statechainCommitments: {},
  adaptorPubKey: await signer.generatePublicKey()
};

const frostSignature = await signer.signFrost(params);
console.log("FROST signature:", frostSignature);

Aggregate FROST Signatures

aggregateFrost(params) Aggregates FROST signature shares into a final signature.
const params = {
  message: new TextEncoder().encode("Hello, FROST!"),
  publicKey: await signer.generatePublicKey(),
  verifyingKey: await signer.generatePublicKey(),
  selfCommitment: await signer.getRandomSigningCommitment(),
  selfSignature: new Uint8Array(64),
  statechainSignatures: {},
  statechainPublicKeys: {}
};

const finalSignature = await signer.aggregateFrost(params);
console.log("Final signature:", finalSignature);

Encryption

Encrypt Leaf Private Key

encryptLeafPrivateKeyEcies(receiverPublicKey, publicKey) Encrypts a leaf private key using ECIES.
const receiverPublicKey = await signer.generatePublicKey();
const publicKey = await signer.generatePublicKey();
const encryptedKey = await signer.encryptLeafPrivateKeyEcies(receiverPublicKey, publicKey);
console.log("Encrypted key:", encryptedKey);

Decrypt ECIES

decryptEcies(ciphertext) Decrypts ECIES-encrypted data using the identity key.
const ciphertext = new Uint8Array(/* encrypted data */);
const decryptedData = await signer.decryptEcies(ciphertext);
console.log("Decrypted data:", decryptedData);

Utility Functions

Hash Random Private Key

hashRandomPrivateKey() Generates a hash of a random private key.
const hash = await signer.hashRandomPrivateKey();
console.log("Random key hash:", hash);

Generate Adaptor Signature

generateAdaptorFromSignature(signature) Generates an adaptor signature from a regular signature.
const signature = new Uint8Array(64);
const adaptor = await signer.generateAdaptorFromSignature(signature);
console.log("Adaptor signature:", adaptor.adaptorSignature);
console.log("Adaptor public key:", adaptor.adaptorPublicKey);

Complete Example

import { SparkSigner } from "@buildonspark/spark-sdk";

async function demonstrateSparkSigner() {
  // Initialize signer (this would be your custom implementation)
  const signer = new SparkSigner();

  try {
    // 1. Generate mnemonic and initialize
    const mnemonic = await signer.generateMnemonic();
    console.log("Generated mnemonic:", mnemonic);

    const seed = await signer.mnemonicToSeed(mnemonic);
    const identityKey = await signer.createSparkWalletFromSeed(seed, 0);
    console.log("Identity key:", identityKey);

    // 2. Generate and manage keys
    const publicKey = await signer.generatePublicKey();
    console.log("Generated public key:", publicKey);

    const trackedKeys = await signer.getTrackedPublicKeys();
    console.log("Tracked keys:", trackedKeys.length);

    // 3. Sign messages
    const message = new TextEncoder().encode("Hello, Spark Signer!");
    
    // ECDSA signature
    const ecdsaSignature = await signer.signMessageWithIdentityKey(message);
    console.log("ECDSA signature:", ecdsaSignature);

    // Schnorr signature
    const schnorrSignature = await signer.signSchnorrWithIdentityKey(message);
    console.log("Schnorr signature:", schnorrSignature);

    // 4. Validate signature
    const isValid = await signer.validateMessageWithIdentityKey(message, ecdsaSignature);
    console.log("Signature valid:", isValid);

    // 5. Deposit key management
    const depositKey = await signer.getDepositSigningKey();
    console.log("Deposit key:", depositKey);

    const staticDepositKey = await signer.generateStaticDepositKey(0);
    console.log("Static deposit key:", staticDepositKey);

  } catch (error) {
    console.error("Spark Signer operation failed:", error);
  }
}