> For the complete documentation index, see [llms.txt](https://bsv.brc.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bsv.brc.dev/wallet/0002.md).

# Data Encryption and Decryption

Ty Everett (<ty@projectbabbage.com>)

## Abstract

We devise a method for applications to request the encryption and decryption of data. Specifically, we define a mechanism for data encryption within the [BRC-42](/key-derivation/0042.md) key derivation system, utilizing the [BRC-43](/key-derivation/0043.md) protocol and key ID scheme. During encryption, the sender derives their own child private key and the child public key of the recipient using the [BRC-42](/key-derivation/0042.md) process, then computes an ECDH shared secret between the child keys which is used in symmetric encryption with AES-256-GCM. The initialization vector, together with the ciphertext, are sent to the recipient. During decryption, the recipient computes their own private key and the public key of the sender, and uses ECDH to compute the same shared secret. The key is then used together with the provided initialization vector to decrypt the ciphertext. When no counterparty exists, we stipulate substitution for the sender's own public key in the child key derivation process.

## Motivation

The Bitcoin ecosystem has demonstrated a clear desire for wallets to support data encryption between parties[<sup>1</sup>](#footnote-1). This capability facilitates secure exchange of information, improves user privacy, and enables novel applications that require direct and secure communication between users. The unique economic incentives of micropayment-based applications, particularly those facilitated by Bitcoin wallets, make user privacy paramount, and have led to the adoption of end-to-end encryption by many applications[<sup>2</sup>](#footnote-2). While several encryption systems have been developed and integrated into various platforms, there is currently no standard methodology that supports both single-party and multi-party encryption, protocol-level permissions management, and leverages [BRC-42](/key-derivation/0042.md) key derivation. The [BRC-2](/wallet/0002.md) standard aims to fill this gap and provide a secure and standardized framework for encryption and decryption within the Bitcoin ecosystem.

## Status Note

The cryptographic construction in this document remains the basis for wallet `encrypt` and `decrypt`, but the BRC-1 message framing and legacy SDK references are historical. Current implementations expose these operations through [BRC-100](/wallet/0100.md), using `protocolID`, `keyID`, `counterparty`, `privileged`, `privilegedReason`, and `seekPermission` arguments.

## Specification

We start with the same constructs defined in [BRC-43](/key-derivation/0043.md): users with clients, protocols and applications. We stipulate the use of [BRC-43](/key-derivation/0043.md) invoice numbers in the context of [BRC-42](/key-derivation/0042.md) key derivation, and we build on top of the permissions architecture defined by [BRC-43](/key-derivation/0043.md).

When an application sends a message to a client requesting that data be encrypted, the message comprises:

* The [BRC-43](/key-derivation/0043.md) security level, protocol ID, key ID and counterparty to facilitate [BRC-42](/key-derivation/0042.md) key derivation and permissioning
* The data to encrypt

We stipulate the following process for encryption:

* The message sender begins by computing the [BRC-43](/key-derivation/0043.md) invoice number based on the security level, protocol ID, and key ID
* The message sender uses [BRC-42](/key-derivation/0042.md) key derivation with the computed invoice number to derive a child public key for the recipient
* The message sender uses [BRC-42](/key-derivation/0042.md) key derivation with the computed invoice number to derive their own child private key
* The message sender computes the ECDH shared secret between the two derived child keys
* The resulting elliptic curve point's X coordinate is encoded as exactly 32 big-endian bytes, including leading zero bytes, to create the AES-256-GCM symmetric encryption key. No additional hash of the X or Y coordinate is applied
* The resulting 256-bit value is used in conjunction with a randomly-generated 256-bit initialization vector to encrypt the message with AES-256-GCM
* The returned encrypted value is the concatenation `IV || ciphertext || authenticationTag`, with a 32-byte initialization vector and a 16-byte AES-GCM authentication tag. The client returns this byte array to the application through the wallet interface.

We stipulate the following process for message decryption:

* The recipient somehow comes to know the ciphertext (prepended with the initialization vector), the counterparty, the security level, protocol ID, and key ID. The mechanism for conveying this information to the recipient is beyond the scope of this specification.
* The recipient begins by computing the [BRC-43](/key-derivation/0043.md) invoice number based on the security level, protocol ID, and key ID
* The recipient uses [BRC-42](/key-derivation/0042.md) key derivation with the computed invoice number, their own private key and the public key of the sender, to compute the sender's child public key
* The recipient uses the same process to compute his own child private key
* The recipient computes a shared secret between the two child keys, encoding its X coordinate as exactly 32 big-endian bytes as the AES-256-GCM symmetric key, without additional hashing
* The recipient separates the first 32 bytes as the initialization vector, the last 16 bytes as the authentication tag and the intervening bytes as ciphertext. Values shorter than 48 bytes are invalid
* The recipient uses the symmetric key to decrypt and authenticate the ciphertext with the provided initialization vector and authentication tag. Authentication failure MUST produce an error; unauthenticated plaintext MUST NOT be returned

### Compatibility Clarification

The X-coordinate key and `IV || ciphertext || authenticationTag` framing above describe the current reference implementation and the existing encryption test vector in this document. Earlier prose incorrectly instructed implementations to hash the shared point's X and Y values and did not explicitly describe the authentication tag. This correction does not change the reference implementation's key derivation or stored ciphertext. Ciphertext created by a different interpretation of the earlier prose is not automatically compatible; applications must identify the construction used before migrating such data, rather than silently changing keys or discarding authentication tags.

### Confidentiality and Key Linkage Disclosure

BRC-2 confidentiality depends on keeping the relevant private keys and shared key-derivation material confidential. [BRC-69](/key-derivation/0069.md) Method 1 intentionally discloses a counterparty pair's root ECDH shared point. For known identity public keys and derivation labels, that disclosure suffices to calculate this scheme's child ECDH point and encryption key without recovering either private key. A recipient who also possesses the ciphertext can therefore decrypt data under that identity-key pair across protocols and key IDs, including earlier ciphertext. Protocol permissions and a revelation timestamp do not restrict this mathematical capability. The disclosure does not provide shared points for unrelated counterparty pairs.

BRC-69 Method 2 reveals only an individual derivation offset and has a narrower scope under its stated assumptions. Neither method guarantees confidentiality when the needed key material is otherwise known; encryption to `anyone`, whose private key is publicly `1`, MUST NOT be represented as confidential from the public. Protecting a linkage payload in transit under [BRC-72](/key-derivation/0072.md) protects its delivery to the intended verifier, but does not constrain the verifier's use of the disclosed material.

We build upon the abstract messaging layer first described in [BRC-1](/wallet/0001.md). Specifically, we define five new [BRC-1](/wallet/0001.md) messages to facilitate requests and responses for encryption and decryption, and error handling. For each of the messages, we stipulate that there exists some out-of-band mechanism for the parties to communicate which of the messages are being exchanged, removing the need for a message type field. Finally, specifically for the request messages, we stipulate that the message comprises a header and a payload, with the payload containing the data (ciphertext or plaintext), and the header containing the other information. For the response messages, no message header is defined and the payload simply contains the specified data.

### Encryption Request

The encryption request is a message sent by the [BRC-43](/key-derivation/0043.md) application to the client. It contains a header with the following information:

| Field          | Description                                                                                                                                                                                                                                         |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `protocolID`   | The [BRC-43](/key-derivation/0043.md) security level and protocol ID represented as an array. For example, `[0, "hello world"]` represents a level-0 protocol with open permissions, while `[2, "document signing"]` represents a level 2 protocol. |
| `keyID`        | The [BRC-43](/key-derivation/0043.md) key ID                                                                                                                                                                                                        |
| `counterparty` | The [BRC-43](/key-derivation/0043.md) counterparty, or `self`                                                                                                                                                                                       |

The message payload comprises the data to encrypt.

### Encryption Response

The response message comprises the encrypted byte array `IV || ciphertext || authenticationTag`, with a 32-byte initialization vector and a 16-byte authentication tag.

### Decryption Request

The decryption request is a message sent by the application to the client. It contains a header with the following information:

| Field          | Description                                                                                                                                                                                                                                         |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `protocolID`   | The [BRC-43](/key-derivation/0043.md) security level and protocol ID represented as an array. For example, `[0, "hello world"]` represents a level-0 protocol with open permissions, while `[2, "document signing"]` represents a level 2 protocol. |
| `keyID`        | The [BRC-43](/key-derivation/0043.md) key ID                                                                                                                                                                                                        |
| `counterparty` | The [BRC-43](/key-derivation/0043.md) counterparty, or `self`                                                                                                                                                                                       |

The message payload comprises `IV || ciphertext || authenticationTag` in the same format as the encryption response.

### Decryption Response

The response message comprises a payload containing the decrypted plaintext.

### Cryptography Error

If the client is unable to fulfill the encryption or decryption requests for any reason, we specify that it should respond with a JSON-formatted Cryptography Error. The fields for the object are specified as follows:

| Field         | Description                                                                                                                                                                             |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`      | This should always be a string comprising `"error"`.                                                                                                                                    |
| `code`        | A machine-readable error code. Extensions to this standard can define specific error codes and standardize additional fields. Codes are strings, for example `"ERR_DECRYPTION_FAILED"`. |
| `description` | All errors must have a human-readable `description` field that describes the error. This allows the application to represent the error for the user.                                    |

One example of a Cryptography Error is given below:

```json
{
  "status": "error",
  "code": "ERR_PERMISSION_DENIED",
  "description": "You have denied permission for encrypting this data."
}
```

## Test Vectors

For compatibility with this encryption scheme, we stipulate the following:

A user who has the following identity private key...

```
6a2991c9de20e38b31d7ea147bf55f5039e4bbc073160f5e0d541d1f17e321b8
```

...which implies the followign identity public key for that user...

```
025ad43a22ac38d0bc1f8bacaabb323b5d634703b7a774c4268f6a09e4ddf79097
```

...should be able to use security level `2`, the `BRC2 Test` protocolID with keyID `42` and the following counterparty...

```
0294c479f762f6baa97fbcd4393564c1d7bd8336ebd15928135bbcf575cd1a71a1
```

...to decrypt the message with the following ciphertext (with prepended initialization vector)...

```
[252, 203, 216, 184, 29, 161, 223, 212, 16, 193, 94, 99, 31, 140, 99, 43, 61, 236, 184, 67, 54, 105, 199, 47, 11, 19, 184, 127, 2, 165, 125, 9, 188, 195, 196, 39, 120, 130, 213, 95, 186, 89, 64, 28, 1, 80, 20, 213, 159, 133, 98, 253, 128, 105, 113, 247, 197, 152, 236, 64, 166, 207, 113, 134, 65, 38, 58, 24, 127, 145, 140, 206, 47, 70, 146, 84, 186, 72, 95, 35, 154, 112, 178, 55, 72, 124]
```

... and receive the following plaintext:

```
BRC-2 Encryption Compliance Validated!
```

...and to validate the message with the following HMAC...

```
[81, 240, 18, 153, 163, 45, 174, 85, 9, 246, 142, 125, 209, 133, 82, 76, 254, 103, 46, 182, 86, 59, 219, 61, 126, 30, 176, 232, 233, 100, 234, 14]
```

... the message whose HMAC is above as being:

```
BRC-2 HMAC Compliance Validated!
```

## Implementations

* This encryption capability is incorporated into current `@bsv/sdk` BRC-100 wallet interfaces and wallet permission enforcement. Older Babbage SDK references are retained only for historical context. The maintained [KeyDeriver](https://github.com/bsv-blockchain/ts-stack/blob/3e41d6a220783b268b6240ae654f27628c4af557/packages/sdk/src/wallet/KeyDeriver.ts#L255-L272) uses the child ECDH X coordinate as the key, and [SymmetricKey](https://github.com/bsv-blockchain/ts-stack/blob/3e41d6a220783b268b6240ae654f27628c4af557/packages/sdk/src/primitives/SymmetricKey.ts#L152-L179) serializes the 32-byte IV, ciphertext and 16-byte tag.

## Revision History

* **2026-09-30**: Reconciled the symmetric-key and authenticated ciphertext framing prose with the existing reference implementation and published encryption vector. Clarified BRC-69 disclosure consequences; no reference ciphertext or derivation change is introduced.

## References

* 1: [MoneyButton Encryption](https://github.com/moneybutton/docs/blob/master/docs/mb-encryption.md)
* 2: [BaeMail](https://baemail.me/)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bsv.brc.dev/wallet/0002.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
