Client-Side Encryption
AnonPaste supports client-side encryption for pastes and files. The content is encrypted before it reaches the API — the server stores only ciphertext.
This means:
- AnonPaste cannot read your content
- If the server is compromised, your data remains protected
- Only someone with the encryption key can decrypt it
Encryption scheme
Section titled “Encryption scheme”The SDK uses AES-256-CBC with a key derived by SHA-256 hashing your password. This is the same scheme used internally by AnonPaste for encrypted pastes.
key = SHA256(password)iv = be410fea41df7162a679875ec131cf2c (fixed)mode = AES-256-CBCpad = PKCS7Encrypted pastes
Section titled “Encrypted pastes”Create
Section titled “Create”The SDK compresses the text with lz-string first, then encrypts it:
const { id } = await anonpaste.pastes.encryptAndCreate({ name: 'My Secret Notes', text: 'This content is encrypted end-to-end.', encryptionKey: 'my-strong-passphrase', // Optional: control visibility and expiry mode: PasteMode.Private, neverExpire: true,});Read and decrypt
Section titled “Read and decrypt”const paste = await anonpaste.pastes.getAndDecrypt(id, 'my-strong-passphrase');console.log(paste.decryptedText); // original plaintextUsing curl (manual)
Section titled “Using curl (manual)”If you’re not using the SDK, you must handle compression and encryption yourself:
- Compress the text with lz-string (
compressToBase64) - Encrypt with AES-256-CBC (key = SHA256 of password, fixed IV above)
- Send the ciphertext as the
textfield
# The text field must be the AES-CBC encrypted, lz-compressed ciphertextcurl -X POST https://api.anonpaste.com/api/dev/pastes/create \ -H "x-api-key: your_api_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Encrypted Paste", "text": "<base64-encoded-ciphertext>", "mode": 0 }'Encrypted files
Section titled “Encrypted files”Upload an encrypted file
Section titled “Upload an encrypted file”Encrypts the file client-side before uploading:
import { readFileSync } from 'fs';
const { fileId, readUrl } = await anonpaste.files.uploadEncrypted({ fileName: 'sensitive.pdf', contentType: 'application/pdf', fileData: readFileSync('./sensitive.pdf'), encryptionKey: 'my-strong-passphrase',});The uploaded blob is opaque to the server. To decrypt it after downloading:
import { decryptBuffer } from 'anonpaste-sdk';
const { readUrl } = await anonpaste.files.get(fileId);const response = await fetch(readUrl);const encrypted = await response.text(); // base64 ciphertextconst decrypted = decryptBuffer(encrypted, 'my-strong-passphrase');// decrypted is a Uint8Array containing the original file bytesStandalone encryption helpers
Section titled “Standalone encryption helpers”All encryption functions are exported at the top level of the SDK:
import { encryptText, decryptText, encryptBuffer, decryptBuffer } from 'anonpaste-sdk';
// Textconst ciphertext = encryptText('hello world', 'my-key');const plaintext = decryptText(ciphertext, 'my-key');
// Binary (Buffer / Uint8Array)const encryptedBlob = encryptBuffer(someBuffer, 'my-key'); // returns base64 stringconst originalBytes = decryptBuffer(encryptedBlob, 'my-key'); // returns Uint8ArrayCompression helpers
Section titled “Compression helpers”import { compressToBase64, decompressFromBase64 } from 'anonpaste-sdk';
const compressed = compressToBase64('long text...');const decompressed = decompressFromBase64(compressed);Key management tips
Section titled “Key management tips”- Use strong passphrases — the security of your encrypted content depends entirely on key strength
- Never send the key to the server — the SDK ensures keys only exist in your code
- Store keys separately from ciphertext — if you store the key alongside the encrypted data, you lose the security benefit
- Use different keys per resource — a single compromised key should only affect one resource