Skip to main content

SDK Security Model

The SDK is built so that the safe path is also the default path. Cryptography runs locally, secrets are hard to leak by accident, and the only code that talks to the network is code you construct yourself.

This page covers the SDK boundary. For the protocol's broader threat model, including the quantum adversary and what SPECTER does not hide, read security boundaries.

Local by default

Key generation, encapsulation, decapsulation, and stealth derivation all run on the device through WebAssembly. The local functions never send secrets over the network.

The cryptography is compiled from pinned Rust crates, the same core that backs the CLI and the hosted backend. There is no separate JavaScript reimplementation of the primitives to audit.

Secret-bearing fields

Some return values carry material that can spend funds or detect payments: secretKey, sharedSecret, and ethPrivateKey. The SDK protects these against the most common leak, which is logging.

These fields are:

  • non-enumerable, so they do not show up in a plain object spread or iteration,
  • redacted from JSON.stringify,
  • redacted from Node's inspect and console output.
const enc = encapsulate(recipient.viewing.publicKey);
console.log(enc);
// sharedSecret prints as a redacted placeholder, not the bytes
Warning

Redaction protects against accidental logging. It does not stop your own code from reading the value and copying it somewhere unsafe. If you assign ethPrivateKey to a new variable and log that, it leaks. Keep secrets inside the signing path.

Input and output validation

The SDK validates inputs and checks output lengths against the known sizes. A wrong key length, a malformed ciphertext, or bad hex fails fast with a typed SpecterSdkError rather than producing silent garbage.

When the SDK uses the network

Local crypto helpers are offline. Network calls happen in exactly one place: the trusted API client you create with createSpecterApiClient. If you never call that constructor, the SDK never opens a connection.

FunctionNetworkSecret exposure
generateSpecterKeys, generateKeysLocalNoneNone
encapsulate, decapsulateNoneNone
createStealthPaymentNoneNone
scanAnnouncement, scanAnnouncementsNoneNone
generateKeysRemoteYesServer generates and sees the keys
createStealthPaymentRemoteYesMeta-address only
publishAnnouncementYesAnnouncement data only
scanRemoteYesSends the viewing secret key

Using the remote helpers safely

generateKeysRemote and scanRemote are useful when a backend owns the whole flow, but they move secret material off the device. If you use them:

  • Point them only at infrastructure you control.
  • Require TLS.
  • Put your own authorization boundary in front of the API.

For wallets and anything holding user funds, prefer the local equivalents. They never leave the machine.

Disclosure

Report vulnerabilities privately to hello@specterpq.com, not through public issues. The full policy lives in SECURITY.md in the SDK repository.