End-to-End Encryption API

Use the End-to-End Encryption API to encrypt media being sent through a media server from your application.

Important: In OpenTok.js 2.27.0+, end-to-end encryption will not work when connecting to clients using an earlier version of OpenTok.js. When you upgrade your app to use OpenTok.js 2.27.0+, make sure all clients are using OpenTok.js 2.27.0+ if the app uses end-to-end encryption.

Overview

End-to-end encryption (or E2EE) allows application developers to encrypt media in routed sessions from client to client. For relayed sessions, media is already encrypted client-to-client, through WebRTC protocols. This feature adds an encryption layer by encrypting the media payload at the client so that it will remain encrypted through the Media Router that routes media to other clients (in routed sessions). You enable end-to-end encryption when you create a session.

End-to-end encryption is supported in web apps on Chromium-based (Chrome, Opera, Samsung Internet and Edge) and WebKit-based browsers, for example Safari on macOS/iOS and Chrome on iOS. End-to-end encryption is not supported in web apps on Firefox.

WebKit-based browser support is only available from version OpenTok.js 2.30.0 onwards.

End-to-end encryption is supported in each of the native client SDKs (for Android, iOS, Windows, Linux, and macOS).

You set the encryption secret in a web application using OpenTok.js. You must set encryption secrets in the web client when you initialize a session, and you can change encryption secrets on the fly once the session has connected. The encryption secret is a non-empty string. All users must use the same secret to receive intelligible media. The encryption secret is key material for generating a cryptographic key that is used to encrypt and decrypt media. Specifically, the encryption secret generates an AES-256 encryption key using an AES-CTR algorithm with a 256-bit key.

Please note that the Media Router does not have access to unencrypted media when using end-to-end encryption.

So, features that require media decoding --- such as archiving, live streaming broadcasts, experience composer, audio connector, and SIP interconnect --- are unsupported in end-to-end encrypted sessions. .

End-to-End encryption per codec support across endpoints

Codec/End-point Chrome Android Chrome iOS Chrome Firefox Safari Edge iOS SDK Android SDK Windows SDK macOS SDK Linux SDK
VP8
H.264
VP9

Adding end-to-end encryption for your account

End-to-end encryption is available as an add-on feature. You can enable it on your Video account page.

Enabling encryption using the REST API

You enable end-to-end encryption when you create a session using the REST API. Set the e2ee property to true.

See session creation.

Note: Before enabling end-to-end encryption for a session, you must enable it for your Video account.

The following Node.js example creates an end-to-end encryption enabled session:

const Vonage = require('@vonage/server-sdk');

const vonage = new Vonage({
    applicationId: APP_ID,
    privateKey: PRIVATE_KEY_PATH
});

try {
    const session = await vonage.video.createSession({
         mediaMode: "routed",
         e2ee: true, // This will enable end-to-end encryption
    });
} catch(error) {
    console.error("Error creating session: ", error);
}

Implementations

Setting the encryption secret

End-to-end encrypted sessions are created using server APIs (see Enabling encryption using the REST API). To have a React Native client join an end-to-end encrypted session, set the encryptionSecret prop of the OTSession component:

<OTSession
  applicationId="api-key"
  sessionId="session-id"
  token="token"
  encryptionSecret="initial-encryption-secret"
>
  <OTPublisher />
  <OTSubscriber />
</OTSession>

A valid secret is a string between 8 and 256 characters.

You can change the secret by setting the encryptionSecret prop to a property of the React state and changing its value:

<OTSession
  applicationId="api-key"
  sessionId="session-id"
  token="token"
  encryptionSecret={this.state.encryptionSecret}>
>
  <OTPublisher />
  <OTSubscriber />
</OTSession>

Events and errors

Events and errors are essential to managing the behavior of user-driven encryption behavior. End-to-end encryption uses the shared secret model: everyone in the session is expected to use the same secret to encrypt their media and decrypt everyone else's.

The OTSubscriber error() event handler callback is invoked when the subscriber is unable to decode a stream's media due to a mismatched (or unset) encryption secret:

<OTSubscriber
eventHandlers={{
    error: event => {
    // Show UI notification.
    },
}}
>

The OTSession error() event handler callback is invoked if the client tries to connect to an end-to-end encrypted session that was initialized with an invalid encryption secret (or without specifying an encryption secret). A valid secret is a string between 8 and 256 characters. For the best user experience, the application should catch an invalid user supplied secret before setting the OTSession encryptionSecret prop. In the following example, a session is initialized with an empty (and thus invalid) secret, which causes an error when attempting to connect:

<OTSession
  applicationId="api-key"
  sessionId="session-id"
  token="token"
  encryptionSecret=""
  eventHanders={{
    error: event => {
      // An error event is dispatched if you set an invalid encryption secret
    }
  }}
>
  <OTPublisher />
  <OTSubscriber />
</OTSession>