---
source_url: https://www.pubnub.com/docs/general/setup/data-security
title: Data Security
updated_at: 2026-06-01T12:03:03.296Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Data Security

PubNub is serious about the security of your data. Using TLS and AES256 encryption algorithms, and with [CCPA](https://www.pubnub.com/trust/legal/california-consumer-privacy-act/), [GDPR](https://www.pubnub.com/trust/legal/gdpr/), [HIPAA](https://www.pubnub.com/trust/compliance/hipaa/), [SOC 2 type II](https://www.pubnub.com/trust/compliance/soc2/), [SOC 3](https://cdn.builder.io/o/assets%2F0ee4d50ccdc943eda308d1099e2b1915%2Ff907e6ed501f4139a59d29099ca5c7c2?alt=media&token=7b08c88f-288a-47a6-b72c-240d000e6730&apiKey=0ee4d50ccdc943eda308d1099e2b1915), and [ISO 27001](https://www.pubnub.com/trust/compliance/iso-27001/) compliance, you can be sure your data is safeguarded.

:::tip Compliance reports
If you are a [Pro customer](https://www.pubnub.com/pricing/), you can access the most recent versions of the SOC2 type II and SOC 3 and other compliance reports directly from the [Admin Portal](https://admin.pubnub.com) (under **Organization settings**). If you’re not a Pro customer, contact [PubNub Compliance](https://www.pubnub.com/docs/mailto:compliance@pubnub.com).
:::

There are several ways in which PubNub helps to secure your app:

* [Connection security](#connection-security) secures the traffic between your client and PubNub
* [Message encryption](#message-encryption) provides end-to-end security for every message, in transit and at rest
* [File encryption](#file-encryption) provides end-to-end security for every file you upload, in transit and at rest
* [Access management](https://www.pubnub.com/docs/general/security/access-control) provides a detailed permission schema for your app

:::note User ID / UUID
User ID is also referred to as **UUID/uuid** in some APIs and server responses but **holds the value** of the **userId** parameter you [set during initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id).
:::

## Connection security

PubNub offers connection level security through TLS Encryption ([Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security)). It's enabled by default and generally there is no reason to disable it for any production application.

:::note TLS version
Connections to PubNub APIs are encrypted using TLS 1.2, which provides secure communication over HTTPS between clients and PubNub servers.
:::

### Configuring TLS

TLS is enabled by default. If you need to disable it for any reason, it can be done during the PubNub object initialization.

:::note SSL
Some PubNub SDKs, the parameter name is `ssl` (a legacy name for TLS) but it represents the latest connection encryption technology available. *SSL v3* was deprecated due to a security exploit that was discovered and TLS was developed to replace it as the industry standard. Many will refer to TLS as SSL out of habit.
:::

###### JavaScript

```javascript
var pubnub = new PubNub({
    subscribeKey: "mySubscribeKey",
    publishKey: "myPublishKey",
    userId: "myUniqueUserId",
    ssl: false // default 'true'
});
```

###### Swift

```swift
import PubNubSDK

let config = PubNubConfiguration(
  publishKey: "demo",
  subscribeKey: "demo",
  userId: "myUniqueUserId",
  useSecureConnections: false // default true
)

let pubnub = PubNub(configuration: config)
```

###### Objective-C

```objectivec
PNConfiguration *pnconfig = [PNConfiguration configurationWithPublishKey:@"myPublishKey"
                                             subscribeKey:@"mySubscribeKey"];

pnconfig.uuid = "theClientUUID"
pnconfig.TLSEnabled = NO; // default YES
self.client = [PubNub clientWithConfiguration:pnconfig];
```

###### Java

```java
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "yourSubscribeKey");
// publishKey from Admin Portal (only required if publishing)
configBuilder.publishKey("PublishKey");
configBuilder.secure(false);
PubNub pubNub = PubNub.create(configBuilder.build());
```

###### C#

```csharp
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"));
pnConfiguration.PublishKey = "myPublishKey";
pnConfiguration.SubscribeKey = "mySubscribeKey";
pnConfiguration.Secure = false;  // default true

Pubnub pubnub = new Pubnub(pnConfiguration);
```

###### Python

```python
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub

pnconfig = PNConfiguration()
pnconfig.publish_key = "myPublishKey"
pnconfig.subscribe_key = "mySubscribeKey"
pnconfig.user_id = "myUserID"
pnconfig.ssl = False # default True

pubnub = PubNub(pnconfig)
```

### TCP connection troubleshooting

If you need to capture the TCP traffic (a tcpdump to a `.pcap` file) to analyze and debug the network traffic, you may need to disable TLS in your development environment. This level of analysis is only necessary to troubleshoot the most difficult network connection and communication issues that are typically outside of the PubNub domain.

### Custom domain

You might want to use your own domain name for client applications to access PubNub’s real-time messaging infrastructure instead of the default PubNub endpoint `ps.pndsn.com`.

The reasons can include:

* Branding – a custom domain helps maintain a consistent and professional brand image across all your services and interactions by making your application's traffic appear under your own domain
* Compliance and control – you may have legal or regulatory requirements to use custom domains for data management, offering more control over how data is accessed and tracked.
* Infrastructure integration – for better integration with the existing security, CDN, or networking infrastructure, optimizing your overall system configuration.
* Traffic management – a custom domain allows PubNub to route traffic per customer efficiently, mainly when a point of presence (PoP) is underperforming or unavailable, improving performance and reliability.

:::note Secure connections
Ensure connections are made over HTTPS instead of HTTP. HTTPS ensures a secure network by encrypting data and protecting your client data by preventing man-in-the-middle attacks.
:::

If you are a paid customer, you can submit a request to [PubNub support](https://support.pubnub.com/hc/en-us) and have the custom domain (a.k.a. origin) configured for you.

PubNub also provides TLS certificate hosting if required. When TLS is used, you must supply us with your own certificate. This service comes with an additional monthly fee.

#### Request process

To request a custom domain, contact PubNub support by raising a [support ticket](https://support.pubnub.com/hc/en-us) entitled "Request Custom Origin" and providing the following details in the request:

* The PubNub account email that has or will have the paid production keyset(s).
* Three choices for your subdomain in order of preference (12 characters or less, like `abc.pubnubapi.com`).
* PubNub SDKs you currently use in your applications: SDK language/name and version.
* If you have customers or devices in China, mention it in the request.

PubNub support will confirm your custom origin name and SDK initialization code for the SDK/version you use.

Once you have it, you can start using it by changing the way you [initialize](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#initialization) a PubNub instance in your SDK (with the [origin](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#initialization) parameter).

#### Connection limits

To improve response times and avoid congestion, browsers have their own limitations to concurrent connections:

| Browser | Connections per host name | Max connections |
| --- | --- | --- |
| Chrome | 6 | 10 |
| Chrome mobile | 6 | 16 |
| Internet Explorer 9 | 6 | 35 |
| Internet Explorer Mobile 9 | 6 | 60 |
| Internet Explorer 10 | 8 | 17 |
| Internet Explorer 11 | 13 | 17 |
| Firefox | 6 | 17 |
| Safari | 6 | 17 |
| Android | 6 | 17 |

## Message encryption

PubNub SDKs allow you to configure the encryption/decryption algorithms using pre-bundled packages for encrypting/decrypting data (cryptors) in your apps through crypto modules.

##### Why encrypt messages?

Use TLS with message-level encryption for strong protection. AES ([Advanced Encryption Standard](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)) is symmetric and end to end. Choose full or partial encryption based on data sensitivity and performance.

### Crypto module

A crypto module contains cryptors that encrypt and decrypt data in your app. You can choose the algorithm:

* Legacy 128‑bit (legacy module)
* Recommended AES‑CBC 256‑bit ([CBC mode](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation))

Compatibility:

* Current SDKs can decrypt content from either module.
* Legacy 128‑bit and AES‑CBC 256‑bit can read each other’s content.
* You can switch to AES‑CBC 256‑bit and still read historical and older‑client messages.

:::note Legacy encryption with 128-bit cipher key entropy
You don't have to change your encryption configuration if you want to keep using the legacy encryption. If you want to use the recommended 256-bit AES-CBC encryption, you **must** explicitly set that in PubNub config.
:::

If you do not explicitly select either module in your app and have `cipherKey` and, optionally, `useRandomInitializationVector` set in PubNub configuration, the client defaults to using the legacy encryption.

For information on how to configure modules, refer to the [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) documentation of each SDK.

:::tip Keep your clients up to date
Apps not using the latest SDK version will **not** be able to decrypt data encrypted using the 256-bit AES-CBC cipher. Make sure to update your clients or encrypt data using the legacy module.
:::

### Upgrade to 256-bit encryption

For information on how to migrate to the recommended encryption algorithm, refer to [256-bit AES-CBC Encryption](https://www.pubnub.com/docs/general/resources/migration-guides/256-bit-encryption-migration).

### Encryption scope

Depending on whether you want to encrypt all messages and files or just some of them, create and register a crypto module differently.

* To fully encrypt every message and file in all channels for a given API key, specify and register the crypto module as part of the PubNub configuration when you create the object.
* To only encrypt some or partially encrypt messages, do not specify the crypto module as part of the PubNub configuration. Instead, create a standalone instance of a crypto module and call one of the available encrypt() or decrypt() methods.

### Encrypting messages

To configure encryption for **all messages and files** in all channels for a given API key, you need to register a module, provide a `cipherKey`, and, optionally, decide whether to use a random initialization vector to encrypt (and decrypt) data.

For information on partial encryption, refer to the [Partial Message Encryption](#partial-message-encryption) section.

#### JavaScript

```javascript
var pubnub = new PubNub({
  ...
  // all necessary config options
  cryptoModule: PubNub.CryptoModule.aesCbcCryptoModule({cipherKey: 'pubnubenigma'})
});
```

#### Swift

```swift
let pubnub = PubNub(
  configuration: PubNubConfiguration(
    ...
    // all necessary config options
    cryptorModule: CryptorModule.aesCbcCryptoModule(with: "pubnubenigma")
  )
)
```

#### Objective-C

```objectivec
...
// all necessary config options
config.cryptoModule = [PNCryptoModule AESCBCCryptoModuleWithCipherKey:@"enigma"
                                          randomInitializationVector:YES];
```

#### Java

```java
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "yourSubscribeKey");
// publishKey from Admin Portal (only required if publishing)
configBuilder.publishKey("PublishKey");
configBuilder.cryptoModule(CryptoModule.createAesCbcCryptoModule("enigma", true));
// all necessary config options
PubNub pubNub = PubNub.create(configBuilder.build());
```

#### Go

```go
config := pubnub.NewConfigWithUserId(UserId("myUniqueUserId"))
// all necessary config options
config.CryptoModule = crypto.NewAesCbcCryptoModule("cipherKey", true)

pn := pubnub.NewPubNub(config)
```

#### Kotlin

```kotlin
val config = com.pubnub.api.v2.PNConfiguration.builder(UserId("myUserId"), "demo").apply {
    publishKey = "demo"
    cryptoModule = CryptoModule.createAesCbcCryptoModule("enigma")
}.build()

val pubnub = PubNub.create(config)
```

#### Rust

```rust
let client = PubNubClientBuilder::with_transport(Transport)
    ...
    // all necessary config options
    .with_cryptor(CryptoModule::new_aes_cbc_module("enigma", true)?)
    .build()?;
```

#### Ruby

```ruby
pubnub = Pubnub.new(
    ...
    # all necessary config options
    crypto_module: Crypto::CryptoModule.new_aes_cbc("enigma", true)
)
```

#### Dart

```dart
final pubnub =
  PubNub(
    ...
    // all necessary config options
    crypto: CryptoModule.aescbcCryptoModule(CipherKey.fromUtf8('enigma'));
  );
```

#### C#/Unity

```csharp
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"));
...
// all necessary config options
pnConfiguration.CryptoModule = new CryptoModule(new AesCbcCryptor("enigma"), new List<ICryptor> { new LegacyCryptor("enigma") })

new PubNub(pnConfiguration);
```

The SDK encrypts each message before publish. The network routes only encrypted data. The message stays encrypted until it reaches the subscribing client.

The subscriber decrypts it with the same cipher key. Data stored in [Message Persistence](https://www.pubnub.com/docs/general/storage) (and logging systems) remains encrypted. Only clients with the cipher key can decrypt it.

:::note Protect your cipher key
You shouldn't share the cipher key outside of the PubNub network.
:::

#### Partial message encryption

Sometimes encrypting only part of the payload makes sense. With *Mobile Push Notifications*, push services must read specific keys and values. Encrypt only sensitive fields and leave push-related fields as clear text.

Create a separate crypto module instance and call `encrypt()` or `decrypt()` on that instance.

##### APNs example

This example shows how to encrypt only the `results` object in an APNs payload.

**Before encryption**:

```json
{
  "pn_apns": {
    "aps": {
      "alert": "Your test results are available.",
      "sound" : "bingbong.aiff"
    }
  },
  "results": {
    "test_name": "pregnancy",
    "results": "positive",
    "notes": "You are having twins!"
  }
}
```

**Encrypt it**:

Only the `results` object must be encrypted. Other fields can remain plain text.

###### JavaScript

```javascript
const clearText = JSON.stringify(
  {"test_name":"pregnancy","results":"positive","notes":"You are having twins!"});

// create a crypto module instance
const cryptoModule = PubNub.CryptoModule.aesCbcCryptoModule({
  cipherKey: "pubnubenigma"
});

const secureText = cryptoModule.encrypt(clearText);
```

###### Swift

```swift
let clearData = [
  "test_name":"pregnancy",
  "results":"positive",
  "notes":"You are having twins!"
]

do {
  let cryptoModule = CryptoModule.aesCbcCryptoModule(with: "pubnubenigma")
  let encryptedMessage = try cryptoModule.encrypt(data: try JSONEncoder().encode(clearData)).get()
} catch {
  // ...
}
```

###### Objective-C

```objectivec
PNCryptoModule *aesCBCCrypto = [PNCryptoModule AESCBCCryptoModuleWithCipherKey:@"enigma" randomInitializationVector:YES];

NSString *message = @"You are having twins!";
NSData *messageData = [message dataUsingEncoding:NSUTF8StringEncoding];

NSData *encryptedWithAESCBC = [aesCBCCrypto encrypt:messageData];
```

###### Java

```java
JsonObject clearData = new JsonObject();
clearData.addProperty("test_name", "pregnancy");
clearData.addProperty("results", "positive");
clearData.addProperty("notes", "You are having twins!");
byte[]  clearBytes = clearData.toString().getBytes(StandardCharsets.UTF_8);

CryptoModule aesCbcCryptoModule = CryptoModule.createAesCbcCryptoModule("myCipherKey01", true);

byte[] encryptedData = aesCbcCryptoModule.encrypt(clearBytes);
// [80, 78, 69, 68, 1, 65, 67, 82, 72, 16, 83, 67, -54, -1, 98, -51, 91, 120, 31, 121, 100, 95, 75, 54, -95, 60, -74, 32, 26, 108, 77, 107, -47, 50, -45, -8, 86, -67, 72, 30, -106, -9, 45, -92, -111, 118, 50, -55, -48, -103, -90, -115, -70, 120, -47, -107, 41, 7, -61, 52, -37, -61, 83, -20, 34, -30, -64, 61, 104, 24, 3, 25, 41, -122, -36, 60, 98, -16, 34, 81, -41, 46, 102, 7, -97, 64, -37, -10, 124, 67, -41, 101, 35, -80, -103, -27, -26, -34, -50, -86, -2, -84, 105, 16, -84, 4]
```

You can now add the `secureData` variable to the payload so that PubNub and third party mobile push vendors can process the Push payload correctly.

Using a 32‑character cipher key for AES‑256, the resulting message payload is as follows.

**After encryption**:

```json
{
  "pn_apns": {
    "aps": {
      "alert": "Your test results are available.",
      "sound" : "bingbong.aiff"
    }
  },
  "results": "Nio2At2uvQzteLoSqznLkZQ3dlFlMzLGlUwbsMndZ7/7tllq2joJw6WcUv3XpMdEugYRnoEvsrlhEVkSnBibxaxDDWMFEDvKS+VLlA8mfmg="
}
```

:::tip Partial Message Encryption
You may need to encrypt certain data values within the APNs/FCM payload, but be sure not to encrypt any APNs/FCM keys, or any values that need to be parsed as unencrypted text by those mobile push services.
:::

### Decrypting messages

On the receiver, use the same crypto module and cipher key to decrypt the encrypted parts of the payload.

#### JavaScript

```javascript
// parse the received message and pass the encrypted parts to decrypt API.
const secureText =
  "Nio2At2uvQzteLoSqznLkZQ3dlFlMzLGlUwbsMndZ7/7tllq2joJw6WcUv3XpMdEugYRnoEvsrlhEVkSnBibxaxDDWMFEDvKS+VLlA8mfmg="

const clearData = pubnub.decrypt(secureText);
```

#### Swift

```swift
// parse the received message and pass the encrypted parts to decrypt API
let secureText =
  "Nio2At2uvQzteLoSqznLkZQ3dlFlMzLGlUwbsMndZ7/7tllq2joJw6WcUv3XpMdEugYRnoEvsrlhEVkSnBibxaxDDWMFEDvKS+VLlA8mfmg="

do {
  let clearData = try pubnub.decrypt(data: Data(base64Encoded: secureText) ?? Data()).get()
} catch {
  // ...
}
```

#### Objective-C

```objectivec
PNCryptoModule *aesCBCCrypto = [PNCryptoModule AESCBCCryptoModuleWithCipherKey:@"enigma" randomInitializationVector:YES];
PNCryptoModule *aesCBCCrypto = [PNCryptoModule AESCBCCryptoModuleWithCipherKey:@"enigma" randomInitializationVector:YES];

// parse the received message and pass the encrypted parts to decrypt API

NSString *secureText =
  @"Nio2At2uvQzteLoSqznLkZQ3dlFlMzLGlUwbsMndZ7/7tllq2joJw6WcUv3XpMdEugYRnoEvsrlhEVkSnBibxaxDDWMFEDvKS+VLlA8mfmg="

NSData *secureData = [[NSData alloc] initWithBase64EncodedString:secureText options:0];
NSString *clearData = [aesCBCCrypto decrypt:secureData];
```

#### Java

```java
// parse the received message and pass the encrypted parts to decrypt API.
CryptoModule aesCbcCryptoModule = CryptoModule.createAesCbcCryptoModule("myCipherKey01", true);
byte[] encryptedData = new byte[]{80, 78, 69, 68, 1, 65, 67, 82, 72, 16, 83, 67, -54, -1, 98, -51, 91, 120, 31, 121, 100, 95, 75, 54, -95, 60, -74, 32, 26, 108, 77, 107, -47, 50, -45, -8, 86, -67, 72, 30, -106, -9, 45, -92, -111, 118, 50, -55, -48, -103, -90, -115, -70, 120, -47, -107, 41, 7, -61, 52, -37, -61, 83, -20, 34, -30, -64, 61, 104, 24, 3, 25, 41, -122, -36, 60, 98, -16, 34, 81, -41, 46, 102, 7, -97, 64, -37, -10, 124, 67, -41, 101, 35, -80, -103, -27, -26, -34, -50, -86, -2, -84, 105, 16, -84, 4};

byte[] decryptedBytes = aesCbcCryptoModule.decrypt(encryptedData);
JsonObject decryptedJson = JsonParser.parseString(new String(decryptedBytes, StandardCharsets.UTF_8)).getAsJsonObject();
assert decryptedJson.get("test_name").getAsString().equals("pregnancy");
assert decryptedJson.get("results").getAsString().equals("positive");
assert decryptedJson.get("notes").getAsString().equals("You are having twins!");
```

For more examples of decrypting messages in other languages, refer to the [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) and/or [Miscellaneous](https://www.pubnub.com/docs/sdks/javascript/api-reference/misc) documentation of each SDK.

## File encryption

You can also encrypt files with a crypto module.

If you registered a crypto module in configuration, you don't need to pass it when encrypting or decrypting uploaded files.

:::warning Do not pass cipher key
Passing a cipher key in `sendFile` or `downloadFile` overrides the crypto module configuration and uses legacy 128‑bit encryption.
Refer to [Encrypting Messages](#encrypting-messages) for information on how to configure the crypto module.
:::

With client‑side encryption, the SDK encrypts file data before upload. The receiving client decrypts the data on download using the same key before it is displayed in the end‑user application.

### Encrypting files

The following shows how to encrypt a file using the crypto module registered in PubNub config.

#### Node.js

```javascript
 import fs from 'fs';

 const myFile = fs.readFileSync('./cat_picture.jpg');

 const result = await pubnub.sendFile({
   channel: 'my_channel',
   message: 'Look at this photo!',
   file: { data: myFile, name: 'cat_picture.jpg', mimeType: 'application/json' }
 });
```

#### C#

```csharp
PNResult<PNFileUploadResult> fileUploadResponse = await pubnub.SendFile()
    .Channel("my_channel")
    .File("cat_picture.jpg") //checks the bin folder if no path is provided
    .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));
}
```

#### Go

```go
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!").
  Name("cat_picture.jpg").
  File(file).Execute()
fmt.Println(resSendFile, statusSendFile, errSendFile)
fmt.Println(resSendFile.Data.ID)
```

#### Objective-C

```objectivec
NSURL *localFileURL = ...;
PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"my_channel"
                                                           fileURL:localFileURL];

[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.
         */
    }
}];
```

#### Java

```java
// encryption is automatic if you have a crypto module configured

pubnub.sendFile()
    .channel("my_channel")
    .fileName("cat_picture.jpg")
    .inputStream(inputStream)
    .message("Look at this photo!")
    .async(result -> {
        result.onSuccess(res -> {
            System.out.println("send timetoken: " + res.getTimetoken());
            System.out.println("send status: " + res.getStatus());
            System.out.println("send fileId: " + res.getFile().getId());
            System.out.println("send fileName: " + res.getFile().getName());
        });
    });
```

### Decrypting files

The following shows how to decrypt a file using the crypto module registered in PubNub config.

#### Node.js

```javascript
const file = await pubnub.downloadFile({
   channel: 'my_channel',
   id: 'd9515cb7-48a7-41a4-9284-f4bf331bc770',
   name: 'cat_picture.jpg'
 });
```

#### C#

```csharp
PNResult<PNDownloadFileResult> fileDownloadResponse = await pubnub.DownloadFile()
    .Channel("my_channel")
    .FileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
    .FileName("cat_picture.jpg")
    .ExecuteAsync();
PNDownloadFileResult fileDownloadResult = fileDownloadResponse.Result;
PNStatus fileDownloadStatus = fileDownloadResponse.Status;
if (fileDownloadResult != null)
{
    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));
}
```

#### Go

```go
resDLFile, statusDLFile, errDLFile := pn.DownloadFile().
  Channel("my_channel").
  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)
    }
}
```

#### Objective-C

```objectivec
PNDownloadFileRequest *request = [PNDownloadFileRequest requestWithChannel:@"my_channel"
                                                                identifier:@"<file-identifier>"
                                                                      name:@"cat_picture.jpg"];
request.targetURL = ...;

[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]
         */
    }
}];
```

#### Java

```java
// decryption is automatic if you have a crypto module configured

pubnub.downloadFile()
    .channel("my_channel")
    .fileName("cat_picture.jpg")
    .fileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
    .async(result -> {
        result.onSuccess(res -> {
            System.out.println("getFile fileName: " + result.getFileName());
            System.out.println("getFile byteStream: " + result.getByteStream());
        });
    });
```

For more examples of encrypting/decrypting files in other languages, refer to the [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) and/or [Files](https://www.pubnub.com/docs/sdks/javascript/api-reference/files) documentation of each SDK.

## Custom encryption

Encryption and decryption are decoupled from the SDKs. You can implement your own methods.

Each SDK exposes an interface to register cryptors.

During decryption, the SDK inspects the payload and chooses the matching cryptor.

### Implementation guidelines

Usage differs by SDK, but the flow is similar:

1. Implement the required interfaces (names vary). See the Crypto interfaces.
2. Create a Crypto module with your cryptor and pass it to PubNub configuration, or use it standalone for partial encryption. Refer to each SDK's Crypto module documentation.

#### Example custom cryptor implementation

This example uses Kotlin, but the idea is the same across SDKs.

1. Implement the Cryptor interface. Note that the id() method should return a ByteArray of exactly 4 bytes. fun myCustomCryptor() = object : Cryptor { override fun id(): ByteArray { // Should return a ByteArray of exactly 4 bytes. return byteArrayOf('C'.code.toByte(), 'U'.code.toByte(), 'S'.code.toByte(), 'T'.code.toByte()) } override fun encrypt(data: ByteArray): EncryptedData { // implement your crypto logic return EncryptedData(metadata = null, data = data) } override fun decrypt(encryptedData: EncryptedData): ByteArray { // implement your crypto logic return encryptedData.data } override fun encryptStream(stream: InputStream): EncryptedStreamData { // implement your crypto logic return EncryptedStreamData(metadata = null, stream = stream) } override fun decryptStream(encryptedData: EncryptedStreamData): InputStream { // implement your crypto logic return encryptedData.stream } }
2. Use your newly created myCustomCryptor that implements the Cryptor interface to instantiate a CryptoModule:

```kotlin
val customCryptor = myCustomCryptor()
val cryptoModule = CryptoModule.createNewCryptoModule(defaultCryptor = customCryptor)
```

### Interfaces to implement

* C-Core: [pbcc_crypto.h](https://github.com/pubnub/c-core/blob/master/core/pbcc_crypto.h#L73-L108)
* C#: [ICryptor.cs](https://github.com/pubnub/c-sharp/blob/master/src/Api/PubnubApi/Security/Crypto/ICryptor.cs)
* Dart: [ICryptor.dart](https://github.com/pubnub/dart/blob/master/pubnub/lib/src/core/crypto/crypto.dart#L28)
* Go: [cryptor.go](https://github.com/pubnub/go/blob/master/crypto/cryptor.go)
* Java: [Cryptor.kt](https://github.com/pubnub/kotlin/blob/master/pubnub-kotlin/pubnub-kotlin-core-api/src/jvmMain/kotlin/com/pubnub/api/crypto/cryptor/Cryptor.kt)
* JavaScript: [ICryptor.ts](https://github.com/pubnub/javascript/blob/master/src/crypto/modules/NodeCryptoModule/ICryptor.ts)
* Kotlin: [Cryptor.kt](https://github.com/pubnub/kotlin/blob/master/pubnub-kotlin/pubnub-kotlin-core-api/src/jvmMain/kotlin/com/pubnub/api/crypto/cryptor/Cryptor.kt)
* Objective-C: [PNCryptor.h](https://github.com/pubnub/objective-c/blob/master/PubNub/Misc/Protocols/PNCryptor.h)
* PHP: [Cryptor.php](https://github.com/pubnub/php/blob/master/src/PubNub/Crypto/Cryptor.php)
* Python: [crypto_core.py](https://github.com/pubnub/python/blob/master/pubnub/crypto_core.py#L38-L47)
* Ruby: [cryptor.rb](https://github.com/pubnub/ruby/blob/master/lib/pubnub/modules/crypto/cryptor.rb)
* Rust: [cryptor.rs](https://github.com/pubnub/rust/blob/master/src/core/cryptor.rs)
* Swift: [Cryptor.swift](https://github.com/pubnub/swift/blob/master/Sources/PubNub/Helpers/Crypto/Cryptors/Cryptor.swift#L36)
* Unity: [ICryptor.cs](https://github.com/pubnub/c-sharp/blob/master/src/Api/PubnubApi/Security/Crypto/ICryptor.cs)
* Unreal: [PubnubCryptorInterface.h](https://github.com/pubnub/unreal-engine/blob/master/Source/PubnubLibrary/Public/Crypto/PubnubCryptorInterface.h)