This document describes how to integrate SFrame (Secure Frame) encryption into WebRTC applications. SFrame provides end-to-end media security that works even when media flows through untrusted servers or intermediaries.
SFrame encryption can be applied at two different levels:
- Per-frame: Encrypts complete video/audio frames before packetization
- Per-packet: Encrypts individual RTP packets after packetization
Both approaches offer strong security guarantees, with per-packet providing finer granularity and per-frame offering better performance characteristics.
// Available modes for SFrame encryption
const SFrameMode = {
"per-frame", // Encrypt at frame level
"per-packet" // Encrypt at packet level
};Assumption; JS API usage after recent W3C meeting.
// Create peer connection
const peerConnection = new RTCPeerConnection();
// Add video track
const videoTransceiver = peerConnection.addTransceiver("video", {
direction: "sendonly"
});
// Configure SFrame options
const sframeOptions = {
mode: "per-packet" // or "per-frame"
};
// Apply SFrame transform
videoTransceiver.sender.transform = new SFrameTransform(sframeOptions);- SFrame can be configured independently for each media track
- Both sender and receiver need compatible SFrame configurations
- The API maintains backward compatibility with non-SFrame endpoints
The SFrame API design provides transformer injection at the sender and receiver level, following the JavaScript API pattern:
videoTransceiver.sender.transform = new SFrameTransform(sframeOptions);Following this design proposal principles, the SetSFrameTransformer method will be exposed through the RTPSenderInterface and RTPReceiverInterface to provide this granular control and maintain consistency with the JavaScript API surface.
Defines the granularity at which SFrame encryption is applied to media data.
api/sframe/sframe_options.h
enum SFrameMode {
kPerFrame, // Frame-level encryption
kPerPacket // Packet-level encryption
};Configuration structure that defines SFrame encryption behavior.
api/sframe/sframe_options.h
struct SFrameOptions {
SFrameMode mode;
// Additional options can be added here in the future
};The SFrameTransformerHost interface provides a unified way to inject SFrame transformers into WebRTC components. This interface will be implemented by RTP senders and receivers to enable SFrame encryption and decryption capabilities.
api/sframe/sframe_transformer_interface.h
class SFrameTransformerHost {
public:
virtual ~SFrameTransformerHost() = default;
// Configures SFrame transformer with specified options
virtual void SetSFrameTransformer(
scoped_refptr<SFrameTransformerInterface> sframe_transformer,
SFrameOptions options) = 0;
// Retrieves currently configured transformer (may return nullptr)
virtual scoped_refptr<SFrameTransformerInterface> GetSFrameTransformer() = 0;
};The main interface for implementing SFrame encryption/decryption:
api/sframe/sframe_transformer_interface.h
class SFrameTransformerInterface : public RefCountInterface {
public:
virtual ~SFrameTransformerInterface() = default;
// Configure encryption keys
virtual void SetEncryptionKey(/*Keys*/) = 0;
// Transform media data (encrypt or decrypt)
virtual void Transform(CopyOnWriteBuffer buffer) = 0;
};RTP interfaces inherit from SFrameTransformerHost to support SFrame injection:
api/rtp_sender_interface.h
class RtpSenderInterface : public SFrameTransformerHost {
public:
// Default implementation, actuall implementation will be done by classes inheriting RtpSenderInterface
void SetSFrameTransformer(
scoped_refptr<SFrameTransformerInterface> sframe_transformer,
SFrameOptions options) {};
};api/rtp_receiver_interface.h
class RtpReceiverInterface : public SFrameTransformerHost {
public:
// Default implementation, actuall implementation will be done by classes inheriting RtpReceiverInterface
void SetSFrameTransformer(
scoped_refptr<SFrameTransformerInterface> sframe_transformer,
SFrameOptions options) {};
};WebRTC will provide a built-in SFrame implementation using the Cisco SFrame library.
Decision whether SFrameTransformer should perform encryption or decryption will be defined by the SFrameRole parameter.
api/sframe/sframe_transformer.h
enum SFrameRole {
Encrypt,
Decrypt
};api/sframe/sframe_transformer.h
enum SFrameCipherSuite {
AES_128_CTR_HMAC_SHA256_8, // AES-128-CTR with 8-byte auth tag
AES_128_CTR_HMAC_SHA256_64, // AES-128-CTR with 64-byte auth tag
AES_128_CTR_HMAC_SHA256_32, // AES-128-CTR with 32-byte auth tag
AES_128_GCM_SHA256_128, // AES-128-GCM with 128-bit auth tag
AES_256_GCM_SHA512_128 // AES-256-GCM with 128-bit auth tag
};RTCSFrameTransformer will leverage Cisco SFrame library to implement SFrame encryption/decryption.
modules/sframe/rtc_sframe_transformer.h
class RTCSFrameTransformer : public SFrameTransformerInterface {
public:
explicit RTCSFrameTransformer(SFrameRole role, SFrameCipherSuite cipher_suite);
void SetEncryptionKey(std::string key) override {
// Update keys in SFrame Context
}
// Transform media data (encrypt or decrypt)
void Transform(CopyOnWriteBuffer buffer) override {
// role == SFrameRole::Encrypt ? Encrypt(buffer) : Decrypt(buffer);
}
private:
void Encrypt(CopyOnWriteBuffer buffer);
void Decrypt(CopyOnWriteBuffer buffer);
};RTCSFrameTransformer creation will be possible throught the factory method exposed from the libwebrtc API.
api/sframe/sframe_transformer_factory.h
scoped_refptr<SFrameTransformerInterface> CreateSFrameTransformer(SFrameRole role, SFrameCipherSuite cipher_suite);scoped_refptr<SFrameTransformerInterface> CreateSFrameTransformer(SFrameRole role, SFrameCipherSuite cipher_suite)
{
return make_ref_counted<RTCSFrameTransformer>(role, cipher_suite);
}// Create peer connection
RTCPeerConnection pc;
// Add video transceiver
auto transceiver = pc.AddTransceiver("video");
// Create SFrame transformer for encryption
auto sframe_transformer = CreateSFrameTransformer(SFrameRole::kEncrypt,
SFrameCipherSuite::AES_128_GCM_SHA256_128);
// Configure for per-packet encryption
SFrameOptions options;
options.mode = SFrameMode::kPerPacket;
// Apply to sender
transceiver->sender()->SetSFrameTransformer(sframe_transformer, options);
sframe_transformer->SetEncryptionKey("XYZ");- SFrame Protocol - The underlying SFrame specification
- WebRTC API - W3C WebRTC specification
- Cisco SFrame Library - Reference implementation
- RTP SFrame
- Encoded Transform
Open Questions:
- Should we use
CopyOnWriteBufferor ratherArraView<uint8_t>for transformation - Do we need on libwebrtc level to have single "Transformer" interface.
Maybe it's fine to split it into encrypter and decrypter, and let browser level code decide which to create.
Instead of having an generic
RTCSFrameTransformerwithSFrameRolein the parameter, we could create a separate objects for handling encryption and decryption.
class RTCSFrameEncryptor : public SFrameTransformerInterface {
public:
explicit RTCSFrameEncryptor(SFrameCipherSuite cipher_suite);
// Implementation handles the crypto details
};
class RTCSFrameDecryptor : public SFrameTransformerInterface {
public:
explicit RTCSFrameDecryptor(SFrameCipherSuite cipher_suite);
// Implementation handles the crypto details
};