# Secure channel encryption (/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Media stream encryption encrypts audio and video streams with a unique [key](https://en.wikipedia.org/wiki/Public_key_certificate) and [salt](https://en.wikipedia.org/wiki/Salt_%28cryptography%29) controlled by your app server. Encryption ensures that only authorized users in a channel can see and hear each other. RTC SDK provides built-in encryption methods that you can use to guarantee data confidentiality during transmission.

This article describes how to integrate Agora built-in media stream encryption into your app.

## Understand the tech

The following figure illustrates data transfer with media stream encryption enabled.

**Data transfer process**


      
![Encrypted media stream transfer process](https://assets-docs.agora.io/images/video-sdk/encrypt_media_streams_dataTransferProcess.svg)

    
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  

## Prerequisites

Ensure that you have implemented the [SDK quickstart](/en/realtime-media/rtc/get-started-sdk) in your project.

## Implement media stream encryption


      
To add built-in media stream encryption to your app, refer to the following steps.

1. Generate a key and salt on your server.

   To generate a random 32-byte hexadecimal key on your server as a string, run:

   ```bash
   openssl rand -hex 32
   ```

   To generate a random Base64-encoded, 32-byte salt on your server, run:

   ```bash
   openssl rand -base64 32
   ```

2. Implement client-side logic.

   <CalloutContainer type="info">
     <CalloutDescription>
       All users in a channel must use the same encryption mode, key, and salt. Discrepancies may lead to unexpected behavior, such as black screens or audio loss.

       To ensure security, use a new key and salt each time you enable media stream encryption.
     </CalloutDescription>
   </CalloutContainer>

   Obtain the string key and Base64-encoded salt from your server, convert the salt from Base64 to `uint8_t`, and call `enableEncryption` before joining a channel. Set the encryption mode to `AES_128_GCM2` or `AES_256_GCM2` and pass the key and salt to the SDK.

   <CodeBlockTabs defaultValue="Java">
     <CodeBlockTabsList>
       <CodeBlockTabsTrigger value="Java">
         Java
       </CodeBlockTabsTrigger>

       <CodeBlockTabsTrigger value="Kotlin">
         Kotlin
       </CodeBlockTabsTrigger>
     </CodeBlockTabsList>

     <CodeBlockTab value="Java">
       ```java  tabGroup="encryption-android"
       // Noise-free sample values must come from your server.
       String encryptionKey = getEncryptionKeyFromServer();
       byte[] encryptionKdfSalt = getEncryptionSaltFromServer();

       EncryptionConfig config = new EncryptionConfig();
       config.encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2;
       config.encryptionKey = encryptionKey;
       config.encryptionKdfSalt = encryptionKdfSalt;

       int result = rtcEngine.enableEncryption(true, config);
       ```
     </CodeBlockTab>

     <CodeBlockTab value="Kotlin">
       ```kotlin  tabGroup="encryption-android"
       // Noise-free sample values must come from your server.
       val encryptionKey = getEncryptionKeyFromServer()
       val encryptionKdfSalt = getEncryptionSaltFromServer()

       val config = EncryptionConfig().apply {
         encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2
         this.encryptionKey = encryptionKey
         this.encryptionKdfSalt = encryptionKdfSalt
       }

       val result = rtcEngine.enableEncryption(true, config)
       ```
     </CodeBlockTab>
   </CodeBlockTabs>

## Reference

### Sample project

* [ChannelEncryption](https://github.com/AgoraIO/API-Examples/blob/main/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ChannelEncryption.java)

### API reference

* [`enableEncryption`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_irtcengine.html#api_irtcengine_enableencryption)
* [`EncryptionConfig`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_encryptionconfig.html)

    
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  
      
  


## Platform-specific versions
- [Android](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/android.md)
- [iOS](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/ios.md)
- [macOS](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/macos.md)
- [Web](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/web.md)
- [Windows](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/windows.md)
- [Electron](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/electron.md)
- [Flutter](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/flutter.md)
- [React Native](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/react-native.md)
- [Unity](/en/realtime-media/rtc/build/secure-and-protect-channels/media-stream-encryption/unity.md)
