Secure channel encryption

Updated

Add Agora built-in media stream encryption to your app.

Media stream encryption ensures that only authorized users in a channel see and hear each other. Encryption prevents potential eavesdroppers from accessing sensitive and private information shared in a channel. IoT SDK provides built-in encryption methods that you can use to guarantee data confidentiality during transmission, when required.

This page shows you how to integrate media stream encryption into your app using IoT SDK.

Understand the tech

To ensure secure communication, your app uses an SSL key and a salt to encrypt and decrypt data in the channel. You use the key and salt to create an encryption configuration. Agora SDRTN® uses the encryption configuration to encrypt a stream and sends it to remote users. When a remote user receives an encrypted media stream, the remote app decrypts it using the same salt and key.

The following figure shows the call flow for media stream encryption:

All users in a channel must use the same encryption configuration. You set this up when you initiate the Agora Engine and enable encryption before joining a channel. If you don’t have the correct configuration, you cannot decrypt channel content. Best practice is to have your authentication system generate a new key and salt regularly.

IoT SDK supports the following encryption modes:

  • SM4-128-ECB
  • AES_128_ECB
  • AES_128_XTS
  • AES_256_XTS
  • AES-128-GCM
  • AES-256-GCM
  • AES-128-GCM2 (recommended)
  • AES-256-GCM2 (recommended)

Compared to other encryption modes, GCM2 encryption uses a more secure key derivation function and supports salt. If you choose another encryption mode, you only need to set the encryption mode and key.

Prerequisites

To follow this procedure you must have:

Project setup

To encrypt media streams in your app, you need to:

  • Open the SDK quickstart IoT SDK project you created previously.

  • Set up OpenSSL on your development device.

Implement Agora media stream encryption

To implement media stream encryption, do the following:

  1. Add variables to hold the encryption mode, encryption key, and salt

    Open <project-root>/agora_rtsa_sdk/example/hello_rtsa/hello_rtsa.c in your development environment and add the following declarations to main() after char params[512];:

    char * encryptionMode; // depends on your choice of an encryption method
    const char * encryptionKey = "<32-byte key generated through OpenSSL>";
    const char * encryptionSaltBase64 = "<Base64-encoded, salt generated through OpenSSL>";
  2. Enable encryption

    Set enable_aut_encryption to true in the channel options. Add the following line in main() after channel_options.auto_subscribe_video = true:

    channel_options.enable_aut_encryption = true;
  3. Set encryption parameters

    You specify the media stream encryption mode and the related parameters in JSON format by calling agora_rtc_set_params. Depending on your choice of an encryption mode, add one of the following pieces of code before agora_rtc_join_channel function in main():

    • SM4-128-ECB encryption

      // set the encryption mode
      encryptionMode = "SM4-128-ECB";
      
      // set encryption parameters
      memset(params, '\0', sizeof(params));
      snprintf(params, sizeof(params), "{\"rtc.encryption\": {\"enable\": true,\"mode\": \"%s\", \"master_key\": \"%s\" }}", encryptionMode, encryptionKey);
      rval = agora_rtc_set_params(params);
      if (rval != 0) {
          LOGE("set encryption key failed, reason: %s", agora_rtc_err_2_str(rval));
          return -1;
      }
    • AES-128-GCM encryption

      // set the encryption mode
      encryptionMode = "AES-128-GCM";
      
      // set encryption parameters
      memset(params, '\0', sizeof(params));
      snprintf(params, sizeof(params), "{\"rtc.encryption\": {\"enable\": true,\"mode\": \"%s\", \"master_key\": \"%s\" }}", encryptionMode, encryptionKey);
      rval = agora_rtc_set_params(params);
      if (rval != 0) {
          LOGE("set encryption key failed, reason: %s", agora_rtc_err_2_str(rval));
          return -1;
      }
    • AES-128-GCM2 encryption

      // set the encryption mode
      encryptionMode = "AES-128-GCM2";
      
      // set encryption parameters
      memset(params, '\0', sizeof(params));
      snprintf(params, sizeof(params), "{\"rtc.encryption\": {\"enable\": true,\"mode\": \"%s\", \"master_key\": \"%s\", \"salt_type\": \"BASE64\"}}" }}", encryptionMode, encryptionKey, encryptionSaltBase64);
      rval = agora_rtc_set_params(params);
      if (rval != 0) {
          LOGE("set encryption key failed, reason: %s", agora_rtc_err_2_str(rval));
          return -1;
      }
  4. Disable encryption

    To disable encryption, use the following code:

    // Disable built-in encryption
    agora_rtc_set_params("{\"rtc.encryption\": {\"enable\": false}}");

Test your implementation

To ensure that you have implemented Agora media stream encryption in your app:

  1. Add the 32-byte key to your app:

    1. Run the following command in a terminal window:

      openssl rand -hex 32
    2. Paste the key string returned into the encryptionKey variable.

  2. Add the 64-byte salt to your app:

    1. Run the following command in your terminal window:

      openssl rand -base64 32
    2. Paste the salt string returned into the encryptionSaltBase64 variable.

  3. Generate a temporary token in Agora Console.

  4. Compile the sample project by executing the following commands in a terminal window:

    cd <project-root>/agora_rtsa_sdk/example
    
    ./build-x86_64.sh
  5. Run the sample app by executing the following commands:

    cd out/x86_64
    
    ./hello_rtsa --app-id <your-app-id> --channel-id <your-channel-name> --token <authentication-token>

    Make sure you insert your app ID, channel ID, and token from Agora Console in to the command.

    On launch, the app joins a channel and shows output similar to the following:

    [INF] Welcome to RTSA SDK v1.9.0
    [INF] File parser found: h264
    [INF] File parser found: pcm
    [INF] [conn-1] Join the channel demo successfully, uid 2645490531 elapsed 602 ms
    [INF] [conn-1] Bandwidth change detected. Please adjust encoder bitrate to 499 kbps
  6. Test with an unauthorized user

    In your browser, navigate to the Agora web demo and update App ID, Channel, and Token with the values for your temporary token, then click Join. You see the local user video in your browser.

    In the terminal, your compiled app shows a decryption error as the web demo does not have the SSL key and salt for stream encryption and decryption.

    [INF] [conn-1] Remote user "3674330576" has joined the channel, elapsed 6784 ms
    [WRN] Error 120 is captured. Error msg "audio:decrypt error"
    [WRN] Error 120 is captured. Error msg "video:not set"
  7. Test with an authorized user

    Open two Linux terminals. Navigate to <project-root>/agora_rtsa_sdk/example/out/x86_64 and execute the following command to launch the app from both terminals.

    ./hello_rtsa --app-id <your-app-id> --channel-id <your-channel-name> --token <authentication-token>

    You see that both clients join the same channel and successfully exchange data as they are using the same SSL key and salt.

    Terminal output for User 1:

    [DBG] [conn-1] on_audio_data, uid 3534962825 sent_ts 28149 data_type 100, len 640
    [DBG] [conn-1] on_video_data: uid 3534962825 sent_ts 28150 data_type 2 frame_type 4 stream_type 0 len 618
    [DBG] [conn-1] on_audio_data, uid 3534962825 sent_ts 28169 data_type 100, len 640

    Terminal output for User 2:

    [DBG] [conn-1] on_video_data: uid 2689257578 sent_ts 1494 data_type 2 frame_type 4 stream_type 0 len 160
    [DBG] [conn-1] on_video_data: uid 2689257578 sent_ts 1534 data_type 2 frame_type 4 stream_type 0 len 189
    [DBG] [conn-1] on_audio_data, uid 2689257578 sent_ts 1541 data_type 100, len 640

Communication between your test devices is now end-to-end encrypted. This prevents data from being read or secretly modified by anyone other than the true sender and recipient.

Reference

This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

API reference