skills/message-signing/SKILL.md
This skill should be used when the user asks to "sign a message", "verify a signature", "use BSM", "use BRC-77", "implement Sigma signing", "create signed messages", "authenticate with Bitcoin", "sign with AIP", "AIP protocol", or mentions message signing, signature verification, ECDSA signatures, or authentication protocols on BSV.
npx skillsauth add b-open-io/bsv-skills message-signingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Three approaches for message signing on BSV, from simple to full-featured.
| Approach | Package | Use Case |
|----------|---------|----------|
| Direct SDK | @bsv/sdk | Simple message signing (BSM, BRC-77) |
| Templates | @1sat/templates | Script parsing/creation for protocols |
| Sigma Protocol | sigma-protocol | Transaction-bound signatures |
For simple message authentication without transaction context.
import { BSM, PrivateKey, Signature, BigNumber } from "@bsv/sdk";
const privateKey = PrivateKey.fromWif("L1...");
const message = [/* byte array */];
// Sign
const signature = BSM.sign(message, privateKey, "raw") as Signature;
const h = new BigNumber(BSM.magicHash(message));
const recovery = signature.CalculateRecoveryFactor(privateKey.toPublicKey(), h);
const compactSig = signature.toCompact(recovery, true, "base64");
// Verify - recover public key and check address
const sig = Signature.fromCompact(compactSig, "base64");
for (let r = 0; r < 4; r++) {
try {
const pubKey = sig.RecoverPublicKey(r, new BigNumber(BSM.magicHash(message)));
if (BSM.verify(message, sig, pubKey)) {
console.log("Signer:", pubKey.toAddress());
break;
}
} catch { /* try next */ }
}
import { SignedMessage, PrivateKey, PublicKey } from "@bsv/sdk";
const signer = PrivateKey.fromWif("L1...");
const message = [/* byte array */];
// Public signature (anyone can verify)
const sig = SignedMessage.sign(message, signer);
const valid = SignedMessage.verify(message, sig);
// Private signature (only recipient can verify)
const recipientPubKey = PublicKey.fromString("02...");
const privateSig = SignedMessage.sign(message, signer, recipientPubKey);
const recipientKey = PrivateKey.fromWif("K1...");
const privateValid = SignedMessage.verify(message, privateSig, recipientKey);
See: examples/bsm-sign-verify.ts, examples/brc77-private-sig.ts
For working with BitCom protocols and script parsing. Uses @1sat/templates.
import { Sigma, SigmaAlgorithm, BitCom } from "@1sat/templates";
import { PrivateKey, Hash } from "@bsv/sdk";
// Decode from existing script
const bitcom = BitCom.decode(script);
const sigmas = Sigma.decode(bitcom);
// Create signature (given pre-computed hashes)
const inputHash = Array.from(Hash.sha256(outpointBytes));
const dataHash = Array.from(Hash.sha256(scriptDataBytes));
const sigma = Sigma.sign(inputHash, dataHash, privateKey, {
algorithm: SigmaAlgorithm.BRC77, // or SigmaAlgorithm.BSM
vin: 0
});
// Verify
const valid = sigma.verifyWithHashes(inputHash, dataHash);
// Generate locking script
const lockingScript = sigma.lock();
AIP.sign() accepts a Signer — either PrivateKeySigner (raw key) or WalletSigner (BRC-100 wallet).
import { AIP, BitCom, PrivateKeySigner, WalletSigner } from "@1sat/templates";
// Decode AIP from script
const bitcom = BitCom.decode(script);
const aips = AIP.decode(bitcom);
// Sign with raw PrivateKey
const signer = new PrivateKeySigner(privateKey);
const aip = await AIP.sign(dataBytes, signer);
// Sign with BRC-100 wallet (uses BAP identity key derivation)
const walletSigner = new WalletSigner(wallet, [1, "bapid"], "identity", "self");
const aip2 = await AIP.sign(dataBytes, walletSigner);
const valid = aip.verify();
The applyAip helper signs OP_RETURN data and appends the AIP suffix to a locking script:
import { applyAip } from '@1sat/actions'
// ctx is a OneSatContext with a BRC-100 wallet
const signedScript = await applyAip(ctx, lockingScript)
// Appends: | AIP_PREFIX BITCOIN_ECDSA <address> <compactSig>
Uses the wallet's BAP identity key (protocolID: [1, "bapid"], keyID: "identity"). Delegates signing to AIP.sign() from templates via WalletSigner.
See: examples/sigma-template.ts
Note: Sigma template requires sigma-protocol as peer dependency for Algorithm enum.
For complete transaction-bound signatures. Use when:
bun add sigma-protocol
import { Sigma, Algorithm } from "sigma-protocol";
import { Transaction, PrivateKey } from "@bsv/sdk";
// Create Sigma instance
const sigma = new Sigma(tx, targetVout, sigmaInstance, refVin);
// Sign with BSM (default)
const { signedTx } = sigma.sign(privateKey);
// Sign with BRC-77
const { signedTx: tx2 } = sigma.sign(privateKey, Algorithm.BRC77);
// Sign with BRC-77 for specific verifier (private)
const { signedTx: tx3 } = sigma.sign(privateKey, Algorithm.BRC77, verifierPubKey);
// Verify
const valid = sigma.verify();
const privateValid = sigma.verify(recipientPrivateKey); // for private BRC-77
// First signature (user with BSM)
const sigma1 = new Sigma(tx, 0, 0);
const { signedTx } = sigma1.sign(userKey, Algorithm.BSM);
// Second signature (platform with BRC-77)
const sigma2 = new Sigma(signedTx, 0, 1);
sigma2.sign(platformKey, Algorithm.BRC77);
// Verify each
sigma2.setSigmaInstance(0);
sigma2.verify(); // User
sigma2.setSigmaInstance(1);
sigma2.verify(); // Platform
See: examples/sigma-multi-sig.ts
| Feature | BSM | BRC-77 |
|---------|-----|--------|
| Key derivation | Direct | Child key per message |
| Recovery | From signature | Embedded in signature |
| Private verify | No | Yes (with recipient key) |
| SDK module | BSM | SignedMessage |
| Scenario | Approach |
|----------|----------|
| Simple message auth | Direct SDK (BSM or BRC-77) |
| BAP identity signing | bsv-bap library |
| Parse existing Sigma/AIP scripts | Templates |
| Build BitCom transaction outputs | Templates |
| AIP-sign OP_RETURN with BRC-100 wallet | applyAip from @1sat/actions |
| Sigma-sign inscription with BRC-100 wallet | inscribe with signWithBAP: true |
| Sign transaction OP_RETURN data | sigma-protocol |
| Multiple signatures per output | sigma-protocol |
| Platform + user dual signing | sigma-protocol |
BAP identities use BSM for signing. The bsv-bap library handles this:
import { BAP } from "bsv-bap";
import { Utils } from "@bsv/sdk";
const { toArray } = Utils;
const bap = new BAP({ rootPk: wif });
const identity = bap.getId(bap.listIds()[0]);
// Sign with BSM (uses derived identity signing key)
const message = toArray("Hello World", "utf8");
const { address, signature } = identity.signMessage(message);
// Verify BSM signature
const isValid = bap.verifySignature("Hello World", address, signature);
A CLI is also available: bun add -g bsv-bap (see create-bap-identity skill).
The inscribe action from @1sat/actions supports a signWithBAP parameter that applies a Sigma BSM signature using the wallet's BAP identity key. This is the recommended approach when signing inscriptions through the actions framework — it handles anchor tx construction, sigma hash computation, and broadcast automatically.
import { inscribe, createContext } from '@1sat/actions'
const result = await inscribe.execute(ctx, {
base64Content: btoa('Hello Sigma'),
contentType: 'text/plain',
signWithBAP: true, // Signs with BAP identity via Sigma protocol
})
The resulting transaction carries a Sigma signature that can be verified with sigma-protocol:
import { Sigma } from 'sigma-protocol'
const sigma = new Sigma(tx, 0, 0, 0)
sigma.verify() // true
references/brc-77-spec.md - Full BRC-77 specificationreferences/sigma-advanced.md - Remote signing, hash details, advanced patternsexamples/bsm-sign-verify.ts - Direct BSM signingexamples/brc77-private-sig.ts - BRC-77 private signaturesexamples/sigma-template.ts - Template-based Sigma operationsexamples/sigma-multi-sig.ts - Full sigma-protocol with multi-sigdevelopment
This skill should be used when the user asks to integrate "Yours Wallet", "connect a BSV wallet", use "BRC-100", "pay with BSV wallet", add "wallet checkout in a web app", use "yours-wallet-provider", build a "pay with Yours Wallet" button, access "window.CWI", or connect a React app to a BRC-100 wallet.
development
This skill should be used when the user asks to "send BSV", "transfer satoshis", "create payment transaction", "send from WIF", "P2PKH transaction", or needs to build, sign, and broadcast P2PKH transactions from a WIF private key using @bsv/sdk.
development
This skill should be used when the user asks to "encrypt message with BSV key", "decrypt with private key", "ECDH encryption", "AES-256-GCM BSV", "EncryptedMessage", "BRC-2 encryption", or needs to encrypt/decrypt data using BSV keys and @bsv/sdk.
tools
This skill should be used when the user asks to "implement BRC-100 wallet", "use wallet-toolbox", "TypeScript BSV wallet", "BRC-100 implementation", "desktop wallet", "Electron wallet", "browser wallet", "IndexedDB wallet storage", "wallet actions", "wallet baskets", "UTXO management", "createAction", "listOutputs", "wallet certificates", "WalletClient", "noSend", "BEEF payment", "pay-beef", "send BEEF", "Transaction.fromBEEF", "toHexBEEF", or needs guidance on building conforming wallets using @bsv/wallet-toolbox or connecting to a user's BRC-100 wallet via WalletClient.