# Secure HLS streams with AES-128 external encryption using the Wowza Video REST API The Wowza Video™ service allows you to secure HLS streams using the external method of AES-128 encryption. When you use the external method of AES-128 encryption, encryption keys are delivered to devices from an external URL. This article describes how to use the Wowza Video REST API to configure AES-128 encryption for an HLS stream. ## Before you start You should complete the following tasks: - Create a **live stream** or a **transcoder**. You'll need the resulting `live_stream_id` or `transcoder_id` to configure AES-128 encryption. View our [connect a source](/docs/wowza-video/guides/video-source/encoder-camera/connect-an-ip-camera) topics to learn how to create a live stream or transcoder for RTMP, RTSP, IP camera, SRT encoder, UDP encoder, WebRTC, and Wowza Streaming Engine. ## 1. Configure AES-128 encryption Configure the following transcoder properties to enable AES encryption. You'll need to first configure the `aes128Host` and then the `aes128Secret`. ### Configure the aes128Host You can use the following sample request, making sure to: - Set `key` to `aes128Host`. - Set `section` to `cupertino`. - Set `value` to the URL that devices will use to fetch the key to decrypt the stream. - Set `id` to the `live_stream_id` or `transcoder_id`. #### Sample request Endpoint Reference ``` curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${WV_JWT}" \ -d '{ "property": { "key": "aes128Host", "section": "cupertino", "value": "https://[server-url].com/aes128/key.bin" } }' "${WV_HOST}/api/${WV_VERSION}/transcoders/[id]/properties" ``` #### Sample response ``` { "property": { "key": "aes128Host", "section": "cupertino", "value": "https://[server-url].com/aes128/key.bin" } } ``` ### Configure the aes128Secret You can use the following sample request, making sure to: - Set `key` to `aes128Secret`. - Set `section` to `cupertino`. - Set `value` to the 16-byte key that will be used to decrypt the stream. The key must be 32 characters in length and can only contain hex characters (a-f, A-F, 0-9). The key must match the key returned by the `aes128Host`. - Set `id` to the `live_stream_id` or `transcoder_id`. #### Sample request Endpoint Reference ``` curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${WV_JWT}" \ -d '{ "property": { "key": "aes128Secret", "section": "cupertino", "value": "AaBbCc123456789DdEeFf123456789aa" } }' "${WV_HOST}/api/${WV_VERSION}/transcoders/[id]/properties" ``` #### Sample response ``` { "property": { "key": "aes128Secret", "section": "cupertino", "value": "AaBbCc123456789DdEeFf123456789aa" } } ``` Info If you have started a transcoder at any point before updating its transcoder property, you must reset the transcoder for the property to take effect. This step isn’t necessary if you haven’t started the transcoder at all. ## 2. Reset the transcoder Endpoint Reference ``` curl -X PUT \ -H "Authorization: Bearer ${WV_JWT}" \ "${WV_HOST}/api/${WV_VERSION}/transcoders/[transcoder_id]/reset" ``` ## Examples The following examples show how to use popular web application technologies such as **ASP.NET**, **JSP**, and **PHP** to send the key data. Each example includes a Boolean `isValid` value that defaults to `true`. You can modify the examples to provide your own security tests to validate that users can access the content. If users shouldn't be allowed to access the content, you can block them from receiving the decryption key by setting `isValid` to `false`. If the request for the key returns a status of `403`, then the device won't be able to decrypt and play the stream. If the key is returned, then the stream will be decrypted and played. Require HTTPS access to this key to ensure that it isn't sent over an unsecured connection on the Internet. The key being sent in these examples is `DE51A7254739C0EDF1DCE13BBB308FF0`. You should substitute this value with a different 16-byte key. The key should match the key value specified for the `aes128Secret` transcoder property. Info These examples are provided as-is with no expressed warranty. You can modify or distribute them without restriction. #### ASP.NET example ``` <%@ Page Language="C#" %> <% Boolean isValid = true; if (!isValid) { Response.Status = "403 Forbidden"; } else { Response.AddHeader("Content-Type", "binary/octet-stream"); Response.AddHeader("Pragma", "nocache"); String keyStr = "DE51A7254739C0EDF1DCE13BBB308FF0"; int len = keyStr.Length/2; byte[] keyBuffer = new byte[len]; for (int i=0;i ``` #### JSP example ``` <%@ page import="java.util.*,java.io.*" %> <% boolean isValid = true; if (!isValid) { response.setStatus( 403 ); } else { response.setHeader("Content-Type", "binary/octet-stream"); response.setHeader("Pragma", "no-cache"); String keyStr = "DE51A7254739C0EDF1DCE13BBB308FF0"; int len = keyStr.length()/2; byte[] keyBuffer = new byte[len]; for (int i=0;i ``` ### PHP example ``` ``` ## Next Steps - [Test AES encryption for HLS streams from the Wowza Video REST API](/docs/wowza-video/guides/stream-security/test-aes-encryption-for-hls-streams)