Secure WebM MPEG-DASH streams using Common Encryption in Wowza Streaming Engine

Learn how to configure encryption for WebM MPEG-DASH streams using the Common Encryption (CENC) standard with Wowza Streaming Engine™ media server software. This article assumes you're sending a WebM compatible VP8/VP9 stream directly to Wowza Streaming Engine. You can also use Transcoder to generate the VP8/VP9 stream.

Note: Wowza Streaming Engine 4.4.0 or later is required.

Before you start


You should complete the following tasks:

You should also be familiar with the following concepts:

Encrypt WebM MPEG-DASH streams with CENC


  1. Add the following custom module that injects DRM information into the WebM live stream.
     
    import com.wowza.wms.drm.cenc.*;
    import com.wowza.wms.module.*;
    import com.wowza.wms.stream.livepacketizer.*;
    
    public class ModuleWebMDashEncryption extends ModuleBase
    {
        public static class WebMDashCustomDRMInfo implements ICencDRMInfo
        {
            String systemName = null;
            String systemId = null;
            String url = null;
    
            public WebMDashCustomDRMInfo(String systemName)
            {
                this.systemName = systemName;
            }
    
            @Override
            public void setSystemId(String systemId)
            {
                this.systemId = systemId;
            }
    
            @Override
            public String getSystemId()
            {
                return systemId;
            }
    
            @Override
            public String getURL()
            {
                return url;
            }
    
            @Override
            public void setURL(String url)
            {
                this.url = url;
            }
    
            @Override
            public String getNameSpaces()
            {
                return null;
            }
    
            @Override
            public String getMPEGDashCPSubElements(boolean keyRotation)
            {
                return null;
            }
    
            @Override
            public String getSystemName()
            {
                return this.systemName;
            }
    
            @Override
            public boolean supportsKeyGeneration()
            {
                return false;
            }
    
            @Override
            public byte[] generateKey(byte[] KID)
            {
                return null;
            }
    
            @Override
            public void updateKeyInfo(byte[] KID, byte[] contentKey)
            {
            }
    
            @Override
            public byte[] serialize()
            {
                return null;
            }
    
            @Override
            public void deserialize(byte[] data)
            {
            }
    
            @Override
            public byte[] getPsshData(boolean keyRotation)
            {
                return null;
            }
    
            @Override
            public void setPsshData(byte[] psshData)
            {
            }
    
            @Override
            public boolean isComplete()
            {
                return true;
            }
        }
    
        public void onHTTPMPEGDashEncryptionKeyLiveChunk(ILiveStreamPacketizer liveStreamPacketizer, String streamName, CencInfo cencInfo, long chunkId)
        {
            if (cencInfo.getKID() != null && cencInfo.getEncKeyString() != null)
            {
                try
                {
                    String idStr = "test";
                    String url = "empty";
                    String systemId = "12345678-1234-1234-1234-123456789012";
    
                    WebMDashCustomDRMInfo drmInfo = new WebMDashCustomDRMInfo(idStr);
    
                    drmInfo.setURL(url);
                    drmInfo.setSystemId(systemId);
    
                    getLogger().info("ModuleWebMDashEncryption.onHTTPMPEGDashEncryptionKeyLiveChunk["+streamName+"]: Add DRM: "+idStr+":"+systemId);
                    cencInfo.addDRM(idStr+":"+systemId, drmInfo);
                    cencInfo.setKeyRotationType(CencInfo.KEY_ROTATION_TYPE_NONE);
                    cencInfo.setPSSHVersion(CencInfo.PSSH_VERSION_1);
                }
                catch (Exception e)
                {
                    getLogger().error("ModuleWebMDashEncryption.onHTTPMPEGDashEncryptionKeyLiveChunk["+streamName+"]: ", e);
                }
            }
        }
    }
  2. Add a key file named [install-dir]/keys/myStream.key to encrypt the live stream.
     
    mpegdashstreaming-cenc-key-id: 12345DCF-7F93-4B8E-85C7-F908840DA059
    mpegdashstreaming-cenc-content-key: Hh8gISIjJCUmJx4fICEiIw==
    mpegdashstreaming-cenc-algorithm: AESCTR
    mpegdashstreaming-cenc-pssh-version: 1
  3. Send a WebM-compatible live stream named myStream to your live application in Wowza Streaming Engine. You should see a log statement similar to the following that indicates the stream is being encrypted:

    MPEGDashWriterHandler.createChunkWebM[myApplication/_definst_/myStream]: WebM encryption: kid:12345dcf7f934b8e85c7f908840da059
     
  4. Play the stream using a player that supports WebM MPEG-DASH encryption like Google Shaka Player. Refer to the documentation for your player for information about configuring playback of encrypted WebM MPEG-DASH streams.

More resources