# NaCl crypto_box encrypt/decrypt

Encrypt or decrypt NaCl crypto_box messages with Curve25519 keys, XSalsa20-Poly1305 authentication, and hex/base64 inputs. Free, local, and browser-based.

## Run it

- **CLI:** `gizza tool nacl-box-encrypt 'operation=encrypt'`
- **Web:** https://gizza.ai/tools/nacl-box-encrypt/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/nacl-box-encrypt/tool.json

## Inputs

- `operation` — Operation _(field)_
- `data` — Data _(field)_
- `recipient_key` — Recipient key _(field)_
- `sender_key` — Sender key _(field)_
- `nonce` — Nonce _(field)_
- `key_encoding` — Key encoding _(field)_
- `nonce_encoding` — Nonce encoding _(field)_
- `data_encoding` — Data encoding _(field)_
- `output_encoding` — Output encoding _(field)_

## Output

- Result (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `operation` — Operation
- `data` — Data
- `recipient_key` — Recipient key
- `sender_key` — Sender key
- `nonce` — Nonce
- `key_encoding` — Key encoding
- `nonce_encoding` — Nonce encoding
- `data_encoding` — Data encoding
- `output_encoding` — Output encoding

Example: `https://gizza.ai/tools/nacl-box-encrypt/?operation=encrypt&data=Plaintext%20for%20encrypt%2C%20or%20nonce%2Bciphertext%2Btag%20for%20decrypt&recipient_key=For%20encrypt%3A%20recipient%20public%20key.%20For%20decrypt%3A%20recipient%20secret%20key.&sender_key=For%20encrypt%3A%20sender%20secret%20key.%20For%20decrypt%3A%20sender%20public%20key.&nonce=000102030405060708090a0b0c0d0e0f1011121314151617&key_encoding=hex&nonce_encoding=hex&data_encoding=text&output_encoding=base64`

---

## About this tool

NaCl crypto_box is public-key authenticated encryption: the sender combines their Curve25519 secret key with the recipient's Curve25519 public key, then seals the message with XSalsa20-Poly1305. The recipient opens the box with their secret key and the sender's public key. If any key, nonce, ciphertext, or authentication tag byte changes, decryption fails instead of returning corrupted plaintext.

This local browser tool accepts raw 32-byte keys as hex or base64. Encryption requires a 24-byte nonce and returns one combined value: `nonce || ciphertext || 16-byte Poly1305 tag`, encoded as base64 by default. Decryption can read that combined value directly, or you can pass the nonce separately when your input is only `ciphertext || tag`.

### Worked example

Use Alice's RFC 7748 test-vector secret key to encrypt for Bob's public key:

```bash
gizza tool nacl-box-encrypt operation=encrypt data='attack at dawn' recipient_key=de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f sender_key=77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a nonce=000102030405060708090a0b0c0d0e0f1011121314151617 output_encoding=hex
```

To decrypt, swap key roles: Bob's secret key becomes `recipient_key`, Alice's public key becomes `sender_key`, and `data` is the combined box.

### Limits and edge cases

- Keys must decode to exactly 32 bytes; PEM and passphrases are intentionally not parsed here.
- Nonces must decode to exactly 24 bytes and must be unique for each sender/recipient key pair.
- The tool performs deterministic encryption for a supplied nonce; it does not generate random nonces.
- Decryption returns UTF-8 plaintext when valid. Non-UTF-8 plaintext bytes are encoded with `output_encoding`.
- This is NaCl `crypto_box` (`Curve25519 + XSalsa20-Poly1305`), not sealed boxes, age, PGP, or secretbox.

## FAQ

<details>
<summary>Which key goes in recipient_key and sender_key?</summary>

For encryption, `recipient_key` is the recipient's public key and `sender_key` is the sender's secret key. For decryption, `recipient_key` is the recipient's secret key and `sender_key` is the sender's public key. That mirrors how `crypto_box` authenticates both parties.

</details>

<details>
<summary>Why does encryption require a nonce?</summary>

NaCl crypto_box needs a unique 24-byte nonce for every message encrypted with the same sender/recipient key pair. Reusing a nonce with the same keys can reveal information about the plaintexts, so this tool makes the nonce explicit instead of silently generating one you might lose.

</details>

<details>
<summary>What is included in the encrypted output?</summary>

Encryption returns `nonce || ciphertext || tag`. The first 24 bytes are the nonce, the middle bytes are the encrypted message, and the final 16 bytes are the Poly1305 authentication tag. Decryption accepts that combined format by default.

</details>

<details>
<summary>How is this different from secretbox?</summary>

Secretbox uses one shared 32-byte symmetric key. Crypto_box uses Curve25519 public-key agreement, so the sender uses their secret key plus the recipient's public key and the recipient uses their secret key plus the sender's public key.

</details>

## Related tools

- [NaCl Secretbox encrypt/decrypt](https://gizza.ai/tools/nacl-secretbox-encrypt/): Encrypt or decrypt NaCl secretbox data with a 32-byte shared key and 24-byte nonce. Free, local, and browser-based.
- [ECIES encrypt/decrypt](https://gizza.ai/tools/ecies-encrypt/): Encrypt or decrypt ECIES payloads with secp256k1, P-256, or P-384 keys, HKDF-SHA256, AES-GCM/XChaCha20, and hex/base64/PEM inputs.
- [RSA encrypt](https://gizza.ai/tools/rsa-encrypt/): Encrypt a short message to an RSA public key (OAEP or PKCS#1 v1.5, SHA-256/384/512) and get base64 ciphertext, in your browser. Nothing is uploaded.
- [AES cipher](https://gizza.ai/tools/aes-cipher/): Encrypt or decrypt text with AES in CBC, CTR, GCM or ECB mode and 128/192/256-bit keys, with hex/base64 I/O — in your browser. Nothing is uploaded.
- [AES Key Wrap](https://gizza.ai/tools/aes-key-wrap/): Wrap and unwrap cryptographic keys with AES Key Wrap (KW / RFC 3394, KWP / RFC 5649) using a 128/192/256-bit KEK — hex or base64, free and in-browser.
