Secure PubNub applications with Access Manager, encryption, and TLS
PubNub provides built-in AES-256 encryption for end-to-end message security.
cipherKey before sendingcipherKeyconst pubnub = new PubNub({
publishKey: 'pub-c-...',
subscribeKey: 'sub-c-...',
userId: 'user-123',
cipherKey: 'my-strong-secret-cipher-key' // AES-256 encryption enabled
});
// All messages automatically encrypted/decrypted
await pubnub.publish({
channel: 'secure-channel',
message: { secretData: 'sensitive information' }
});pnconfig = PNConfiguration()
pnconfig.publish_key = 'pub-c-...'
pnconfig.subscribe_key = 'sub-c-...'
pnconfig.uuid = 'user-123'
pnconfig.cipher_key = 'my-strong-secret-cipher-key'
pubnub = PubNub(pnconfig)let config = PubNubConfiguration(
publishKey: "pub-c-...",
subscribeKey: "sub-c-...",
userId: "user-123"
)
config.cipherKey = "my-strong-secret-cipher-key"
let pubnub = PubNub(configuration: config)| Data | Encrypted with cipherKey |
|---|---|
| Message payload | Yes |
| File metadata/caption | Yes |
| Channel name | No |
| Publisher UUID | No |
| Timetoken | No |
| Message persistence (history) | Stored encrypted |
// Generate a strong cipher key
const crypto = require('crypto');
const cipherKey = crypto.randomBytes(32).toString('hex');
// e.g., "a1b2c3d4e5f6..."// Different cipher keys for different security contexts
const publicPubnub = new PubNub({
subscribeKey: 'sub-c-...',
publishKey: 'pub-c-...',
userId: 'user-123'
// No cipherKey - public channels
});
const privatePubnub = new PubNub({
subscribeKey: 'sub-c-...',
publishKey: 'pub-c-...',
userId: 'user-123',
cipherKey: 'private-channel-key'
});// When rotating keys, old messages remain encrypted with old key
// Consider using versioned keys
const cipherKeys = {
v1: 'old-cipher-key',
v2: 'new-cipher-key'
};
// Include version in message for decryption
await pubnub.publish({
channel: 'secure-channel',
message: {
keyVersion: 'v2',
data: encryptedPayload
}
});// TLS (HTTPS) is ON by default
const pubnub = new PubNub({
subscribeKey: 'sub-c-...',
userId: 'user-123'
// ssl: true is the default
});// Only disable for specific testing scenarios
const pubnub = new PubNub({
subscribeKey: 'sub-c-...',
userId: 'user-123',
ssl: false // NOT RECOMMENDED for production
});Important: As of February 1, 2025, PubNub only supports TLS 1.2+
Verify TLS 1.2 compatibility:
# Test endpoint
curl https://pubsub-tls12-test.pubnub.comEnsure your environment supports TLS 1.2:
| Key Type | Purpose | Location | PubNub Access |
|---|---|---|---|
| Cipher Key | Encrypt message payloads | Client | Never sees it |
| Secret Key | Sign PAM admin requests | Server only | Has it |
| TLS | Encrypt transport layer | Both | Terminates at edge |
// Maximum security: Use ALL three
const pubnub = new PubNub({
subscribeKey: 'sub-c-...',
publishKey: 'pub-c-...',
userId: 'user-123',
authKey: 'pam-auth-token', // Access Manager
cipherKey: 'my-strong-cipher-key', // AES-256 encryption
ssl: true // TLS (default)
});When using PubNub File Sharing:
// File metadata is encrypted with cipherKey
// File binary uses PubNub infrastructure security (HTTPS + at-rest encryption)
const pubnub = new PubNub({
subscribeKey: 'sub-c-...',
publishKey: 'pub-c-...',
userId: 'user-123',
cipherKey: 'my-cipher-key'
});
// Send file - metadata encrypted
await pubnub.sendFile({
channel: 'file-sharing',
file: myFile,
message: { caption: 'Encrypted caption' } // This is encrypted
});For file content encryption where PubNub never sees plaintext:
// 1. Encrypt file content yourself BEFORE sending
const encryptedFileBuffer = await encryptFile(originalFile, myEncryptionKey);
// 2. Send encrypted file
await pubnub.sendFile({
channel: 'secure-files',
file: {
data: encryptedFileBuffer,
name: 'encrypted-document.bin'
}
});
// 3. Recipient downloads and decrypts
const downloadedFile = await pubnub.downloadFile({
channel: 'secure-files',
id: fileId,
name: fileName
});
const decryptedFile = await decryptFile(downloadedFile, myEncryptionKey);Messages encrypted with cipherKey are stored encrypted:
// Publish encrypted message
await pubnub.publish({
channel: 'secure-history',
message: { secret: 'data' }
});
// Retrieve history - automatically decrypted if same cipherKey
const history = await pubnub.fetchMessages({
channels: ['secure-history'],
count: 10
});
// Messages in history.channels['secure-history'] are decryptedNote: If you fetch history with wrong/no cipherKey, messages appear as encrypted blobs.
tessl i pubnub/pubnub-security@0.1.4