Encryption API for C SDK
The crypto module encrypts payloads transparently for publish and subscribe, message persistence, and file transfer, and it can also be called directly for manual encryption. Two distinct layers make up this feature, and keeping them apart is the key to reading this page correctly:
- The module API you call. Declared in
#include <pubnub/features/crypto.h>, gated byPUBNUB_ENABLE_CRYPTO. Apubnub_crypto_module_twraps a default cryptor plus up toPUBNUB_CFG_CRYPTO_MAX_FALLBACK_CRYPTORSfallback cryptors (default4,2under theembeddedprofile). You create a module with one of the factory functions below and attach it topubnub_config_t.crypto_module. The SDK then encrypts and decrypts message payloads and file content for you. You can also call the module's encrypt/decrypt functions directly for data you handle yourself. - The provider vtable, which you implement only for a custom algorithm. Declared in
#include <pubnub/providers/crypto.h>. This ispubnub_crypto_provider_t, the function-pointer table that both built-in algorithms populate. You only touch this layer if you are writing your own cryptor.
The SDK ships two built-in algorithms: AES-CBC with a random IV, identified on the wire as "ACRH", and a legacy cryptor kept for interoperating with data encrypted by older PubNub SDKs. Fallback cryptor selection, covered in Migrate from legacy to AES-CBC, lets you switch your default cryptor from legacy to ACRH without losing the ability to read data you already encrypted.
danger
crypto_module = NULL disables encryption silentlypubnub_config_t.crypto_module defaults to NULL, and there is no compiled-in fallback module. A NULL crypto_module means every publish, subscribe, history, and file payload travels in plaintext, with no error and no warning. If your application expects encryption, verify crypto_module is set. Nothing else will tell you it is missing.
Backend selection and build profiles
Whether encryption is available at all is a build-time choice, controlled by PUBNUB_PROVIDER_CRYPTO (openssl, mbedtls, none, or custom):
| Profile | PUBNUB_ENABLE_CRYPTO | PUBNUB_PROVIDER_CRYPTO |
|---|---|---|
full | ON | openssl |
minimal | OFF | none |
embedded | OFF | none |
Under minimal and embedded, PUBNUB_PROVIDER_CRYPTO=none compiles no crypto backend at all. With PUBNUB_ENABLE_CRYPTO also OFF, the entire body of features/crypto.h is preprocessed out. None of the functions on this page exist in the compiled library or the installed header for those profiles. If you want encryption on an embedded target, start from (or switch to) the full profile, or override both flags explicitly on top of your chosen profile: -DPUBNUB_ENABLE_CRYPTO=ON -DPUBNUB_PROVIDER_CRYPTO=openssl (or mbedtls). An explicit -D always wins over the profile default. See Environment Setup for the full flag matrix and Providers for backend selection mechanics.
Create an AES-CBC (ACRH) crypto module
pubnub_crypto_module_aes_cbc() creates a module whose default cryptor encrypts with AES-256-CBC and a random IV, identified on the wire as "ACRH". This is the recommended cryptor for all new encryption.
Method(s)
pubnub_crypto_module_t* pubnub_crypto_module_aes_cbc(const char* cipher_key,
int use_random_iv,
pubnub_allocator_provider_t* alloc);
| Parameter | Description |
|---|---|
cipher_key *Type: const char* | NUL-terminated cipher key string. Borrowed only for the duration of the call. The module derives its own key material and does not retain the original pointer. |
use_random_iv *Type: int | Controls the IV mode of the legacy fallback cryptor this factory wires in automatically, not of ACRH itself (ACRH always uses a random IV). 1 = expect a random IV prepended to legacy ciphertext when decrypting. 0 = use the static IV "0123456789012345". |
allocType: pubnub_allocator_provider_t* | Allocator for the module's internal state. NULL uses the compiled-in default allocator. |
C-family contract
- Header —
#include <pubnub/features/crypto.h> - Types —
pubnub_crypto_module_t,pubnub_allocator_provider_t - Feature flag —
PUBNUB_ENABLE_CRYPTO - Ownership / lifetime — returns a heap-allocated module the caller owns. The module also owns an internally created legacy cryptor (used as its decrypt fallback) and destroys both when you call
pubnub_crypto_module_destroy(). - Blocking — never blocks. This is a local, synchronous computation with no network involvement.
Sample code
Adapted from examples/crypto/cooperative.c.
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <pubnub/features/publish.h>
#include <pubnub/future.h>
#include <pubnub/response.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/* 1. Create a crypto module (AES-256-CBC, random IV). NULL alloc
* uses the compiled-in default. */
pubnub_crypto_module_t* crypto = pubnub_crypto_module_aes_cbc("my-cipher-key", 1, NULL);
if (NULL == crypto) {
show all 60 linesThe SDK also ships examples/crypto/async.c, the identical scenario delivered through a pubnub_async() completion callback instead of cooperative polling. See Environment Setup for the three ways to consume a pubnub_future_t.
Returns
A pubnub_crypto_module_t* you own, or NULL on allocation or key-derivation failure.
Create a legacy crypto module
pubnub_crypto_module_legacy() creates a module whose default cryptor uses the legacy algorithm, the same encryption older PubNub SDKs use.
Weaker key derivation: use only for compatibility
The legacy cryptor derives its AES key from only 32 ASCII hex characters of a SHA-256 digest of cipher_key, half the digest's entropy, encoded inefficiently as text, instead of the full 32-byte raw digest ACRH uses. Do not choose the legacy cryptor for new encryption. Use it only to decrypt data that an older client already encrypted with it. For anything new, create an AES-CBC module instead.
Method(s)
pubnub_crypto_module_t* pubnub_crypto_module_legacy(const char* cipher_key,
int use_random_iv,
pubnub_allocator_provider_t* alloc);
| Parameter | Description |
|---|---|
cipher_key *Type: const char* | NUL-terminated cipher key string. Borrowed only for the duration of the call. |
use_random_iv *Type: int | 1 = generate a random 16-byte IV per encrypt and prepend it to the ciphertext; 0 = use the static IV "0123456789012345". This governs the module's own (legacy) encryption, not just its fallback, unlike the use_random_iv parameter on pubnub_crypto_module_aes_cbc(). |
allocType: pubnub_allocator_provider_t* | Allocator for the module's internal state. NULL uses the compiled-in default. |
C-family contract
- Header —
#include <pubnub/features/crypto.h> - Types —
pubnub_crypto_module_t,pubnub_allocator_provider_t - Feature flag —
PUBNUB_ENABLE_CRYPTO - Ownership / lifetime — returns a heap-allocated module. The module owns an internally created ACRH cryptor as its decrypt fallback and destroys both cryptors on
pubnub_crypto_module_destroy(). - Blocking — never blocks. Synchronous local computation.
Sample code
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
pubnub_crypto_module_t* legacy = pubnub_crypto_module_legacy("my-cipher-key", 1, NULL);
if (NULL == legacy) {
return EXIT_FAILURE;
}
const uint8_t plaintext[] = "message encrypted by an older SDK version";
show all 45 linesReturns
A pubnub_crypto_module_t* you own, or NULL on allocation or key-derivation failure.
Create a crypto module with custom cryptors
pubnub_crypto_module_create() builds a module from cryptors you supply explicitly, instead of the automatic ACRH/legacy pairing the two named factories create. Use it to control exactly which algorithms participate, or to register a custom cryptor.
Method(s)
pubnub_crypto_module_t* pubnub_crypto_module_create(pubnub_crypto_provider_t* default_cryptor,
pubnub_crypto_provider_t** others,
size_t others_count,
pubnub_allocator_provider_t* alloc);
| Parameter | Description |
|---|---|
default_cryptor *Type: pubnub_crypto_provider_t* | The cryptor that handles all encryption. Borrowed. The module does not take ownership. |
othersType: pubnub_crypto_provider_t** | Array of fallback cryptors, consulted only on decrypt. Borrowed. May be NULL when others_count is 0. |
others_countType: size_t | Number of entries in others. Must not exceed PUBNUB_CFG_CRYPTO_MAX_FALLBACK_CRYPTORS (default 4; 2 under embedded); exceeding it makes the factory return NULL. |
allocType: pubnub_allocator_provider_t* | Allocator for the module struct itself. NULL uses the compiled-in default. |
Standalone factories build the cryptors to pass in:
pubnub_crypto_provider_t* pubnub_cryptor_aes_cbc_create(const char* cipher_key,
pubnub_allocator_provider_t* alloc);
pubnub_crypto_provider_t* pubnub_cryptor_legacy_create(const char* cipher_key,
int use_random_iv,
pubnub_allocator_provider_t* alloc);
void pubnub_cryptor_destroy(pubnub_crypto_provider_t* cryptor);
pubnub_cryptor_destroy() securely zeros key material before freeing, and is NULL-safe.
C-family contract
- Header —
#include <pubnub/features/crypto.h> - Types —
pubnub_crypto_module_t,pubnub_crypto_provider_t,pubnub_allocator_provider_t - Feature flag —
PUBNUB_ENABLE_CRYPTO - Ownership / lifetime — unlike
pubnub_crypto_module_aes_cbc()/pubnub_crypto_module_legacy(), a module built withpubnub_crypto_module_create()does not own any cryptor you pass in. Destroying the module frees only the module struct. You must destroy each cryptor yourself withpubnub_cryptor_destroy(), and you must do so after destroying the module, not before. - Blocking — never blocks.
Sample code
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <pubnub/providers/crypto.h>
#include <stdlib.h>
int main(void)
{
/* Build the same ACRH-default/legacy-fallback pairing that
* pubnub_crypto_module_aes_cbc() creates automatically, but with
* explicit control over both cryptors. */
pubnub_crypto_provider_t* acrh = pubnub_cryptor_aes_cbc_create("my-cipher-key", NULL);
if (NULL == acrh) {
return EXIT_FAILURE;
}
show all 41 linesReturns
A pubnub_crypto_module_t* you own, or NULL if allocation fails or others_count exceeds the compile-time fallback limit.
Destroy a crypto module
void pubnub_crypto_module_destroy(pubnub_crypto_module_t* module);
NULL-safe. What it destroys depends on how the module was created:
| Created with | What pubnub_crypto_module_destroy() does |
|---|---|
pubnub_crypto_module_aes_cbc() or pubnub_crypto_module_legacy() | Destroys the module and both of its internally created cryptors, securely zeroing key material. |
pubnub_crypto_module_create() | Frees only the module struct. Cryptors you passed in are untouched. Destroy each one yourself with pubnub_cryptor_destroy(), after this call returns. |
Ownership / lifetime: a module attached to pubnub_config_t.crypto_module is borrowed by the context. Destroy the context with pubnub_destroy()/pubnub_deinit() before destroying the module, never the other way round. Blocking: never blocks.
Attach a crypto module to a context
pubnub_config_t.crypto_module is what turns a module into transparent, automatic encryption for feature calls. This field is documented in full in Configuration; this section covers only its encryption-specific behavior.
| Field | Type | Required | Default | Ownership |
|---|---|---|---|---|
crypto_module | pubnub_crypto_module_t* | Optional | NULL: payload encryption disabled, deliberately, with no compiled-in fallback | Borrowed. The caller manages the module's lifetime and must keep it alive for as long as any context references it. |
When crypto_module is non-NULL, these operations encrypt and decrypt automatically, with no explicit encrypt/decrypt call in your application code:
| Feature | What gets encrypted |
|---|---|
| Publish | The JSON message payload, base64-encoded into the outgoing publish body. |
| Subscribe | The JSON message payload of each incoming message, decoded from the base64 string PubNub delivers. |
History (pubnub_fetch_messages()) | Same base64 JSON-message path as subscribe. |
| Files | Two distinct paths: the raw file content is encrypted and decrypted as binary, with no base64 or JSON wrapping, around the upload/download transfer; the JSON file-message that describes the file (published after upload) uses the same base64 JSON path as publish. |
Signal payloads are not on this list. A pubnub_signal() call does not encrypt its payload through the crypto module.
Decryption failure is silent, not an error
On subscribe, history, and file downloads, a decryption failure does not fail the operation or surface a distinct pubnub_res_t. Subscribe and history return the still-encrypted payload unchanged, exactly as received. File downloads set the result's decrypted flag to 0 rather than failing. If your application does not check for this, it can end up treating ciphertext as if it were plaintext. Check the payload or the decrypted flag explicitly rather than assuming a successful transaction means successfully decrypted content.
Access Manager and crypto are independent
PUBNUB_ENABLE_PAM requires PUBNUB_ENABLE_CRYPTO at build time, because PAM request signing depends on the crypto provider's hmac_sha256 vtable member. This dependency is on the provider layer, not on crypto_module. PAM signing works whether or not you configure a crypto_module for payload encryption, and configuring one does not by itself enable PAM. On the minimal and embedded profiles, both PUBNUB_ENABLE_CRYPTO and PUBNUB_ENABLE_PAM are OFF, so Access Manager needs the same explicit override described in Backend selection and build profiles.
Encrypt and decrypt into a fixed-size buffer
Use these functions to encrypt or decrypt data yourself, into a buffer you already own. No allocation happens inside the SDK.
Method(s)
size_t pubnub_crypto_module_encrypt_size(pubnub_crypto_module_t* module, size_t input_len);
size_t pubnub_crypto_module_encrypted_base64_size(pubnub_crypto_module_t* module, size_t input_len);
pubnub_res_t pubnub_crypto_module_encrypt_buf(pubnub_crypto_module_t* module,
const uint8_t* input, size_t input_len,
uint8_t* output, size_t output_cap,
size_t* output_len);
pubnub_res_t pubnub_crypto_module_decrypt_buf(pubnub_crypto_module_t* module,
const uint8_t* input, size_t input_len,
uint8_t* output, size_t output_cap,
size_t* output_len);
| Parameter | Description |
|---|---|
moduleType: pubnub_crypto_module_t* | Required, borrowed. |
inputType: const uint8_t* | Required, borrowed. Plaintext for encrypt; PNED-headed or raw legacy ciphertext for decrypt. |
input_lenType: size_t | Length of input in bytes. |
outputType: uint8_t* | Required. Caller-owned, pre-allocated output buffer. |
output_capType: size_t | Capacity of output in bytes. |
output_lenType: size_t* | Required. Receives the actual number of bytes written on success. |
pubnub_crypto_module_encrypt_size() returns the worst-case output size (PNED header + metadata + ciphertext) for a plaintext of input_len bytes, or 0 on error (for example, a NULL module). pubnub_crypto_module_encrypted_base64_size() returns the equivalent worst-case size for the base64-encoded form, including the NUL terminator. Call one of these before _encrypt_buf/_encrypt_to_base64 to size your buffer.
C-family contract
- Header —
#include <pubnub/features/crypto.h> - Types —
pubnub_crypto_module_t - Feature flag —
PUBNUB_ENABLE_CRYPTO - Ownership / lifetime — no allocation.
outputis entirely caller-owned, before and after the call. - Buffers — see the warning below. This is the single most consequential detail on this page.
- Blocking — never blocks. Synchronous local computation.
Both encrypt and decrypt enforce their buffer size
pubnub_crypto_module_encrypt_buf() checks output_cap against pubnub_crypto_module_encrypt_size() and returns PUBNUB_ERR_BUFFER_TOO_SMALL if your buffer is too small. pubnub_crypto_module_decrypt_buf() requires output_cap >= input_len (plaintext is never longer than the ciphertext that carried it) and returns PUBNUB_ERR_BUFFER_TOO_SMALL if that condition is not met. Always size your decrypt output buffer to at least input_len bytes; the function checks this for you before writing anything.
Sample code
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pubnub_crypto_module_t* crypto = pubnub_crypto_module_aes_cbc("my-cipher-key", 1, NULL);
if (NULL == crypto) {
return EXIT_FAILURE;
}
const uint8_t plaintext[] = "encrypt me";
const size_t plaintext_len = sizeof(plaintext) - 1;
show all 61 linesReturns
PUBNUB_OK on success. pubnub_crypto_module_encrypt_buf() returns PUBNUB_ERR_BUFFER_TOO_SMALL if output_cap is insufficient, or PUBNUB_ERR_CRYPTO on an encrypt failure. pubnub_crypto_module_decrypt_buf() returns PUBNUB_ERR_BUFFER_TOO_SMALL if output_cap < input_len, or PUBNUB_ERR_CRYPTO on failure (no matching cryptor for the input's identifier, a decryption error, or a truncated header). See Error handling.
Encrypt and decrypt into an SDK-allocated buffer
These variants allocate the output buffer for you, sized exactly to the result.
Method(s)
pubnub_res_t pubnub_crypto_module_encrypt(pubnub_crypto_module_t* module,
const uint8_t* input, size_t input_len,
uint8_t** output, size_t* output_len);
pubnub_res_t pubnub_crypto_module_decrypt(pubnub_crypto_module_t* module,
const uint8_t* input, size_t input_len,
uint8_t** output, size_t* output_len);
void pubnub_crypto_module_free(pubnub_crypto_module_t* module, void* ptr);
| Parameter | Description |
|---|---|
moduleType: pubnub_crypto_module_t* | Required, borrowed. |
inputType: const uint8_t* | Required, borrowed. |
input_lenType: size_t | Length of input in bytes. |
outputType: uint8_t** | Required. Receives an allocator-owned buffer pointer. |
output_lenType: size_t* | Required. Receives the output length in bytes. |
C-family contract
- Header —
#include <pubnub/features/crypto.h> - Ownership / lifetime — the SDK allocates
*outputusing the module's own stored allocator (the one passed to the factory that created it, or the compiled-in default ifNULLwas passed). Free it withpubnub_crypto_module_free(module, ptr), notfree()directly, and pass the same module that produced the pointer, not any other module or allocator.pubnub_crypto_module_free()isNULL-safe forptr. - Buffers — no capacity to size yourself. The SDK sizes the allocation exactly to the encrypted or decrypted result.
- Blocking — never blocks.
Sample code
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pubnub_crypto_module_t* crypto = pubnub_crypto_module_aes_cbc("my-cipher-key", 1, NULL);
if (NULL == crypto) {
return EXIT_FAILURE;
}
const uint8_t plaintext[] = "encrypt me, allocated";
const size_t plaintext_len = sizeof(plaintext) - 1;
show all 38 linesReturns
PUBNUB_OK on success with *output/*output_len populated, PUBNUB_ERR_OUT_OF_MEMORY or PUBNUB_ERR_CRYPTO on encrypt failure, PUBNUB_ERR_CRYPTO on decrypt failure.
Encrypt and decrypt as base64 text
A convenience pair that combines encryption with base64 encoding in one call, the same mechanism publish, subscribe, and history use internally to move encrypted payloads through JSON.
Method(s)
pubnub_res_t pubnub_crypto_module_encrypt_to_base64(pubnub_crypto_module_t* module,
const uint8_t* input, size_t input_len,
char** out_base64, size_t* out_len);
pubnub_res_t pubnub_crypto_module_decrypt_from_base64(pubnub_crypto_module_t* module,
const char* base64, size_t base64_len,
uint8_t** output, size_t* output_len);
| Parameter | Description |
|---|---|
moduleType: pubnub_crypto_module_t* | Required, borrowed. |
input / base64Type: const uint8_t* / const char* | Required, borrowed. Plaintext to encrypt, or base64 ciphertext to decrypt. |
input_len / base64_lenType: size_t | Length of the corresponding input in bytes. |
out_base64 / outputType: char** / uint8_t** | Required. Receives an allocator-owned buffer. |
out_len / output_lenType: size_t* | Required. Receives the output length in bytes. |
C-family contract
- Header —
#include <pubnub/features/crypto.h> - Ownership / lifetime — same rule as the allocating binary variants: free the output with
pubnub_crypto_module_free(module, ptr), using the module that produced it. - Blocking — never blocks.
Sample code
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
pubnub_crypto_module_t* crypto = pubnub_crypto_module_aes_cbc("my-cipher-key", 1, NULL);
if (NULL == crypto) {
return EXIT_FAILURE;
}
const uint8_t plaintext[] = "{\"text\":\"hello\"}";
show all 39 linesReturns
PUBNUB_OK on success with the output pointer and length populated; PUBNUB_ERR_CRYPTO on encrypt or decrypt failure.
Migrate from legacy to AES-CBC
This is how a legacy-to-AES-CBC migration stays transparent: encrypt always uses only the module's default cryptor, but decrypt can use the default cryptor or any of its fallbacks.
Decrypt resolves which cryptor to use like this:
- If the input carries a PNED header (the short binary marker ACRH writes ahead of its ciphertext), the module reads the header's 4-byte identifier and looks for a cryptor with a matching
identifier, the default cryptor first, then each fallback in order. If nothing matches, decryption fails withPUBNUB_ERR_CRYPTO. - If the input has no PNED header, it is treated as legacy-format ciphertext, and the module looks for a cryptor whose identifier is the all-zero legacy identifier (default first, then fallbacks). If none match, decryption fails with
PUBNUB_ERR_CRYPTO. - Encryption never consults this fallback list. It is decrypt-only: every encrypt call uses whatever cryptor
pubnub_crypto_module_default_cryptor()reports for that module.
Both named factories exploit this automatically: pubnub_crypto_module_aes_cbc() wires in an internally created legacy cryptor as its fallback, and pubnub_crypto_module_legacy() wires in an internally created ACRH cryptor as its fallback. The practical result is that switching your application's default cryptor from legacy to ACRH does not require re-encrypting anything already stored: create an ACRH module going forward, and it can still decrypt every message your old, legacy-default deployment encrypted, because the legacy identifier is already in its fallback list.
#include <pubnub/client.h>
#include <pubnub/features/crypto.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/* Data encrypted earlier, when the application's default cryptor
* was legacy. */
pubnub_crypto_module_t* old_deployment = pubnub_crypto_module_legacy("my-cipher-key", 1, NULL);
if (NULL == old_deployment) {
return EXIT_FAILURE;
}
show all 67 linesWrite a custom cryptor (the provider vtable)
Implement pubnub_crypto_provider_t to plug in an algorithm the SDK does not ship, for example a hardware security module, or a third algorithm you need for interoperability. Pass your provider to pubnub_crypto_module_create() as default_cryptor or as an entry in others.
The sample below is a structural template for wiring up the vtable. Implement encrypt, decrypt, and hmac_sha256 with a real cryptographic library before using anything like it in production.
Method(s)
typedef struct pubnub_encrypted_data {
uint8_t* data;
size_t data_len;
uint8_t* metadata;
size_t metadata_len;
} pubnub_encrypted_data_t;
typedef struct pubnub_crypto_provider {
uint8_t identifier[4];
size_t (*encrypt_size)(struct pubnub_crypto_provider* self, size_t plaintext_len);
pubnub_res_t (*encrypt)(struct pubnub_crypto_provider* self,
const uint8_t* input, size_t input_len,
pubnub_encrypted_data_t* output);
show all 28 lines| Field | Description |
|---|---|
identifier[4] | 4-byte algorithm identifier the module matches on decrypt (see Migrate from legacy to AES-CBC). Use all zeros only if you specifically mean "legacy/default algorithm." |
encrypt_size | Returns the exact output size your encrypt needs for a given plaintext length, so the caller (the module, or a caller of the buffer variants) can size output->data correctly before calling encrypt. pubnub_encrypted_data_t carries no capacity field of its own, so encrypt_size() is the only contract governing how large a buffer the caller prepares. |
encrypt | Writes ciphertext into output->data and sets output->data_len; writes algorithm-specific metadata (for example, an IV) into output->metadata and sets output->metadata_len, or leaves metadata untouched (NULL/0) if your algorithm needs none. |
decrypt | output_len is in/out: on entry it carries the caller's buffer capacity, on exit the actual plaintext length. Unlike the SDK's own OpenSSL-backed ACRH and legacy cryptors, a custom decrypt does receive its buffer's capacity through output_len and should check it before writing, since nothing else in the call path performs that check. |
hmac_sha256 | Required only if this provider will sign Access Manager requests; output buffer is at least 32 bytes. |
init / deinit | Optional (NULL = no-op). Called once per context, during context initialization and teardown respectively, from normal (non-ISR) context only. |
C-family contract
- Header —
#include <pubnub/providers/crypto.h> - Types —
pubnub_crypto_provider_t,pubnub_encrypted_data_t - Thread / callback context — every callback runs from normal (non-ISR) context only.
Sample code
#include <pubnub/error.h>
#include <pubnub/providers/crypto.h>
#include <stddef.h>
#include <stdint.h>
/* Toy XOR "cryptor" — illustrates vtable wiring only. This is NOT secure
* and must never be used to protect real data; a real implementation
* needs a vetted cryptographic library for encrypt/decrypt/hmac_sha256. */
static size_t demo_encrypt_size(struct pubnub_crypto_provider* self, size_t plaintext_len)
{
(void)self;
return plaintext_len;
}
show all 72 linesdemo_provider is a plain static struct with no dynamic state, so it has nothing for pubnub_cryptor_destroy() to free or zero. That function exists for cryptors obtained from pubnub_cryptor_aes_cbc_create()/pubnub_cryptor_legacy_create(), which do own allocated state. Pass &demo_provider to pubnub_crypto_module_create() as default_cryptor or as an entry in others. You own its lifetime for as long as any module references it, and there is no destroy call to make on the provider itself.
Returns
Each callback returns pubnub_res_t; PUBNUB_OK on success. The module surfaces PUBNUB_ERR_CRYPTO to its own caller when a callback fails, except for a PUBNUB_ERR_BUFFER_TOO_SMALL your decrypt returns explicitly, which propagates unchanged.
Error handling
Crypto operations return the same pubnub_res_t type every other feature uses; see The pubnub_res_t result catalog for the full list. The two values specific to this page:
PUBNUB_ERR_CRYPTO: no cryptor in the module matched the input's identifier, a decrypt or encrypt operation failed inside the selected cryptor, or a PNED header was truncated or malformed.PUBNUB_ERR_BUFFER_TOO_SMALL: returned by the encrypt path when your output buffer is smaller thanpubnub_crypto_module_encrypt_size()reports, and by the decrypt path whenoutput_cap < input_len; see the buffer-sizing warning above.