Cisco Internet Streamer CDS 2.5 Software Configuration Guide
URL Signing and Validation
Downloads: This chapterpdf (PDF - 273.0KB) The complete bookPDF (PDF - 4.65MB) | Feedback

URL Signing and Validation

Table Of Contents

URL Signing and Validation

Introduction

URL Signing Components

Supported Protocols and Media

Configuring the CDS for URL Signing

Configuring URL Signing in Release 2.5.1 and Release 2.5.3

Configuring URL Signing in Release 2.5.7 and Release 2.5.9

Configuring Service Rules for URL Signing

Configuring URL Signing on Each SE

URL Signing and Validating

URL Signing Script for Symmetric Keys

URL Signing Version

Example of a Python URL Signing Script

Running a Python URL Signing Script

URL Signing and Flash Media Streaming

Importance of Device Synchronization

Understanding the Signing Procedure

Public Key URL Signing for Asymmetric Keys

How Public Key URL Signing Works with CDS

URL Signing C Program


URL Signing and Validation


This appendix describes the URL signing and validation method for the Cisco Internet Streamer CDS. This appendix contains the following sections:

Introduction

Configuring the CDS for URL Signing

URL Signing and Validating

Introduction

The Cisco Internet Streamer CDS accepts and fulfills requests for video content from client devices in the form of content URLs. Content and service providers, to protect their copyright and fulfill their licensing obligations, often need to restrict access to content and limit viewing times. Basic authentication and authorization at the portal (for example, username and passwords) can help achieve this objective by restricting content access to authorized users. However, because URLs are inherently open, users (once authenticated at the portal) could potentially share these content URLs with other possibly unauthorized users, or continue to access the content beyond the allotted time.

Cisco Internet Streamer CDS provides the infrastructure to sign and validate content URLs, restricting access to some users and limiting viewing times.

URL Signing Components

One of the easiest ways to restrict content access to a particular user is to embed, within the content URL, the client IP address of the user for whom the content access was authorized. Similarly, to ensure that the content expires after a predetermined time, an expiry timestamp could be embedded. These values can then be validated against the actual client sending the request and the current time at the Service Engine serving the request. If either of the two validations fail, the request is rejected.


Note You can exclude the checks for the client IP address and the content expiry by configuring a service rule on each SE. For more information, see the "Configuring URL Signing" section.


However, because any of these strings in the URL could potentially be edited manually and circumvented by any knowledgeable user, it is important to generate and attach a signature to the URL. This can be achieved by attaching a keyed hash to the URL, using a secret key shared only between the signer (the portal) and the validating component (CDS).

CDS has incorporated an open and well-documented signing mechanism that uses standard hashing schemes. The URL signing mechanism offers the flexibility to either use the provided signing script, or you can develop a signing application in the platform or language of your choice, as long as it adheres to the specified format.

For signing and validation of the URL, the CDS relies on a set of one or more secret keys shared between the portal and the devices within the CDS.


Note Sometimes media players append the port number to the URL. In this case, the SE removes the port number from the URL before validating the signature.


Supported Protocols and Media

The URL signing and validation is supported across all CDS protocol engines: Windows Media Engine, Movie Streamer Engine, Flash Media Streaming Engine, and Web Engine.


Note In Release 2.5.7 and later releases, URL validation for Web Engine HTTP requests is configured by using the delivery service Service Rule Config. For more information, see the "Service Rule File Config" section.


Configuring the CDS for URL Signing

The URL signing and validation configuration requirements differ depending on the Cisco Internet Streamer CDS software release. Figure H-1 describes the URL signing and validation workflow.

Figure H-1 URL Signing and Validation Configuration Workflow

The CDS URL signing infrastructure supports multiple keys. Different pieces of content, with different URLs, can be signed by different keys. Keys are stored as a key matrix and identified (indexed) by a key ID owner and a key ID number.

Configuring URL Signing in Release 2.5.1 and Release 2.5.3

To enable validation of URLs in the CDS running Release 2.5.1 or Release 2.5.3 for all protocol engines, the following tasks must be completed on all participating Service Engines:

Configure URL Signing

Enable service rules processing

Configure rules to validate URLs matching the above pattern-lists

Configure pattern-lists to match URLs, domain names, or both

For information on configuring URL Signing, see the "Configuring URL Signing" section. For information on enabling service rules processing and configuring service rules on each Service Engine, see the "Configuring Service Rules" section.

Configuring URL Signing in Release 2.5.7 and Release 2.5.9

In Release 2.5.7 and Release 2.5.9, configuring the CDS for URL signing and validation differs depending on the protocol engine.

Configuring URL Signing for All Protocol Engines, Except the Web Engine

To enable validation of URLs in the CDS running Release 2.5.7 or Release 2.5.9, for the Windows Media Streaming Engine, Movie Streamer Engine, or the Flash Media Streaming Engine, the following tasks must be completed on all participating Service Engines:

Configure URL Signing

Enable service rules processing

Configure rules to validate URLs matching the below pattern-lists

Configure pattern-lists to match URLs, domain names, or both

For information on configuring URL Signing, see the "Configuring URL Signing" section. For information on enabling service rules processing and configuring service rules on each Service Engine, see the "Configuring Service Rules" section.

Configuring URL Signing for the Web Engine

To enable validation of URLs in the CDS running Release 2.5.7 or Release 2.5.9, for the Web Engine, the following tasks must be completed:

Configure URL Signing on all participating Service Engines

Enable service rules processing on all participating Service Engines

Enable Authorization Service on all participating Service Engines (enabled by default)

Create a Service Rule XML file and upload it to each participating delivery service. The Service Rule XML file must have the following:

Rules to validate URLs matching the below pattern-lists

Pattern-lists to match URLs, domain names, or both

For information on configuring URL Signing, see the "Configuring URL Signing" section. For information on creating the Service Rule XML file, see the "Creating Service Rule Files." For information on uploading the Service Rule XML file to the delivery service, see the "Service Rule File Config" section.

Configuring Service Rules for URL Signing

Service rules must be enabled on all the Service Engines participating in URL validation. Configure the service rules to validate the URL based on Service Routing Domain Name and the Origin Server FQDN, or the url-regex.

Whether you use the CLI, the CDSM GUI, or the Service Rule XML file (Web Engine only in Release 2.5.7 or later) to configure the service rule; at least one service rule for validating the URL must exist in one of the following forms:

Using the CLI, each SE should contain at least one rule of the form:

rule action validate-url-signature pattern-list <n> protocol <protocol>
 
   

where pattern-list <n> will match the requests coming in from the clients.

Following is another example of using the CLI to configure the SE:

rule pattern-list 1 domain cds.cisco.com 
rule action validate-url-signature error-redirect-url http://foobar.com pattern-list 1 
protocol rtsp
rule enable
 
   

In the CDSM GUI, choose Devices > Service Control > Service Rules, and click the Create New icon. From the Rule Type drop-down list, select pattern-list. Enter parameters to match requests from the client. As an example, entering:

1 url-regex live
 
   

would cause pattern list 1 to match any request with the string "live" in the URL.

Click Create New again and this time from the Rule Type drop-down list, select validate-url-signature. As an example, entering:

error-redirect-url <error_url> pattern-list <n> protocol rtmp
 
   

where the client is redirected to <error_url> when the rule check fails, and pattern list <n> is the one you just created.

In the Service Rule XML file, an example of the service rule for validating the URL follows:

<Rule_Validate matchGroup = "1"  protocol = "http" error-redirect-url = 
"http://wwwin.cisco.com" exclude-validation = "all" />
 
   

where the pattern list 1 will match HTTP requests coming in from the clients, if they do not match the client is redirected to the error URL, and the client IP address and the expiry time are excluded from the validation.

Configuring URL Signing on Each SE

Configure the URL signature with Key-Owner, Key-Number, and Key is you are using Symmetric Key signing. Make sure this database of keys is given to both the portal server and Origin Server. If you are using Asymmetric Key signing, see the "Public Key URL Signing for Asymmetric Keys" section.

Whether you use the CDSM GUI or the CLI, you must configure URL Signing on each SE in one of the following ways:

In the CDSM GUI, choose Devices > Service Control > URL Signing, then click the Create New icon. From the Cryptographic Algorithm drop-down list, select Symmetric Key or Asymmetric Key.

If you selected Symmetric Key, enter the Key ID Owner, Key ID Number, and Key. It is important that these values match those of the portal.

If you selected Asymmetric Key, enter the Key ID Owner, Key ID Number, the location of the Public Key file, and if used, the Private Key location and the Symmetric Key (AES encryption). For more information about the public key signing, see the "Public Key URL Signing for Asymmetric Keys" section.

In the CLI, each SE must have a URL signing key enabled that matches the one in the portal's configuration file.

Adding keys:

url-signature key-id-owner 1 key-id-number 2 key "foobar"
 
   

Viewing keys:

# show url-signature
 
   

URL Signing and Validating

The Internet Streamer CDS software supports symmetric key URL signing and asymmetric key URL signing (also known as public key URL signing. Symmetric key signing uses the same key to sign and validate the URL. Asymmetric keys always have a key pair made up of a public key and private key. The private key is used for signing and the public key is used for validation.

Symmetric keys, which means the same key is used for both signature generation and validation, are known by both parties. There is the signature generator, usually the portal, and the signature validator, which is the Internet Streamer CDS. Symmetric keys use either the MD5 or the SHA1 hash algorithm. They must remain secret at both ends, because the same key is used for both signing and validation. The key should be changed frequently.

Asymmetric keys, which means a private key is used for signing and a public key is used for validation, need to secure only the private key end. Also, the public/private key pair can be used for a longer duration without having to change them.

This section contains the following topics:

URL Signing Script for Symmetric Keys

Public Key URL Signing for Asymmetric Keys

URL Signing Script for Symmetric Keys

At the portal, URLs can be signed for a particular user (client IP address) and expiry time using a URL signing script. The URL signing script example included in this section requires Python 2.3.4 or higher.

You can also use the url-signature command to generate the URL signature for symmetric keys, as well as validate it. For more information, see the "url-signature Command" section. The CDSM GUI offers the ability to generate the URL signature for symmetric keys as well. See the "Configuring URL Signing" section for more information about the Key field.

URL Signing Version

The URL signing script offers three different versions:

MD5 hash algorithm

SHA-1 hash algorithm

SHA-1 hash algorithm with the protocol removed from the beginning of the URL (without schema)


Note A reason to use the SHA-1 hash algorithm with the protocol (schema) removed is when a URL is signed for RTSP and a player does a fallback to HTTP for the same URL. The validation fails because the URL signature includes RTSP. If the URL signature does not include the protocol, the fallback URL is validated correctly even though the protocol is HTTP.


Version 0 or No Version Specified

If you do not specify a version, or specify version 0, for the script, MD5 is used and the SIGV string in the script is not added.

Following is an example of the URL signing script using the MD5 security hash algorithm:

python cds-ims-urlsign.py http://www.cisco.com/index.html 8.1.0.4 200000 1 2 cisco

An example of the resulting signed URL follows:

http://www.cisco.com/index.html?IS=0&ET=1241194518&CIP=8.1.0.4&KO=1&KN=2&US=deebacde45bf71
6071c8b2fecaa755b9
 
   

Version 1 Specified

If you specify version 1 for the script, SHA-1 is used and the SIGV=1 string is added.

Following is an example of the URL signing script using the SHA-1 security hash algorithm:

python cds-ims-urlsign.py http://www.cisco.com/index.html 8.1.0.4 200000 1 2 cisco 1

An example of the resulting signed URL follows:

http://www.cisco.com/index.html?SIGV=1&IS=0&ET=1241194679&CIP=8.1.0.4&KO=1&KN=2&US=8349348
ffac7987d11203122a98e7e64e410fa18
 
   

Version 2 Specified

If you specify version 2 for the script, SHA-1 is used. The protocol from the beginning of the URL is removed before the signature is generated, and the SIGV=2 string is added. The protocol is RTSP, HTTP, or RTMP. The URL is signed without the protocol, but the final signed URL is printed with the protocol.

Following is an example of the URL signing script using the SHA-1 security hash algorithm with version 2 specified:

python cds-ims-urlsign.py http://www.cisco.com/index.html 8.1.0.4 200000 1 2 cisco 2

An example of the resulting signed URL follows:

http://www.cisco.com/index.html?SIGV=2&IS=0&ET=1241194783&CIP=8.1.0.4&KO=1&KN=2&US=68b5f5e
d97d1255a0ec42a42a4f779e794df679c
 
   

Version 3

Version 3 is used by the C binary in externally signing the URLs for the public/private key pairs. The protocol (schema) from the beginning of the URL is removed before the signature is generated, and the SIGV =3 string is added. For more information, see the "Public Key URL Signing for Asymmetric Keys" section.

Example of a Python URL Signing Script

The following simple Python script demonstrates how to construct and sign URLs for use with the Internet Streamer CDS. This example script produces signatures compliant with the format used by the Internet Streamer CDS.

Depending on where the Python binary is installed, you may need to modify the first line of the script. The first line is only necessary if you plan to run the script as an executable. However, if you run the script using the Python interpreter, as documented in the "Running a Python URL Signing Script" section, the first line is not required.


Note Sometimes media players append the port number to the URL. The port number is always removed when generating the URL signature.


#!/usr/local/bin/python
import md5
import hmac
import sha
import socket
import time
import sys
import optparse
 
   
def remove_port(url):
        """ Removes the port number from URL and then constructs the URL without port. """
        sep=":"
        arr=url.split(sep)
        url_no_port=arr[0]+sep
        if ( (len(arr)) == 3 ):
                url_no_port=url_no_port+arr[1]+"/"
                rem=arr[2].split("/",1)
                url_no_port=url_no_port+rem[1]
                return url_no_port
        else:
                return url
 
   
def sign_url(url,key):
        """ Signs url using key and returns the signed URL with the signature appended. """
        # Generate a MD5 hash of the key string (not the url)
        foo = md5.new(key)
 
   
        # Update the hash generated with the url string
        # This effectively means concatenating key and url and generating
        # a hash for the two
        foo.update(url)
 
   
        print "MD5 is used"
        # Get the digest in hex format (human readable)
        return url+foo.hexdigest()
 
   
def sign_url_sha1(url,key):
        """ Signs url using key and returns the signed URL with the signature appended. """
        foo = hmac.new(key,url,sha)
        print "SHA1 is used"
        return url+foo.hexdigest()
 
   
def remove_domain(url):
        """ Removes domain from the URL signature if set to 1, keep domain if set to 0.  """
 
   
        sep="://"
        arr=url.split(sep)
        url = arr[1]
        sep="/"
        arr_1=url.split(sep,1)
        print "Remove domain"
        temp = arr[0] + "://" + arr_1[0]
        print "Remove domain PRINT:: " + temp
        arr_1[0] = temp
        print arr_1
        return arr_1
 
   
def usage():
        """ Prints usage for the URL signing script. """
 
   
        print "Usage:"
        print "python cds-ims-urlsign.py <url> <client-ip> <expiry-delay-seconds> 
<key-id-owner> <key-id-number> <key> <exclude-domain> <version>"
        print "Example:"
        print "python cds-ims-urlsign.py rtsp://abc.com/content/Apocalypto.mov 
171.71.50.123 120 1 2 BubbaGump 1 \"\"or1or2"
 
   
 
   
if __name__ == "__main__":
        """ Prints signed URL """
        
        parser = optparse.OptionParser()
        (options, args) = parser.parse_args()
        if len(sys.argv) < 8:
                usage()
                sys.exit(2)
        
        url = sys.argv[1]		# URL
        client_ip = sys.argv[2] 	
        delay_seconds = sys.argv[3]	# Number of seconds after which URL expires
        ko = sys.argv[4] 		# Key ID Owner 
        kn = sys.argv[5] 		# Key ID Number	
        key = sys.argv[6]		# Key 
        domain = sys.argv[7]		# Exclude-domain config
        domain = int(domain)
        if ( len(args) == 7 ):
                version = ""
        else:
                version = sys.argv[8]
                version=int(version)
 
   
        # Set expiry time as current time (seconds since epoch) + delay
        et = time.time() + int(delay_seconds)
        expires = str(int(et))
 
   
        # Based on version we need to generate URL syntax for signing
        # By default v="" , which means sign URL with schema and no SIGV added. Uses md5
        # If v=0 , which means sign URL with schema and SIGV=0 added. Uses md5
        # If v=1 , which means sign URL with schema and SIGV=1 added. Uses sha1 
        # If v=2 , which means sign URL without schema and SIGV=2 added. Uses sha1
        if ((version!="") & (version!=0) & (version!=1)):
                # python-2.5 is needed for partition. So will use split
                #schema,sep,url = url.partition(':')
                sep="://"
                arr=url.split(sep)
                url = sep + arr[1]
                print url
 
   
        if url.find('?')==-1: 
                url2 = url + "?"
        else:
                url2 = url + "&"
        
        url2 = remove_port(url2)
 
   
        if ((domain==1)):
                temp_arr = remove_domain(url2)
                url2 = "/" + temp_arr[1]
                print url2
 
   
        # This string format is fixed and should not be modified.
        # Note that we sign even the "&US=" part that will point to the signature
        # If schema=1 then we need to append ver string as 0.
        if (version==""):
                url2 = url2 + 
"IS=0"+"&ET="+expires+"&CIP="+client_ip+"&KO="+ko+"&KN="+kn+"&US=";
        elif (version==0):
                url2 = url2 + 
"IS=0"+"&ET="+expires+"&CIP="+client_ip+"&KO="+ko+"&KN="+kn+"&US=";
        elif (version==1):
                url2 = url2 + 
"SIGV=1"+"&IS=0"+"&ET="+expires+"&CIP="+client_ip+"&KO="+ko+"&KN="+kn+"&US=";
        elif (version==2):
                url2 = url2 + 
"SIGV=2"+"&IS=0"+"&ET="+expires+"&CIP="+client_ip+"&KO="+ko+"&KN="+kn+"&US=";
                
        # Based on the Version decide the sign Method to call
        if ((version=="") | (version==0)):
                print url2
                url3 = sign_url(url2,key)
 
   
        if ((version ==1) | (version==2)):
                print url2
                url3 = sign_url_sha1(url2,key)
 
   
        #After we sign, if version=2 we add schema to signed URL
        if ((version==2) & (domain!=1)):
                url3=arr[0]+url3
        print url3
 
   
        # Add the schema+domain after signature generation
        if ((domain==1)):
                print temp_arr[0]
                if ((version==2)):
                        url3 = arr[0] + temp_arr[0] + url3
                else:
                        url3 = temp_arr[0] + url3
                print url3
 
   

Running a Python URL Signing Script

The example script can be used as follows:

python cds-ims-urlsign.py <url> <client-ip> <expiry-delay-seconds> <key-id-owner> <key-id-number> <key> <exclude-domain> <version>

Syntax
Description

url

URL to sign.

client-ip

IP address of the client for which this URL is being signed, in dotted decimal format (A.B.C.D). The signed URL is rejected if sent from any other client when signature validation is enabled.

Note The client-ip cannot be left blank or specified with empty quotes (""); it must be a valid IP address. If the client IP address is not to be considered in validating the URL, you can use any IP address as a place holder, and use the exclude validation option, which would not include the client IP address in the URL validation process. In Release 2.5.7 and later, for the Web Engine, see the "Service Rule File for URL Validation and the Exclude-Validation Attribute" section for examples of the exclude-validation attribute. For earlier releases, or for other protocol engines, see Table 4-13 for configuring service rules on each SE.

expiry-delay-seconds

Seconds (from now) when the URL expires. The request is rejected if the time period has passed when the URL is validated at the device. See the "Importance of Device Synchronization" section.

Note The expiry-delay-seconds cannot be left blank or specified with empty quotes (""); it must be a number representing the expiration time for the URL. If the expiry time is not to be considered in validating the URL, you can use any number of seconds, and use the exclude validation option for the expiry time. In Release 2.5.7 and later, for the Web Engine, see the "Service Rule File for URL Validation and the Exclude-Validation Attribute" section for examples of the exclude-validation attribute. For earlier releases, or for other protocol engines, see Table 4-13 for configuring service rules on each SE.

key-id-owner

The first index into the key matrix. Valid entries are from 1 to 32.

key-id-number

The second index into the key matrix. Valid entries are from 1 to 16.

key

Shared secret key corresponding to this ordered pair (key-id-owner, key-id-number).

exclude-domain

If set to 1, exclude the domain from the URL signature. If set to 0, include the domain in the URL signature.

If the domain is excluded from the URL signature, then the domain must be excluded from the URL validation. To exclude the domain from URL validation for the Web Engine, use the exclude-domain option for the exclude-validate attribute of the Rule_Validate element. For more information, see the "Service Rule File Structure and Syntax" section. To exclude the domain from the URL validation for any other protocol engine, use the exclude domain-name keyword for the validate-url-signature command. For more information, see the Table 4-13.

Note The exclude-domain parameter is a Release 2.5.9 feature.

version

Hash algorithm used to generate the URL signature. The version number for the hash algorithm is as follows:

0 or none—To use MD5, enter zero (0) or do not enter a version number.

1—To use SHA-1.

2—To use SHA-1 and remove the protocol from the URL before signing.


In addition to the above six variables, the current time is used to generate the URL signing, so even if the same values were used for the above variables, the signed URL would be different.


Note The client IP address and the content expiry are checked during validation based on the configuration of the service rules, which are either configured on each SE or configured by using the Service Rule XML file. For more information, see the "Configuring the CDS for URL Signing" section.


To use the URL signing script on the URL "rtsp://cisco.com/content/CiscoCDS.mov," for the client IP address of 171.71.50.123, with an expiry delay of 120 seconds, a key ID owner of 1, a key ID number of 2, a key of kwnx90KGP, and the MD5 hash algorithm, enter the following:

python cds-ims-urlsign.py rtsp://cisco.com/content/CiscoCDS.mov 171.71.50.123 120 1 2 kwnx90KGP

The signed URL is the following:

rtsp://cisco.com/content/CiscoCDS.mov?IS=0&ET=1209422976&CIP=171.71.50.123&KO=1&KN=2&US=4f
b1c1adf1588fbe11cc6a04c6e69f35
 
   

Note The above signed URL is only an example. The hash algorithm generates a different message digest each time. For more information on the MD5 algorithm, see the IETF RFC 1321. For more information on the SHA-1 algorithm, see the IETF RFC 3174.


URL Signing and Flash Media Streaming

When signing a URL for Flash Media Streaming VOD or Flash Media Streaming live streaming, the full URL for the request is used.

For the Flash Media Streaming interactive application, the Service Engine (acting as the Flash Media Streaming edge server proxy) routes the request to the origin server (which is the Flash Media Interactive Server) by way of the hierarchical path of Service Engines (each acting as proxy for the request). Flash Media Streaming includes the edge server (proxy) mode, and by default, all non-live and non-VOD applications are proxied by using the edge server.

Requests for VOD and live streaming, and all the associated events, are received by the Service Engine and URL signature validation is performed in the PLAY event, which has the full URL, including the content name.

All Flash Media Streaming applications send CONNECT, PLAY, STOP, and DISCONNECT events. In the case of live streaming and VOD, all events are received by the Service Engine and the URL signature is validated in the PLAY event. In the case of interactive applications, only the CONNECT and DISCONNECT events are received by the Service Engine, all other events are proxied by the SE and processed on the origin server. The URL signature validation for interactive applications is performed on the CONNECT event, which does not include the content name.

Table H-1 shows an example of each Flash Media Streaming delivery type, with the requested URL and the URL that is used in the URL Signing script.

Table H-1 Flash Media Streaming URL Signing

Delivery Type
Requested URL
URL Used in Signing

VOD

rtmp://fmsvod.com/vod/sample.flv

rtmp://fmsvod.com/vod/sample.flv

Live streaming

rtmp://livefms.com/live/livestream

rtmp://livefms.com/live/livestream

Interactive application

rtmp://fmsvod.com/myvod/sample.flv

rtmp://fmsvod.com/myvod


Importance of Device Synchronization

URL expiry time validation relies on the assumption that the clocks are synchronized on the server running the signing application and the Service Engines validating the URL. Use of Network Time Protocol (NTP) on all devices, including the device running the signing application or script, is highly recommended.

It is not sufficient to merely have the same local times on two devices while their time zones differ.

For example, the following two devices are not synchronized:

Device 1:

Local Time: 11:00:59 PM, October 12, 2008

Time Zone: PST

Device 2:

Local Time: 11:00:59 PM, October 12, 2008

Time Zone: EST

The following two devices are synchronized:

Device 1:

Local Time: 11:00:59 AM, October 12, 2008

Time Zone: PST

Device 2:

Local Time: 2:00:59 PM, October 12, 2008

Time Zone: EST

Understanding the Signing Procedure

To customize the URL signing script for your portal, or to write your own signing application in the platform and language of your choice, and still be able to validate URLs within the CDS, follow the steps explained in this section.

The URL signing script performs these steps when processing an unsigned URL:

1. Reads the version information from the script argument and removes the protocol from the URL if the version equals 2.

2. Checks if the URL already contains a query string.

If the URL does not contain a query string, appends a question mark (?).

If the URL does contain a query string, appends an ampersand (&).

3. Removes the port number in the URL, if one exists.

4. Appends the string IS=0. This string is for legacy support with some CDS components that use both internal (within CDS) and external (portal) signing mechanisms.

5. Appends the string &ET=.

6. Gets the current time in seconds since epoch (as an integer). Adds the expiry time in seconds as an integer and appends this integer.

7. Appends the string &CIP=.

8. Appends the requesting client IP address, using dotted decimal format.

9. Appends the string &KO=.

10. Appends the key ID owner corresponding to the key being used.

11. Appends the string &KN=.

12. Appends the key ID number corresponding to the key being used.

13. Appends the string &US=.

14. Stores this as url2; for example:

"rtsp://cisco.com/content/CiscoCDS.mov?IS=0&ET=1209422976&CIP=171.71.50.123&KO=1&KN=2&US="

15. Generates an MD5 hash of the key being used.

16. Updates the generated hash with url2.

17. Converts the hash to its equivalent human readable hex digest; for example:

4fb1c1adf1588fbe11cc6a04c6e69f35

18. Appends the hex digest to url2. The URL signing is complete.

Public Key URL Signing for Asymmetric Keys

Asymmetric keys always have a key pair made up of a public key and private key. The private key is used for signing and the public key is used for validation.

The public key URL signing supports Elliptic Curve (EC) keys and uses EC Digital Signature Algorithm (DSA), which is the EC equivalent of DSA for signature generation and signature validation.

Elliptic Curve Cryptography (ECC) has the following main advantages:

Key size is small while still offering good security

Key is easy to store

Computation is faster than DSA or RSA

The signed URL of EC-DSA contains some clear text data (for example, client IP [CIP], expiry time [ET], and the US=DSA r and s values). For transport security, the Internet Streamer CDS software takes these tag values, converts them into hexadecimal values, then encrypts them using American Encryption Standard (AES) Counter (CTR) mode and 128-bits key size when the url-signature command symmetric-key option is configured by the user. The encrypted output is attached to the URL as base64 encoded data. Both hexadecimal and Base64 conversions produce URL-safe values, but Base64 produces smaller output, which is why AES encrypted output is converted to Base64.

How Public Key URL Signing Works with CDS

You can generate a pair of EC keys and write each key (public and private) into separate files (a public key file and a private key file) by using the Privacy Enhanced Mail (PEM) format. The url-signature command has keyword options that provide a way to upload these files and associate them to a particular key owner and key number. If you want secure transmission of the CIP, ET, and US tag values, you can use the symmetric-key option of the url-signature command., which uses AES to encrypt the CIP, ET, and US tag values. The CDSM GUI offers the same options for uploading the files and secure transmission. See the "Configuring URL Signing" section for more information.

The URL can be signed externally using the C binary. The signed URL is then sent to the CDS for signature validation. The CDS validates the signed URL by using the key owner (KO) and key number (KN) to look up the URL signature. You can also use the url-signature command to generate the URL signature for symmetric keys, as well as validate it. The CDSM GUI offers the ability to generate the URL signature for symmetric keys as well. See the "Configuring URL Signing" section for more information.

url-signature Command

The url-signature command creates a symmetric key or asymmetric key for the URL signature.

url-signature key-id-owner key-id-owner key-id-number key-id-number {key key | public-key public-key [private-key private-key [symmetric-key] | symmetric-key]}

Syntax Description

key-id-owner

Configures the owner for this key.

key-id-owner

Specifies the ID for the owner of this key. Valid entries are from 1 to 32.

key-id-number

Configures the ID number for this key.

key-id-number

Specifies the ID for the number of this key. Valid entries are from 1 to 32.

key

Configures the symmetric encryption key for signing a URL.

key

Specifies the encryption key. The maximum number of characters is 16. Spaces are not allowed.

public-key

Configures the public key for the specified key owner (KO) and key number (KN).

public-key

Specifies the public key.

private-key

Optional. Configures the private key for the specified KO and KN.

private-key

Specifies the private key.

symmetric-key

Optional. Uses AES to further encrypt the CIP, ET, and US tag values by using the symmetric-key. The length of the AES key is 16 bytes or 128 bits, which is 16 characters.


Following is an example of generating and encrypting the public key and private key using the url-signature command:

(config)# url-signature key-id-owner 1 key-id-number 10 public-key http://1.1.1.1/ec_pub_key private-key 
http://1.1.1.1/ec_pub_key symmetric-key
 
   

URL Signing C Program

To use the C binary to generate the signed URL using the private key, do the following:


Step 1 Get the following information from the client:

URL

Expiry time

Client IP address

Private key file

Key owner

Key number

Symmetric key (AES encryption)


Note The client-ip cannot be left blank or specified with empty quotes (""); it must be a valid IP address. If the client IP address is not to be considered in validating the URL, you can use any IP address as a place holder, and use the exclude validation option, which would not include the client IP address in the URL validation process. In Release 2.5.7 and later, for the Web Engine, see the "Service Rule File for URL Validation and the Exclude-Validation Attribute" section for examples of the exclude-validation attribute. For earlier releases, or for other protocol engines, see Table 4-13 for configuring service rules on each SE.



Note The expiry-delay-seconds cannot be left blank or specified with empty quotes (""); it must be a number representing the expiration time for the URL. If the expiry time is not to be considered in validating the URL, you can use any number of seconds, and use the exclude validation option for the expiry time. In Release 2.5.7 and later, for the Web Engine, see the "Service Rule File for URL Validation and the Exclude-Validation Attribute" section for examples of the exclude-validation attribute. For earlier releases, or for other protocol engines, see Table 4-13 for configuring service rules on each SE.


Step 2 Construct the URL to be signed by removing the schema (the protocol of the URL, for example, HTTP) from the URL.

Step 3 Get the length of the constructed URL and add a tag "LENTOSIGN" before the US tag.

Step 4 Create a digest of the URL with the LENTOSIGN tag using SHA-1 without a key.

Step 5 Sign this digest with an EC private key.

Step 6 The signature contains two values, r and s. Convert them to Hexadecimal and add them to the signed URL.

Step 7 If an AES key is configured, convert the CIP, ET, and US tag values to hexadecimal values, and encrypt them using AES CTR 128 mode. The Initialization Vector (IV) used is 64 bits. The IV is encoded to base64 and added to the URL. After appending the IV to the URL , then append the encrypted data using AES CTR 128. This encrypted data should be encoded to base64 before adding it to URL.


Following is some sample output from C binary:

# ./public_key
 The usage is ./public_key <url> <client-ip> <expiry-delay-seconds> <key-id-owner> 
<key-id-number> <private_key file> <Symmetric-Key>
The number of arguments is less than 8
 
   
# ./public_key rtsp://www.cisco.com/my.wmv 1.1.1.1 20000 1 2 test_priv ciscociscociscoc
Url : rtsp://www.cisco.com/my.wmv , Ko : 1 , KN : 2 Expiry_time : 20000
The Private Key read from file is : -----BEGIN EC PRIVATE KEY-----
MIIBUQIBAQQgNu8C5npnuJPzS+vUDLzbtVYHebXyd2fqI71cFIPky+uggeMwgeAC
AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA////////////////
MEQEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr
vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwRBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLesz
oPShOUXYmMKWT+NC4v4af5uO5+tKfA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////
AAAAAP//////////vOb6racXnoTzucrC/GMlUQIBAaFEA0IABH7vJFy6si5SOY1E
40aByIjsFYuZ9eVuLyo1pyhnX0GINMfkLoJBT0KhJfah5zNuKRSi6V8NtUpaUc28
BYKqx6A=
-----END EC PRIVATE KEY-----
 
   
The ET time value is : 1248690812
The schema removed URL is : ://www.cisco.com/my.wmv
The URL to calculate LENTOSIGN is : 
://www.cisco.com/my.wmv?SIGV=3&IS=0&CIP=1.1.1.1&ET=1248690812&KO=1&KN=2&US=
The URL LENTOSIGN value is : 75
The URL ready for sha1 sign without Key : 
://www.cisco.com/my.wmv?SIGV=3&IS=0&CIP=1.1.1.1&ET=1248690812&KO=1&KN=2&LENTOSIGN=79&US=
The ECDSA Signed URL is : 
rtsp://www.cisco.com/my.wmv?SIGV=3&IS=0&CIP=1.1.1.1&ET=1248690812&KO=1&KN=2&US=DSA=r:CFB03
EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E005668D:s:57ED0E8DF7E786C87E39177DD339
8A7FB010E6A4C0DC8AA71331A929A29EA24E
The base64 encoded IV is : cXgS7eo+sHc=
The ET value to be converted to Hex is : 1248690812The Hex converted ET string is : 
0c304500080c
The IP to be converted to Hex is : 1.1.1.1Hex representation of IP Value is : 01010101
The length of SIG->r is : 64
The length of SIG->r is : 32
The constructed Hex string after adding SIG->r Tag representation : 
01060c304500080c0204010101010332CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E0
05668D
The length of SIG->s is : 64
The length of SIG->s is : 32
The data that will be encrypted is : 
01060c304500080c0204010101010332CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E0
05668D043257ED0E8DF7E786C87E39177DD3398A7FB010E6A4C0DC8AA71331A929A29EA24E
The AES Encrypted URL is : 
rtsp://www.cisco.com/my.wmv?SIGV=3&IS=0&KO=1&KN=2&cXgS7eo+sHc=X+HOeJ6yKmUmmzLObphXZ98ttyj7
BaAeQF1hCaYBxwHgswiNAW+Uj+IHBLojKgxiCXULiPBmawF1czVKrvVmpvA8OoQ5ujJzpjYXeLLBGGSs3g==
 
   

C Program for URL Signing

The pseudo code for signature generation has the following tasks:


Step 1 Make sure the C program accepts the following values as command line arguments to generate the signed URL:

URL

Client_IP

Expiry_time

KO

KN

Private Key file in PEM format

Symmetric Key (for AES Encryption)

Step 2 After reading the arguments, check if the Private Key file can be read. If yes , run fread to read all the data .

Step 3 The URL given as the input argument to the program should then be passed to the function that can remove the schema (the protocol, for example, HTTP) from the URL. For example, http://www.cisco.com/index.html should be changed to ://www.cisco.com/index.html.

Step 4 Construct the URL with all the sign tags as follows:

snprintf(url_lentoadd , URL_MAX,
        "%s%c" "%s&" "%s" "&%s=%s" "&%s=%s" "&%s=%s" "&%s=%s" "&%s=",
        url,'?',
        sigv,"IS=0",
        "CIP",ip,
        "ET",cur_time,
        "KO",ko,
        "KN",kn,
        "US");
 
   

An example of the output follows:

//www.cisco.com/index.html?SIGV=3&IS=0&CIP=1.1.1.1&ET=123456789&KO=1&KN=3&US=
 
   
In the above call snprintf , we construct the URL as above. The cur_time is calculated as 
Epoch_time + expiry time . 
 
   

Step 5 Calculate the length of the URL formed in Step 4.

For example, the length of URL ://www.cisco.com/index.html?SIGV=3&IS=0&CIP=1.1.1.1&ET=123456789&KO=1&KN=3&US is 78.

Step 6 Reconstruct the URL again with the new Tag LENTOSIGN added before the US tag as follows:

snprintf(url_to_sign, URL_MAX,
        "%s%c" "%s&" "%s" "&%s=%s" "&%s=%s" "&%s=%s" "&%s=%s" "&%s=%d" "&%s=",
        url_without_schema,(strchr(url, '?')) ? '&' : '?',
        sigv,"IS=0",
        "CIP",ip,
        "ET",cur_time,
        "KO",ko,
        "KN",kn,
        "LENTOSIGN",len_to_add,
        "US");
 
   

An example of the output follows:

://www.cisco.com/index.html?SIGV=3&IS=0&CIP=1.1.1.1&ET=123456789&KO=1&KN=3&LENTOSIGN=82&US=
 
   

Note The value of LENTOSIGN is taken from Step 5. Also the URL does not have the schema (protocol).


Step 7 The URL is ready to be signed using SHA-1 without a key. An example of a URL ready for SHA-1 without a key follows: ://www.cisco.com/index.html?SIGV=3&IS=0&CIP=1.1.1.1&ET=123456789&KO=1&KN=3&LENTOSIGN=82&US=

The following APIs are used to sign the URL:

create_digest(sign,url_to_sign);
void create_digest(char *digest,char *data)
{
    memset(digest,0,sizeof(digest));
    int md_len;
    unsigned char digest1[20];
    EVP_MD_CTX md_ctx;
    EVP_MD_CTX_init(&md_ctx);
    EVP_DigestInit_ex(&md_ctx, EVP_ecdsa(),NULL);
    EVP_DigestUpdate(&md_ctx,data,strlen(data));
    EVP_DigestFinal_ex(&md_ctx,digest,&md_len);
}
 
   

Step 8 The private key is read from the file and EC_KEY is created using the following APIs:

EC_KEY *eckey=NULL;
    ECDSA_SIG *sig=NULL;
    BIO *out_priv=NULL;
 
   
out_priv=BIO_new_mem_buf(private_key,strlen(private_key));
 
   
eckey=(EC_KEY *)PEM_read_bio_ECPrivateKey(out_priv,NULL,NULL,NULL);
 
   

Step 9 The EC-DSA signature is created using the EC_KEY on the digest that was created in Step 7.

sig=ECDSA_do_sign(sign,20,eckey);
 
   

If the signature is successful, the sig parameter contains r and s values. Extract the r and s values using the following commands:

BN_bn2hex(sig->r)
BN_bn2hex(sig->s)
 
   

Step 10 Add these signature values to the URL generated in Step 4.

strcat(url_lentoadd,"DSA=r:");
    strcat(url_lentoadd,BN_bn2hex(sig->r));
    strcat(url_lentoadd,":s:");
    strcat(url_lentoadd,BN_bn2hex(sig->s));
 
   

An example of the final EC-DSA signed URL follows:

http://www.cisco.com/index.html?SIGV=3&IS=0&CIP=1.1.1.1&ET=123456789&KO=1&KN=3&US=DSA=r:CF
B03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E005668D:s:57ED0E8DF7E786C87E39177DD
3398A7FB010E6A4C0DC8AA71331A929A29EA24E
 
   

Step 11 If transport security needs to be applied to the Tag values (CIP, ET, and US), use AES CTR 128 encryption. Convert them to hexadecimal format. Following is an example:

ET : 01 length hexadecimal_value of ET

 
   

ET is 01 length hexadecimal (1248690812). The resulting value is: 01 06 0c304500080c, which equals 01060c304500080c. The ET value is converted to hexadecimal by taking two digits at a time from the original ET, which in the example is 1248690812. Following are each two-digit conversion:

12 = 0c

48 = 30

69 = 45

08 = 00 08

12 = 0c

Each hexadecimal is four bits. The length is calculated based on the resulting values from the hexadecimal conversion. In the example, there are six 8-bit lengths: 0c 30 45 00 08 0c.

CIP : 02 length hexadecimal (IP)

CIP is 02 length hexadecimal (1.1.1.1). The resulting value is : 02 04 01010101, which equals 020401010101.

US : 03 length sig->r

US is : 03 length ( CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E005668D). The resulting value will be : 03 32 CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E005668D, which equals 0332CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E005668D.

US : 04 length sig->s

US is: 04 length (sig->s). The resulting value is: 04 3257ED0E8DF7E786C87E39177DD3398A7FB010E6A4C0DC8AA71331A929A29EA24E, which is equal to 043257ED0E8DF7E786C87E39177DD3398A7FB010E6A4C0DC8AA71331A929A29EA24E.

The AES Key should be exactly16 bytes in length. It cannot be greater than 16 bytes or less than 16 bytes .

Step 12 Once the ET , CIP and US Tag values have been constructed in hexadecimal, they need to put together to send them to AES CTR encrypt API .

The values from Step 11 are the following:

01060c304500080c + 020401010101 + 
0332CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E005668D + 
043257ED0E8DF7E786C87E39177DD3398A7FB010E6A4C0DC8AA71331A929A29EA24E
 
   

The data that is encrypted using AES CTR 128 is the following:

01060c304500080c0204010101010332CFB03EDB33810AB6C79EE3C47FBD86D227D702F25F66C01CF03F59F1E0
05668D043257ED0E8DF7E786C87E39177DD3398A7FB010E6A4C0DC8AA71331A929A29EA24E
 
   

The data that is encrypted using AES CTR is converted to char * , so the length is 82 bytes.

Step 13 Before calling the APIs to perform the AES CTR encryption, the IV needs to be generated. The IV generated is 64 bits in length.

RAND_bytes(iv,8);
 
   

With the IV that is generated and the resultant data from Step 12, use the following APIs to encrypt the data using AES CTR mode.

AES_set_encrypt_key(sym_key,AES_BLOCK_SIZE*8,&keys);
AES_ctr128_encrypt();	//Need to pass all the arguments
 
   

Step 14 Construct the AES Encrypted URL over EC-DSA signature as follows :

snprintf(final_aes,URL_MAX,
        "%s%c" "%s" "&%s=%s" "&%s=%s" "&%s=%s" "&%s=%s" "%s",
        url,(strchr(url, '?')) ? '&' : '?',
        sigv,
        "IS","0",
        "KO",ko,
        "KN",kn,
        "US",
        base64_iv_p,
        base64_encode);
 
   

Note The IV generated is converted to Base64 format. It is attached to URL after the "US=" tag. The AES CTR encryption output is converted to Base64 format and appended to the URL after adding IV.


For example, if the Base64 encoded IV is : cXgS7eo+sHc=, and the AES CTR encryption output in Base64 format is : X+HOeJ6yKmUmmzLObphXZ98ttyj7BaAeQF1hCaYBxwHgswiNAW+Uj+IHBLojKgxiCXULiPBmawF1czVKrvVmpvA8OoQ5ujJzpjYXeLLBGGSs3g==

The final AES encrypted URL is as follows:

http://www.cisco.com/index.html?SIGV=3&IS=0&KO=1&KN=3&US=
 
   

Step 15 Add the IV in Base64 format to the URL.

http://www.cisco.com/index.html?SIGV=3&IS=0&KO=1&KN=3&US=cXgS7eo+sHc=
 
   

Step 16 Finally, append the AES encryption output in Base64 format.

http://www.cisco.com/index.html?SIGV=3&IS=0&KO=1&KN=3&US=cXgS7eo+sHc= 
X+HOeJ6yKmUmmzLObphXZ98ttyj7BaAeQF1hCaYBxwHgswiNAW+Uj+IHBLojKgxiCXULiPBmawF1czVKrvVmpvA8Oo
Q5ujJzpjYXeLLBGGSs3g==
 
   

These are the detailed steps that are used in generating a signed URL. This can be implemented completely using a C program.