URL Validation
To prevent live resources from being stolen, you can configure URL validation to add authentication information to the end of the original ingest or streaming URL. When a streamer starts live streaming or a viewer requests playback, CDN verifies encrypted information in a URL. Only the requests that pass the verification are responded, and other illegitimate requests are rejected.
If you need to customize other validation rules, submit a service ticket to contact Huawei Cloud technical support.
Working Principle
The process is as follows:
- A tenant enables URL validation on the Live console and configures the authentication method, the key, and timeout interval.
- The Live service delivers the configured authentication method, key value, and timeout interval to a CDN node.
- The streamer or viewer requests CDN to push streams or play video through a signed ingest/streaming URL.
- CDN verifies the request based on authentication information carried in the URL. Only requests that pass the verification are allowed.
Notes
- This function is optional and is disabled by default. After this function is enabled, the original URLs cannot be used. New signed URLs must be generated based on rules.
- Use different keys for streaming authentication and playback authentication to enhance security. If a signed URL expires or the signature fails to be authenticated, the livestream fails to be played and the message "403 Forbidden" is returned.
- For persistent connection services such as RTMP and FLV, the server verifies the validation parameters only when receiving a user request. Once verified, the content can be played continuously.
- For HLS services, users keep sending requests that contain the same validation parameters after content is played. Once the validation parameters expire, the server rejects the access request because the verification fails, which will interrupt the playback.
For such services, you need to set a proper authentication expiration time to prevent playback failures. For example, if the estimated HLS playback lasts less than 1 hour each time, you can set the expiration time to 3600 seconds.
Prerequisites
- The ingest domain name and streaming domain name have been added and associated.
- You have configured CNAME records at your domain names' DNS provider.
Enabling URL Validation
- Log in to the Live console.
- In the navigation pane, choose Domains.
- Click Manage in the Operation column of the desired domain name.
- In the navigation pane, choose Basic Settings > Access Control.
- Choose URL Validation.
The URL Validation dialog box is displayed.
- Toggle on the switch and configure related parameters.
Figure 2 Configuring URL validation
Table 1 URL validation parameters Parameter
Description
Method
You can use signing method A, B, C, or D to calculate a signed string.
Signing methods A and B: The Message Digest algorithm 5 (MD5) is used. For details, see Signing Method A and Signing Method B.
Signing method C: A symmetric encryption algorithm is used. For details, see Signing Method C.
Signing method D: The HMAC-SHA256 algorithm is used. For details, see Signing Method D.
NOTE:Signing methods A, B, and C have security risks. Signing method D is more secure and recommended.
Key
Authentication key.
- You can customize a key. A key consists of 32 characters. Only letters and digits are allowed.
- A key can also be automatically generated.
Duration
Timeout interval of URL authentication information, that is, the maximum difference between the request time carried in authentication information and the time when Live receives the request. This parameter is used to check whether an ingest URL or streaming URL expires. The unit is second. The value ranges from 1 minute to 30 days.
NOTE:- For persistent connection services such as RTMP and FLV, the server verifies the validation parameters only when receiving a user request. Once verified, the content can be played continuously.
- For HLS services, users keep sending requests that contain the same validation parameters after content is played. Once the validation parameters expire, the server rejects the access request because the verification fails, which will interrupt the playback.
For such services, you need to set a proper authentication expiration time to prevent playback failures. For example, if the estimated HLS playback lasts less than 1 hour each time, you can set the expiration time to 3600 seconds.
- Click OK.
- Obtain a signed URL in either of the following ways.
- Manually generate a signed URL based on the configured authentication type. For details, see Signing Method A, Signing Method B, Signing Method C, and Signing Method D.
- Use the tool to automatically generate a signed URL. For details, see Signed URL Generation Tool.
- Verify whether URL validation has taken effect.
Use a third-party livestreaming tool to verify the signed ingest URL and streaming URL. If the original ingest URL and streaming URL cannot be used but the signed ingest URL and streaming URL can, URL validation has taken effect.
Signing Method A
A signed string is calculated based on the Key, timestamp, rand (random), uid (set to 0), and URL.
Original URL?auth_key={timestamp}-{rand}-{uid}-{md5hash}
sstring = "{URI}-{Timestamp}-{rand}-{uid}-{Key}" HashValue = md5sum(sstring)
Field |
Description |
---|---|
timestamp |
Start time of a valid request. The value is the total number of seconds that have elapsed since 00:00:00 January 1, 1970. It is a decimal or hexadecimal integer. Example: 1592639100 (June 20, 2020 15:45) |
Duration |
How long a signed URL remains effective. If the validity period is set to 1800s, users can access the streaming URL within 1800s since the time indicated by timestamp. Authentication fails and the URL is inaccessible if users access the streaming URL 1800s later. For example, if the access time is 00:00:00 (GMT+08:00) on June 30, 2020, the URL expires at 00:30:00 (GMT+08:00) on June 30, 2020. |
rand |
Random number. The recommended value is a UUID, which cannot contain hyphens (-). Example: 477b3bbc253f467b8def6711128c7bec |
uid |
User ID. This parameter is not used now. Set it to 0. |
md5hash |
A string of 32 characters calculated using the MD5 algorithm. The string consists of digits (0 to 9) and lowercase letters. sstring = "{URI}-{Timestamp}-{rand}-{uid}-{Key}" HashValue = md5sum(sstring) |
URI |
Path from the domain name to the end in the original URL
|
Key |
Key value set on the console. For details, see URL Validation |
Signed URL example:
- Cloud Stream Live
Generating a signed streaming URL is used as an example.
Original URL: http://test-play.example.com/livetest/huawei1.flv timestamp: 1592639100 Validity period: 1800s Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly rand: 477b3bbc253f467b8def6711128c7bec uid: 0 URI: /livetest/huawei1.flv
Obtain md5hash using the calculation formula.HashValue = md5sum("/livetest/huawei1.flv-1592639100-477b3bbc253f467b8def6711128c7bec-0-GCTbw44s6MPLh4GqgDpnfuFHgy25Enly") = dd1b5ffa00cf26acec0c169ae1cfabea
The signed streaming URL is:
http://test-play.example.com/livetest/huawei1.flv?auth_key=1592639100-477b3bbc253f467b8def6711128c7bec-0-dd1b5ffa00cf26acec0c169ae1cfabea
- LLL
Generating a signed streaming URL is used as an example.
Original URL: webrtc//test-play.example.com/livetest/huawei1 timestamp: 1592639100 Validity period: 1800s Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly rand: 477b3bbc253f467b8def6711128c7bec uid: 0 URI: /livetest/huawei1.sdp
Obtain md5hash using the calculation formula.HashValue = md5sum("/livetest/huawei1.sdp-1592639100-477b3bbc253f467b8def6711128c7bec-0-GCTbw44s6MPLh4GqgDpnfuFHgy25Enly") = dd1b5ffa00cf26acec0c169ae1cfabea
The signed streaming URL is:
webrtc://test-play.example.com/livetest/huawei1?auth_key=1592639100-477b3bbc253f467b8def6711128c7bec-0-dd1b5ffa00cf26acec0c169ae1cfabea
Signing Method B
A signed string is calculated based on the Key, timestamp, and Stream Name.
Original URL?txSecret=md5(Key + Stream Name + txTime)&txTime=hex(timestamp)
Field |
Description |
---|---|
txTime |
Effective time of a streaming URL. The value is a hexadecimal Unix timestamp. If the value of txTime is greater than the requested time, the playback is normal. Otherwise, the playback is rejected. Example: 5eed5888 (that is, 2020.06.20 08:30:00) |
Key |
Key value set on the console. For details, see URL Validation |
txSecret |
Encryption parameter in the URL. The value is obtained by using the MD5 encryption algorithm to encrypt the string consisting of key, Stream Name, and txTime. txSecret = md5 (Key + Stream Name + txTime) |
Duration |
How long a signed URL remains effective. If txTime is set to the current time and the validity period is set to 1249s, the streaming URL expiration time is the current time plus 1249s. |
Signed URL example:
- Cloud Stream Live
Generating a signed streaming URL is used as an example.
Original URL: http://test-play.example.com/livetest/huawei1.flv Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly Stream Name: huawei1 txTime: 5eed5888 Duration: 1249s
Obtain txSecret based on the calculation formula.txSecret = md5(GCTbw44s6MPLh4GqgDpnfuFHgy25Enlyhuawei15eed5888) = 5cdc845362c332a4ec3e09ac5d5571d6
The signed streaming URL is:
http://test-play.example.com/livetest/huawei1.flv?txSecret=5cdc845362c332a4ec3e09ac5d5571d6&txTime=5eed5888
- LLL
Generating a signed streaming URL is used as an example.
Original URL: webrtc://test-play.example.com/livetest/huawei1 Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly Stream Name: huawei1 txTime: 5eed5888 Duration: 1249s
Obtain txSecret based on the calculation formula.txSecret = md5(GCTbw44s6MPLh4GqgDpnfuFHgy25Enlyhuawei15eed5888) = 5cdc845362c332a4ec3e09ac5d5571d6
The signed streaming URL is:
webrtc://test-play.example.com/livetest/huawei1?txSecret=5cdc845362c332a4ec3e09ac5d5571d6&txTime=5eed5888
Signing Method C
A signed string is calculated based on the Key, Timestamp, App Name, Stream Name, and CheckLevel.
Original URL?auth_info={Encrypted string}.{EncodedIV}
- LiveID = <App Name>+"/"+<Stream Name>
- Encrypted string = UrlEncode(Base64(AES128(<Key>,"$"+<Timestamp>+"$"+<LiveID>+"$"+<CheckLevel>)))
- EncodedIV = Hex (IV used for encryption)
Table 4 describes encryption parameters in the algorithm.
Field |
Description |
---|---|
App Name |
Application name, which is the same as the value of App Name in an ingest or streaming URL |
Stream Name |
Stream name, which is the same as the value of Stream Name in an ingest or streaming URL |
Key |
Key value set on the console. For details, see URL Validation |
LiveID |
Livestream ID, which uniquely identifies a livestream. The value consists of App Name and Stream Name. LiveID = <App Name>+"/"+<Stream Name> |
Timestamp |
UTC time when an authentication parameter is generated, in yyyyMMddHHmmss format. This parameter is used to check whether the authentication parameter has expired, that is, whether the absolute value of the difference between Timestamp and the current time is greater than the configured timeout interval. |
CheckLevel |
Check level. The value is 3 or 5.
|
IV |
Cipher block chaining (CBC) depends on the initialization vector (IV). IV consists of 16 random digits and letters and must be 128 bits. In CBC mode, PKCS7 padding is used. |
Signed URL example:
- Cloud Stream Live
Generating a signed streaming URL is used as an example.
Original URL: http://test-play.example.com/livetest/huawei1.flv App Name: livetest Stream Name: huawei1 Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly LiveID: livetest/huawei1 Timestamp: 20190428110000 CheckLevel: 3 IV: yCmE666N3YAq30SN
The encrypted string and EncodedIV are obtained according to the calculation formula.Encrypted string = I90KW7GhxOMwoy5yaeKMStZsOC %2B6WIyqU2kLBYAvcso %3D EncodIV = 79436d453636364e335941713330534e
The signed streaming URL is:http://test-play.example.com/livetest/huawei1.flv?auth_info=I90KW7GhxOMwoy5yaeKMStZsOC%2B6WIyqU2kLBYAvcso%3D.79436d453636364e335941713330534e
- LLL
Generating a signed streaming URL is used as an example.
Original URL: webrtc://test-play.example.com/livetest/huawei1 App Name: livetest Stream Name: huawei1 Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly LiveID: livetest/huawei1 Timestamp: 20190428110000 CheckLevel: 3 IV: yCmE666N3YAq30SN
The encrypted string and EncodedIV are obtained according to the calculation formula.Encrypted string = I90KW7GhxOMwoy5yaeKMStZsOC %2B6WIyqU2kLBYAvcso %3D EncodIV = 79436d453636364e335941713330534e
The signed streaming URL is:webrtc://test-play.example.com/livetest/huawei1?auth_info=I90KW7GhxOMwoy5yaeKMStZsOC%2B6WIyqU2kLBYAvcso%3D.79436d453636364e335941713330534e
Signing Method D
A signed string is calculated based on the Key, timestamp, and Stream Name.
Original URL?hwSecret=hmac_sha256(Key, Stream Name + hwTime)&hwTime=hex(timestamp)
Field |
Description |
---|---|
hwTime |
Effective time of a streaming URL. The value is a hexadecimal Unix timestamp. If the value of hwTime + duration is greater than the requested time, the playback is normal. Otherwise, the playback is rejected. Example: 5eed5888 (that is, 2020.06.20 08:30:00) |
Key |
Key value set on the console. For details, see URL Validation |
hwSecret |
Encryption parameter in the URL. The value is obtained using the HMAC-SHA256 algorithm, with Key and Stream Name + hwTime as parameters. hwSecret = hmac_sha256 (Key, Stream Name + hwTime) |
Duration |
How long a signed URL remains effective. If hwTime is set to the current time and the validity period is set to 1249s, the streaming URL expiration time is the current time plus 1249s. |
Signed URL example:
- Cloud Stream Live
Generating a signed streaming URL is used as an example.
Original URL: http://test-play.example.com/livetest/huawei1.flv Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly Stream Name: huawei1 hwTime: 5eed5888 Duration: 1249s
Obtain hwSecret based on the calculation formula.hwSecret = hmac_sha256(GCTbw44s6MPLh4GqgDpnfuFHgy25Enly, huawei15eed5888) = ce201856a0957413319e883c8ccae13602f01d3d91e21daf5161964cf708a6a8
The signed streaming URL is:
http://test-play.example.com/livetest/huawei1.flv?hwSecret=ce201856a0957413319e883c8ccae13602f01d3d91e21daf5161964cf708a6a8&hwTime=5eed5888
- LLL
Generating a signed streaming URL is used as an example.
Original URL: webrtc://test-play.example.com/livetest/huawei1 Key: GCTbw44s6MPLh4GqgDpnfuFHgy25Enly Stream Name: huawei1 hwTime: 5eed5888 Duration: 1249s
Obtain hwSecret based on the calculation formula.hwSecret = hmac_sha256(GCTbw44s6MPLh4GqgDpnfuFHgy25Enly, huawei15eed5888) = ce201856a0957413319e883c8ccae13602f01d3d91e21daf5161964cf708a6a8
The signed streaming URL is:
webrtc://test-play.example.com/livetest/huawei1?hwSecret=ce201856a0957413319e883c8ccae13602f01d3d91e21daf5161964cf708a6a8&hwTime=5eed5888
Sample Code
The following is the code example for generating a signed string in method C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; public class Main { public static void main(String[] args) { // data="$"+<Timestamp>+"$"+<LiveID>+"$"+<CheckLevel>. For details, see "Signing Method C." String data = "$20190428110000$live/stream01$3"; // A random 16-digit string consisting of digits and letters byte[] ivBytes = "yCmE666N3YAq30SN".getBytes(); // Key value configured on the Live console byte[] key = "GCTbw44s6MPLh4GqgDpnfuFHgy25Enly".getBytes(); String msg = aesCbcEncrypt(data, ivBytes, key); try { System.out.println(URLEncoder.encode(msg, "UTF-8") + "." + bytesToHexString(ivBytes)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } private static String aesCbcEncrypt(String data, byte[] ivBytes, byte[] key) { try { SecretKeySpec sk = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); if (ivBytes != null) { cipher.init(Cipher.ENCRYPT_MODE, sk, new IvParameterSpec(ivBytes)); } else { cipher.init(Cipher.ENCRYPT_MODE, sk); } return Base64.encode(cipher.doFinal(data.getBytes("UTF-8"))); } catch (Exception e) { return null; } } public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if ((src == null) || (src.length <= 0)) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } } |
Base64 is used to encode encrypted strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
public class Base64 { / ** Base64 encoding table */ private static char base64Code[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',}; /** * The construction method is privatized to prevent instantiation. */ private Base64() { super(); } /** * Encode three bytes in a byte array into four visible characters. * @param bytes Byte data to be encoded * @return Base64 character string after encoding */ public static String encode(byte[] bytes) { int a = 0; // Allocate memory based on the actual length after encoding for acceleration. StringBuffer buffer = new StringBuffer(((bytes.length - 1) / 3) << 2 + 4); // Encoding for (int i = 0; i < bytes.length; i++) { a |= (bytes[i] << (16 - i % 3 * 8)) & (0xff << (16 - i % 3 * 8)); if (i % 3 == 2 || i == bytes.length - 1) { buffer.append(Base64.base64Code[(a & 0xfc0000) >>> 18]); buffer.append(Base64.base64Code[(a & 0x3f000) >>> 12]); buffer.append(Base64.base64Code[(a & 0xfc0) >>> 6]); buffer.append(Base64.base64Code[a & 0x3f]); a = 0; } } // For a byte array whose length is not an integral multiple of 3, add 0 before encoding and replace it with = after encoding. // The number of equal signs (=) is the same as the length of the missing data to identify the actual data length. if (bytes.length % 3 > 0) { buffer.setCharAt(buffer.length() - 1, '='); } if (bytes.length % 3 == 1) { buffer.setCharAt(buffer.length() - 2, '='); } return buffer.toString(); } } |
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.