Encoding and Encryption Guidelines

The PubNub AES Encryption standard adheres to the following configuration requirements:

AES Strength: 256 bit

Mode : CBC

IV : 16 byte value of "0123456789012345"

Padding : PKCS5

Key : The cipher key must always be a 32 element byte array.

In an effort to be cross compatible against multiple platforms, a specific procedure is used to generate this key. In the following example, the user-defined cipher key will be enigma.

  1. Get the string representation of the SHA256 message digest, where the message is the cipher key "enigma".
    $sha_cipher_key_string = SHA256hash_string("enigma");
    Yielding the 64 character string representation of the 32 byte hex value:

  2. Remove 32 characters from the end of this string, leaving the remaining 32 character string representation of a 16 byte hex value:

  3. For each character in this string, take the hex representation of the ASCII character value. For example, the first character, 6, has an ASCII decimal value of 54, and a hex value of 36. So the first value would be 0x36. The second character, 7, has an ASCII decimal value of 55, and a hex value of 37, so the second value would be 0x37.  For the above string, the final, 32 element byte array cipher key would be: 

36 37 61 34 66 34 35 66 30 64 31 64 39 62 63 36 

30 36 34 38 36 66 63 34 32 64 63 34 39 34 31 36


You can easily run through this using openssl and the GNU sha256sum utility:

  1. Derive sha256("enigma"), keeping only the first 32 characters:
    $ geremy@dually:/pubnub-api/javascript$ echo -n "enigma" | sha256sum | cut -c 1-32

  2. Convert it to its hex representation:
    $ echo -n "67a4f45f0d1d9bc606486fc42dc49416" | od -A n -t x1 | sed ':a;N;$!ba;s/\n/ /g'  |  sed 's/ //g'

  3. Use this value for the cipher key, encrypting the JSON string "\"Pubnub Messaging API 1\""

NOTE : Being a JSON encoded string, it is double-quoted!

$ echo -n "\"Pubnub Messaging API 1\"" | openssl enc -aes-256-cbc -e -a -K

3637613466343566306431643962633630363438366663343264633439343136 -iv 30313233343536373839303132333435 


JSON Encoding with and without Encryption


All received, unencrypted URLs (including the message data) follow this sequence of decoding:

  1. URL decode the entire URL
  2. JSON Decode the Message 
  3. Process the native objects (array, string, object, etc) through the callback


All outgoing, unencrypted URLS follow this sequence of encoding:

  1. JSON Encode the native objects (the message)
  2. URL encode the entire URL (including channel, message, UUID, etc)


As an example, given the channel hello^world and the message string "hello there!", the final fully encoded URL string would look like this:



All outgoing and received encrypted URLs follow the same sequence of encoding and decoding as above, with one exception – there is some extra processing required for the message portion of the URL. All received, encrypted messages follow this sequence of decoding:

URL_DECODED(url) → JSON_DECODE(message) → BASE64_DECODE(message) → AES256_DECODE(message) → JSON_DECODE(message) → NATIVE_OBJECTS


All encrypted, outgoing messages follow this sequence of encoding:

NATIVE_OBJECTS → JSON_ENCODE(message) → AES256_ENCODE(message) → BASE64_ENCODE(message) → JSON_ENCODE(message) → URL_ENCODE(url)


The following demonstrates a step-by-step representation of the encoding process, based on the above mentioned encoding sequence.

For this example, the message will be "Pubnub Messaging API 1".

NOTE: You will see double-quotes, and quadruple-quotes in the following example. Double-quotes are intended to convey the phrase the string, where as quadruple-quotes are intended to convey the phrase the quoted string.


For example, "abc", should be read as 'The string value of a, b, and c', whereas ""abc"" should be read as 'The string value of quote, a, b, and c':

  1. "Pubnub Messaging API 1" is JSON encoded into ""Pubnub Messaging API 1""
  2. This string is then encrypted into binary data (for this example, using the cipher key of enigma ). If you try to view it without using a hex viewer, it may look garbled or unreadable.
  3. To turn it into something we can easily transmit over HTTP, it is BASE64-encoded into "f42pIQcWZ9zbTbH8cyLwByD/GsviOE0vcREIEVPARR0="

    NOTE: Some versions of Base64 encode will add a carriage return (\n) to the encoded data.  If your version does this, try to find a version that doesn't, or chop that \n **off.

  4. It is now JSON encoded once again, to resemble ""f42pIQcWZ9zbTbH8cyLwByD\/GsviOE0vcREIEVPARR0=""

  5. It is finally placed into the message component of the URL, where the entire URL is then URL-encoded.


As an example, given the channel hello_world and the message string "Pubnub Messaging API 1" , the final fully encoded, encrypted URL string would look like this:


Handling non-encrypted traffic when encryption is enabled

If enabled for encryption, but there is an error decrypting the traffic for whatever reason, pass the message through as:


PubNub over the wire example Base64 Encoded ↔ Cipher/Plaintext Pairs using SHA256("engima") for Cipher Key

SHA256 of "enigma" trimmed to 32 bytes





{} (empty JSON object)





{"foo" : {"bar" : "foobar"}} (JSON Object)



{"this stuff":{"can get":"complicated!"}}  (JSON Object)






"\"Pubnub Messaging API 2\"" (JSON String)



"\"Pubnub Messaging API 1\"" (JSON String)