Encrypting Connections and Messages
PubNub allows you to encrypt data using TLS/SSL for point-to-point encryption and AES-256 for payload encryption. With TLS/SSL enabled, your data is encrypted as it travels over the internet, but is decrypted, processed, and re-encrypted as it passes through the PubNub network and back out again. To ensure the highest levels of message integrity and end-to-end data security, use TLS/SSL in combination with message-level encryption with AES payload encryption.
Enabling transport-layer encryption
Enable transport-layer encryption with TLS/SSL by setting the ssl
parameter to true
.
const pubnub = new PubNub({
subscribeKey: 'mySubscribeKey',
publishKey: 'myPublishKey',
uuid: 'user-1',
ssl: true,
});
var config = PubNubConfiguration(
subscribeKey: "mySubscribeKey",
publishKey: "myPublishKey",
uuid: "user-1",
useSecureConnections: true
)
var pubnub = PubNub(configuration: config)
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setSubscribeKey("mySubscribeKey");
pnConfiguration.setPublishKey("myPublishKey");
pnConfiguration.setUuid("user-1");
pnConfiguration.setSecure(true);
PubNub pubNub = new PubNub(pnConfiguration);
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.SubscribeKey = "mySubscribeKey";
pnConfiguration.PublishKey = "myPublishKey";
pnConfiguration.UUID = "user-1";
pnConfiguration.Secure = true;
PubNub pubnub = new PubNub(pnConfiguration);
Encrypting message payloads
The code samples below demonstrate how to enable PubNub data-layer encryption with AES-256. When you initialize the client with a cipherKey, PubNub uses that key to AES-256 encrypt the message payload before it's published to the network. The client SDK automatically decrypts the data before displaying it.
const pubnub = new PubNub({
subscribeKey: 'mySubscribeKey',
publishKey: 'myPublishKey',
uuid: 'user-1',
cipherKey: 'myCipherKey',
});
var config = PubNubConfiguration(
subscribeKey: "mySubscribeKey",
publishKey: "myPublishKey",
uuid: "user-1",
cipherKey: "myCipherKey"
)
var pubnub = PubNub(configuration: config)
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setSubscribeKey("mySubscribeKey");
pnConfiguration.setPublishKey("myPublishKey");
pnConfiguration.setUuid("user-1");
pnConfiguration.setCipherKey("myCipherKey");
PubNub pubNub = new PubNub(pnConfiguration);
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.SubscribeKey = "mySubscribeKey";
pnConfiguration.PublishKey = "myPublishKey";
pnConfiguration.UUID = "user-1";
pnConfiguration.CipherKey = "myCipherKey";
pnConfiguration.Secure = true;
PubNub pubnub = new PubNub(pnConfiguration);
You can use the cipherKey
on any device. The cipherKey
is just a symmetric key used for encryption. What you need to ensure is that the cipherKey
is transmitted securely from your server to device. Don't hard-code your cipher key. Messages exchanged over a TLS session are encrypted using a symmetric key too. During the SSL/TLS handshake, public key techniques are used to agree on the symmetric key. Also, cipher keys are only to be shared with trusted parties.
Sending a signed message
General overview only
The following is a general overview only. PubNub SDKs don't include digital signatures. To learn more, refer to User identification with digital signature message verification.
Malicious actors may attempt to spoof other users’ identities to impersonate them. You may consider using a digital signature as a fingerprint.
To attach a digital signature to a message, create the signature by concatenating username + message
. Then, calculate a message digest using the SHA1 or SHA256 algorithm.
Now, you can use this cryptographically generated hash to sign with the user's private key using an ECC/RSA asymmetric algorithm. Finally, attach the signature with the message object to publish.
Receiving a signed message
General overview only
The following is a general overview only. PubNub SDKs don't include digital signatures. To learn more, refer to User identification with digital signature message verification.
When you receive a message with a signature, use the signature to verify the authenticity of the message. If the message was an attempted spoof, drop the message.
To verify the signature, recreate the signature by concatenating the base string (username + message), and calculate a message digest using SHA1 or SHA256. Compare this digest with the original message digest.
You should only print the username retrieved from the Public Key Trusted Source and not from the message content. The message content is only used for signing and verifying identity. If an identity is changed, it must be relayed via the Public Key Infrastructure (PKI) using PubNub's Broadcast mechanism and Storage and Playback for Secure Authorization.
Access tokens, identity names and photos, and asymmetric keys must only be generated from trusted execution environments on your servers, and relayed over a PubNub authorized read-only PKI data channel.
File Encryption
Much like messages, you can also encrypt the files sent from your clients using a cipherKey.
If you specified a cipherKey in the configuration, you don't have to explicitly specify it in the method to encrypt or decrypt the uploaded files. If you do pass a cipherKey in the sendFile
or downloadFile
methods, that key takes precedence over the cipherKey you provided in the configuration. See Encrypting Message Payloads for information on how to provide a cipherKey in the configuration.
With client-side encryption, the SDK encrypts file data before it is uploaded to the storage service. The receiving client must decrypt the data upon download using the same key before it is displayed in the end-user application.
Distribution of Keys
While the PubNub SDKs provide methods for encryption and decryption, they do not provide the ability to distribute cipher keys. It is your responsibility to manage and securely distribute and rotate keys for your clients.
Encrypting Files
You can provide a cipherKey in the sendFile
method to encrypt a file or you can use a cipherKey you provided in the configuration. The following example shows how to encrypt the file cat_picture.jpg
with the cipherKey my_cipher_key
you provide in the method body.
Key Priority
The cipherKey you provide in the body of the method takes precedence over the cipherKey you provide in the configuration.
import fs from 'fs';
const myFile = fs.readFileSync('./cat_picture.jpg');
const result = await pubnub.sendFile({
channel: 'my_channel',
message: 'Look at this picture!',
file: { data: myFile, name: 'cat_picture.jpg', mimeType: 'image/jpeg' },
cipherKey: 'my_cipher_key',
});
PNResult<PNFileUploadResult> fileUploadResponse = await pubnub.SendFile()
.Channel("my_channel")
.File("cat_picture.jpg") // checks the bin folder if no path is provided
.CipherKey("my_cipher_key")
.Message("Look at this photo!")
.ExecuteAsync();
PNFileUploadResult fileUploadResult = fileUploadResponse.Result;
PNStatus fileUploadStatus = fileUploadResponse.Status; // contains troubleshooting info
if (!fileUploadStatus.Error && fileUploadResult != null) // checks if successful
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileUploadResult));
}
else
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileUploadStatus));
}
file, err := os.Open("cat_picture.jpg")
defer file.Close()
if err != nil {
panic(err)
}
resSendFile, statusSendFile, errSendFile := pn.SendFile().
Channel("my_channel").
Message("Look at this photo!").
CipherKey("my_cipher_key").
Name("cat_picture.jpg").
File(file).Execute()
fmt.Println(resSendFile, statusSendFile, errSendFile)
fmt.Println(resSendFile.Data.ID)
NSURL *localFileURL = ...;
PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"my_channel"
fileURL:localFileURL];
request.cipherKey = @"my_cipher_key";
[self.client sendFileWithRequest:request completion:^(PNSendFileStatus *status) {
if (!status.isError) {
/**
* File upload successfully completed.
* Uploaded file information is available here:
* status.data.fileIdentifier is the unique file identifier
* status.data.fileName is the name used to store the file
*/
} else {
/**
* Handle send file error. Check the 'category' property for reasons
* why the request may have failed.
*
* Check 'status.data.fileUploaded' to determine whether to resend the
* request or if only file message publish should be called.
*/
}
}];
Decrypting Files
You must provide a cipherKey in the downloadFile
method to decrypt a file or you can use a cipherKey you provided in the configuration. The following example shows how to decrypt the file cat_picture.jpg
with the cipherKey my_cipher_key
you provide in the method body.
Key Priority
The cipherKey you provide in the body of the method takes precedence over the cipherKey you provide in the configuration.
const file = await pubnub.downloadFile({
channel: 'my_channel',
id: 'd9515cb7-48a7-41a4-9284-f4bf331bc770',
name: 'cat_picture.jpg',
cipherKey: 'my_cipher_key',
});
PNResult<PNDownloadFileResult> fileDownloadResponse = await pubnub.DownloadFile()
.Channel("my_channel")
.FileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
.FileName("cat_picture.jpg")
.CipherKey("my_cipher_key")
.ExecuteAsync();
PNDownloadFileResult fileDownloadResult = fileDownloadResponse.Result;
PNStatus fileDownloadStatus = fileDownloadResponse.Status; // contains troubleshooting info
if (!fileDownloadStatus.Error && fileDownloadResult != null) // checks if successful
{
fileDownloadResult.SaveFileToLocal(downloadUrlFileName); //saves to bin folder if no path is provided
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileDownloadResult.FileName));
}
else
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileDownloadStatus));
}
resDLFile, statusDLFile, errDLFile := pn.DownloadFile().
Channel("my_channel").
CipherKey("my_cipher_key").
ID("d9515cb7-48a7-41a4-9284-f4bf331bc770").
Name("cat_picture.jpg").Execute()
if resDLFile != nil {
filepathOutput := "cat_picture.jpg"
out, _ := os.Create(filepathOutput)
_, err := io.Copy(out, resDLFile.File)
if err != nil {
fmt.Println(err)
}
}
PNDownloadFileRequest *request = [PNDownloadFileRequest requestWithChannel:@"my_channel"
identifier:@"<file-identifier>"
name:@"cat_picture.jpg"];
request.targetURL = ...;
request.cipherKey = @"my_cipher_key";
[self.client downloadFileWithRequest:request
completion:^(PNDownloadFileResult *result, PNErrorStatus *status) {
if (!status.isError) {
/**
* File successfully has been downloaded.
* status.data.location - location where downloaded file can be found
* status.data.temporary - whether file has been downloaded to temporary storage and
* will be removed on completion block return.
*/
} else {
/**
* Handle file download error. Check 'category' property to find out possible issue
* because of which request did fail.
*
* Request can be resent using: [status retry]
*/
}
}];