#601

Global Rank · of 601 Skills

wallet-encrypt-decrypt AI Agent Skill

View Source: b-open-io/bsv-skills

Safe

Installation

npx skills add b-open-io/bsv-skills --skill wallet-encrypt-decrypt

22

Installs

BSV Message Encryption

Encrypt and decrypt messages between parties using @bsv/sdk.

Recommended: Use EncryptedMessage from @bsv/sdk

The @bsv/sdk provides EncryptedMessage for secure message encryption. This is the preferred approach - avoid rolling custom encryption implementations.

import { PrivateKey, EncryptedMessage, Utils } from '@bsv/sdk'

const sender = PrivateKey.fromRandom()
const recipient = PrivateKey.fromRandom()

// Encrypt: sender uses their private key + recipient's public key
const message = Utils.toArray('Secret message', 'utf8')
const encrypted = EncryptedMessage.encrypt(message, sender, recipient.toPublicKey())

// Decrypt: recipient uses their private key
const decrypted = EncryptedMessage.decrypt(encrypted, recipient)
const plaintext = Utils.toUTF8(decrypted)

Two Encryption Patterns

Pattern 1: Static-Static ECDH (Both Parties Have Keys)

Use when both parties have established keypairs (e.g., BAP identities, paymail addresses).

import { PrivateKey, EncryptedMessage, Utils } from '@bsv/sdk'

// Alice and Bob both have persistent keys
const alice = PrivateKey.fromWif('L1...')
const bob = PrivateKey.fromWif('K1...')

// Alice encrypts to Bob
const ciphertext = EncryptedMessage.encrypt(
  Utils.toArray('Hello Bob', 'utf8'),
  alice,
  bob.toPublicKey()
)

// Bob decrypts from Alice
const plaintext = EncryptedMessage.decrypt(ciphertext, bob)

Use cases:

  • Peer-to-peer encrypted messaging
  • Encrypted backups to your own key
  • Communication between known identities

Pattern 2: ECIES-Style (Ephemeral Sender Key)

Use when sender doesn't have a persistent identity (e.g., browser-to-server).

import { PrivateKey, EncryptedMessage, Utils } from '@bsv/sdk'

// Server has persistent key, client generates ephemeral
const serverKey = PrivateKey.fromWif('L1...')
const ephemeralClient = PrivateKey.fromRandom()

// Client encrypts (ephemeral → server)
const encrypted = EncryptedMessage.encrypt(
  Utils.toArray('sensitive data', 'utf8'),
  ephemeralClient,
  serverKey.toPublicKey()
)

// Include ephemeral public key so server can decrypt
const payload = {
  ephemeralPub: ephemeralClient.toPublicKey().toString(),
  ciphertext: Utils.toHex(encrypted)
}

// Server decrypts using ephemeral pubkey
const clientPub = PublicKey.fromString(payload.ephemeralPub)
// Note: EncryptedMessage.decrypt needs the sender info embedded in ciphertext

Use cases:

  • Browser-to-server encryption
  • One-way secure channels
  • Forward secrecy (fresh key per message)

How ECDH Key Agreement Works

Both parties derive the same shared secret:

Alice: alicePrivKey × bobPubKey = sharedPoint
Bob:   bobPrivKey × alicePubKey = sharedPoint

The shared point is then used to derive a symmetric key for AES-256-GCM encryption.

API Reference

EncryptedMessage.encrypt()

static encrypt(
  message: number[],      // Plaintext as byte array
  sender: PrivateKey,     // Sender's private key
  recipient: PublicKey    // Recipient's public key
): number[]               // Encrypted bytes

EncryptedMessage.decrypt()

static decrypt(
  ciphertext: number[],   // Encrypted bytes from encrypt()
  recipient: PrivateKey   // Recipient's private key
): number[]               // Decrypted plaintext bytes

Utility Functions

// String to bytes
Utils.toArray('hello', 'utf8')  // number[]

// Bytes to string
Utils.toUTF8([104, 101, 108, 108, 111])  // 'hello'

// Bytes to hex
Utils.toHex([1, 2, 3])  // '010203'

// Hex to bytes
Utils.toArray('010203', 'hex')  // [1, 2, 3]

Security Properties

  • Authenticated encryption: AES-256-GCM provides confidentiality + integrity
  • Key agreement: ECDH ensures only intended recipient can decrypt
  • No key transmission: Private keys never leave their owner

Common Mistakes

Don't roll your own crypto

Wrong: Implementing ECDH + AES manually

// Don't do this - use EncryptedMessage instead
const sharedSecret = myPrivKey.deriveSharedSecret(theirPubKey)
const aesKey = sha256(sharedSecret)
// ... manual AES encryption

Correct: Use the SDK's built-in class

const encrypted = EncryptedMessage.encrypt(message, sender, recipient)

Don't confuse encryption with authentication

  • Encryption (this skill): Hides message content
  • Authentication (bitcoin-auth): Proves sender identity

For authenticated + encrypted communication, use both:

// Encrypt the payload
const encrypted = EncryptedMessage.encrypt(payload, sender, recipient)

// Sign the request (proves sender identity)
const authToken = getAuthToken({ privateKeyWif, requestPath, body })

Installs

Installs 22
Global Rank #601 of 601

Security Audit

ath Safe
socket Safe
Alerts: 0 Score: 90
snyk Low
EU EU-Hosted Inference API

Power your AI Agents with the best open-source models.

Drop-in OpenAI-compatible API. No data leaves Europe.

Explore Inference API

GLM

GLM 5

$1.00 / $3.20

per M tokens

Kimi

Kimi K2.5

$0.60 / $2.80

per M tokens

MiniMax

MiniMax M2.5

$0.30 / $1.20

per M tokens

Qwen

Qwen3.5 122B

$0.40 / $3.00

per M tokens

How to use this skill

1

Install wallet-encrypt-decrypt by running npx skills add b-open-io/bsv-skills --skill wallet-encrypt-decrypt in your project directory. Run the install command above in your project directory. The skill file will be downloaded from GitHub and placed in your project.

2

No configuration needed. Your AI agent (Claude Code, Cursor, Windsurf, etc.) automatically detects installed skills and uses them as context when generating code.

3

The skill enhances your agent's understanding of wallet-encrypt-decrypt, helping it follow established patterns, avoid common mistakes, and produce production-ready output.

What you get

Skills are plain-text instruction files — not executable code. They encode expert knowledge about frameworks, languages, or tools that your AI agent reads to improve its output. This means zero runtime overhead, no dependency conflicts, and full transparency: you can read and review every instruction before installing.

Compatibility

This skill works with any AI coding agent that supports the skills.sh format, including Claude Code (Anthropic), Cursor, Windsurf, Cline, Aider, and other tools that read project-level context files. Skills are framework-agnostic at the transport level — the content inside determines which language or framework it applies to.

Data sourced from the skills.sh registry and GitHub. Install counts and security audits are updated regularly.

EU Made in Europe

Chat with 100+ AI Models in one App.

Use Claude, ChatGPT, Gemini alongside with EU-Hosted Models like Deepseek, GLM-5, Kimi K2.5 and many more.

Get the App:

Customer Support