Secure channel encryption
Media stream encryption refers to encrypting audio and video streams in an app using a unique key and salt controlled by the app developer. Encryption ensures that only the authorized users in a channel see and hear each other. Video 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 the process of data transfer with media stream encryption enabled.
Best practice is to choose the AES_128_GCM2
or AES_256_GCM2
encryption mode and set a key and salt for enhanced security.
Data transfer process
Prerequisites
Ensure that you have implemented the SDK quickstart in your project.
Implement media stream encryption
To add built-in media stream encryption to your app, refer to the following steps:
-
Generate a key and salt on your server
-
To generate a random 32-byte hexadecimal key on your server as a string, refer to the following
OpenSSL
command: -
To generate a random Base64-encoded, 32-byte salt on your server, refer to the following
OpenSSL
command:
-
-
Implement client-side logic
-
Obtain a String key and Base64-encoded salt from the server.
-
Convert the salt from Base64 to
uint8_t
. -
Before joining the channel, call
enableEncryption
to set theAES_128_GCM2
orAES_256_GCM2
encryption mode, and pass the key and salt to the SDK.
-
- 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, best practice is to use a new key and salt each time you enable media stream encryption.
To implement this logic, refer to the following code:
- Java
- Kotlin
import java.util.Base64;import io.agora.rtc2.RtcEngine;import io.agora.rtc2.internal.EncryptionConfig;class Example { public boolean enableEncryption(RtcEngine mRtcEngine) { if (mRtcEngine == null) { return false; } // Obtain the Base64 encoded salt from the server String encryptionKdfSaltBase64 = Server.getEncryptionKdfSaltBase64(); // Obtain the String type key from the server String encryptionSecret = Server.getEncryptionSecret(); if (encryptionKdfSaltBase64 == null || encryptionSecret == null) { return false; } // Convert the Base64 encoded salt to uint8_t byte[] encryptionKdfSalt = Base64.getDecoder().decode(encryptionKdfSaltBase64); // Create an instance of EncryptionConfig EncryptionConfig config = new EncryptionConfig(); // Set the encryption mode to AES_128_GCM2 config.encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2; config.encryptionKey = encryptionSecret; // Copy the encryption KDF salt into the configuration System.arraycopy(encryptionKdfSalt, 0, config.encryptionKdfSalt, 0, config.encryptionKdfSalt.length); // Enable encryption using the configuration int result = mRtcEngine.enableEncryption(true, config); // Return true if result is 0 return (result == 0); // Success }}
import java.util.Base64import io.agora.rtc2.RtcEngineimport io.agora.rtc2.internal.EncryptionConfigclass Example { fun enableEncryption(mRtcEngine: RtcEngine?): Boolean { if (mRtcEngine == null) return false // Obtain the Base64 encoded salt from the server val encryptionKdfSaltBase64 = Server.getEncryptionKdfSaltBase64() // Obtain the String type key from the server val encryptionSecret = Server.getEncryptionSecret() if (encryptionKdfSaltBase64 == null || encryptionSecret == null) return false // Convert the Base64 encoded salt to byte array (UInt8) val encryptionKdfSalt = Base64.getDecoder().decode(encryptionKdfSaltBase64) // Create an instance of EncryptionConfig val config = EncryptionConfig() // Set the encryption mode to AES_128_GCM2 config.encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2 config.encryptionKey = encryptionSecret // Copy the encryption KDF salt into the configuration System.arraycopy(encryptionKdfSalt, 0, config.encryptionKdfSalt, 0, config.encryptionKdfSalt.size) // Enable encryption using the configuration val result = mRtcEngine.enableEncryption(true, config) // Return true if result is 0 return result == 0 // Success }}
Reference
This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.
Sample projects
Agora provides open-source sample projects for your reference. Download or view the source code for a more detailed example.