NaCl Box Encryption & Decryption (Curve25519-XSalsa20-Poly1305) - Public Key Crypto Tool

Operation Mode
Message
Public & Private Keys click to expand
Recipient's Public Key (32 bytes hex)
Used for encryption
Sender's Private Key (32 bytes hex)
Used for signing/authentication
Must be unique for each message
About NaCl Box (crypto_box)

crypto_box combines Curve25519 ECDH with XSalsa20-Poly1305 for public-key authenticated encryption.

  • Curve25519: Elliptic curve Diffie-Hellman key exchange
  • XSalsa20: Stream cipher for encryption
  • Poly1305: Message authentication code (MAC)
  • Provides confidentiality, integrity, and authentication

Support This Free Tool

Every coffee helps keep the servers running. Every book sale funds the next tool I'm dreaming up. You're not just supporting a site — you're helping me build what developers actually need.

500K+ users
200+ tools
100% private
Privacy Guarantee: Private keys you enter or generate are never stored on our servers. All tools are served over HTTPS.

Public-key Authenticated Encryption: crypto_box

The crypto_box_keypair function randomly generates a secret key and a corresponding public key. It puts the secret key into sk and returns the public key.

The crypto_box function encrypts and authenticates a message using the sender's secret key, the receiver's public key, and a nonce. The function returns the resulting ciphertext.

The crypto_box_open function verifies and decrypts a ciphertext using the receiver's secret key, the sender's public key, and a nonce. The function returns the resulting plaintext.

How to Perform NaCl Cryptography

Go Lang Tutorial

What is NaCl (Networking and Cryptography Library)?

NaCl (pronounced "salt") is a high-speed, easy-to-use cryptography library created by Daniel J. Bernstein, the mathematician behind Curve25519 and ChaCha20. NaCl focuses on providing secure defaults and avoiding common cryptographic pitfalls.

Libsodium is a portable, cross-platform fork of NaCl with the same API but better packaging and additional algorithms. Most modern applications use libsodium.

NaCl Cryptographic Primitives

Function Algorithm Purpose
crypto_secretbox XSalsa20-Poly1305 Secret-key authenticated encryption
crypto_box Curve25519 + XSalsa20-Poly1305 Public-key authenticated encryption
crypto_box_seal X25519 + XSalsa20-Poly1305 Anonymous public-key encryption
crypto_stream XSalsa20 Stream cipher (no authentication)
crypto_sign Ed25519 Digital signatures
crypto_hash SHA-512 Cryptographic hashing
crypto_auth HMAC-SHA-512-256 Message authentication

Key Sizes & Parameters

Secret-key Encryption (secretbox)
  • Key: 32 bytes (256 bits)
  • Nonce: 24 bytes (192 bits)
  • MAC: 16 bytes (128 bits)
Public-key Encryption (box)
  • Public key: 32 bytes
  • Private key: 32 bytes
  • Nonce: 24 bytes
Important: Never reuse a nonce with the same key. The nonce doesn't need to be secret, only unique.

NaCl vs Libsodium vs TweetNaCl

Library Language Notes
NaCl C Original by D.J. Bernstein. Reference implementation.
Libsodium C Portable fork of NaCl. Most widely used. Adds AEAD, Argon2, etc.
TweetNaCl C (100 tweets) Minimal implementation in ~100 tweets. Auditable.
PyNaCl Python Python bindings to libsodium.
TweetNaCl.js JavaScript JavaScript port of TweetNaCl for browsers/Node.js.
Sodium (Go) Go golang.org/x/crypto/nacl

When to Use Each NaCl Function

Use secretbox when:
  • Both parties share the same secret key
  • Encrypting local data (file encryption)
  • Session encryption after key exchange
Use box when:
  • Sender and receiver have key pairs
  • Both parties need to be authenticated
  • Secure messaging between known parties
Use sealedbox when:
  • Sender wants to remain anonymous
  • Anonymous tip lines or feedback
  • Only recipient's public key is known
Use stream (XSalsa20) when:
  • You need raw stream cipher only
  • Implementing custom protocols
  • Warning: No authentication!

Code Examples

# PyNaCl - Secret Box Encryption
from nacl.secret import SecretBox
from nacl.utils import random

key = random(SecretBox.KEY_SIZE)  # 32 bytes
box = SecretBox(key)

# Encrypt
ciphertext = box.encrypt(b"Hello, World!")

# Decrypt
plaintext = box.decrypt(ciphertext)
// TweetNaCl.js - Secret Box Encryption
const nacl = require('tweetnacl');

const key = nacl.randomBytes(32);
const nonce = nacl.randomBytes(24);
const message = new TextEncoder().encode("Hello, World!");

// Encrypt
const ciphertext = nacl.secretbox(message, nonce, key);

// Decrypt
const plaintext = nacl.secretbox.open(ciphertext, nonce, key);
// Go - Secret Box Encryption
import "golang.org/x/crypto/nacl/secretbox"

var key [32]byte
var nonce [24]byte
rand.Read(key[:])
rand.Read(nonce[:])

// Encrypt
ciphertext := secretbox.Seal(nil, []byte("Hello"), &nonce, &key)

// Decrypt
plaintext, ok := secretbox.Open(nil, ciphertext, &nonce, &key)

Security Considerations

  • Nonce reuse: NEVER reuse a nonce with the same key. This completely breaks security.
  • Key management: Use proper key derivation functions (Argon2, HKDF) for password-based keys.
  • Random generation: Use cryptographically secure random number generators.
  • Timing attacks: NaCl/libsodium functions are designed to be constant-time.
  • Memory safety: Libsodium provides sodium_memzero() to securely clear sensitive data.