Creating the Digital Signature

Since iTunes U relies on your institution’s system to provide authentication and authorization information, you must use a security mechanism for iTunes U to validate the authenticity of the information it receives from you. To accomplish this, you send your information to iTunes U along with a digital signature that iTunes U uses to validate the information.

You create the digital signature by using the HMAC-SHA256 algorithm to cryptographically sign the token data you generated with the shared secret.

For more information on HMAC: Keyed-Hashing for Message Authentication and Secure Hash Standards, see RFC 2104 - HMAC at http://www.faqs.org/rfcs/rfc2104.html and http://www.itl.nist.gov/fipspubs/fip180-1.htm, respectively.

To create the digital signature:

  1. Create a signature string by concatenating the URL-encoded key-value string from step 2 in “Generating the Token Data” and the shared secret.

  2. Run the HMAC-SHA256 secure hash algorithm on the signature string (containing the token data and shared secret). HMAC-SHA256 takes an input of any length and generates a 32-byte output value.

  3. Convert the HMAC-SHA256 output value into a 64-character hexadecimal representation.

    For an implementation example, review the following code fragment written in Java:

    /**
      * Generate and sign an authorization token that you can use to securely 
      * communicate to iTunes U a user's credentials and identity. The token 
      * includes all the data you need to communicate  to iTunes U as well as
      * a creation time stamp and a digital signature for the data and time.
      *
      * @param credentials The user's credentials string, as
      *                    obtained from getCredentialsString().
      * @param identity The user's identity string, as
      *                 obtained from getIdentityString().
      * @param time Token time stamp. The token will only be valid from
      *             its time stamp time and for a short time thereafter
      *             (usually 90 seconds).
      * @param key The bytes of your institution's iTunes U shared secret key.
      *
      * @return The authorization token. The returned token will
      *         be URL-encoded and can be sent to iTunes U with
      *         a <A HREF="http://www.ietf.org/rfc/rfc1866.txt">form
      *         submission</A>. iTunes U will typically respond with
      *         HTML that should be sent to the user's browser.
      */
      public String getAuthorizationToken(String credentials, String identity,
                                         Date time, byte[] key) {
    
         // Create a buffer with which to generate the authorization token.
         StringBuffer buffer = new StringBuffer();
    
         // Generate the authorization token.
         try {
    
             // Start with the appropriately encoded credentials.
             buffer.append("credentials=");
             buffer.append(URLEncoder.encode(credentials, "UTF-8"));
    
             // Add the appropriately encoded identity information.
             buffer.append("&identity=");
             buffer.append(URLEncoder.encode(identity, "UTF-8"));
    
             // Add the appropriately formatted time stamp. Note that
             // the time stamp is expressed in seconds, not milliseconds.
             buffer.append("&time=");
             buffer.append(time.getTime() / 1000);
    
             // Generate and add the token signature.
             String data = buffer.toString();
             buffer.append("&signature=");
             buffer.append(this.hmacSHA256(data, key));
    
         } catch (UnsupportedEncodingException e) {
    
             // UTF-8 encoding support is required.
             throw new java.lang.AssertionError(
                 "ITunesU.getAuthorizationToken(): "
                 + "UTF-8 encoding not supported!");
    
         }
    
         // Return the signed authorization token.
         return buffer.toString();
     }
    /**
     * Generate the HMAC-SHA256 signature of a message string, as defined in
     * <A HREF="http://www.ietf.org/rfc/rfc2104.txt">RFC 2104</A>.
     *
     * @param message The string to sign.
     * @param key The bytes of the key to sign it with.
     *
     * @return A hexadecimal representation of the signature.
     */
    public String hmacSHA256(String message, byte[] key) {
    
     // Start by getting an object to generate SHA-256 hashes with.
        MessageDigest sha256 = null;
        try {
            sha256 = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new java.lang.AssertionError(
                    this.getClass().getName()
                    + ".hmacSHA256(): SHA-256 algorithm not found!");
        }
    
        // Hash the key if necessary to make it fit in a block (see RFC 2104).
        if (key.length > 64) {
            sha256.update(key);
            key = sha256.digest();
            sha256.reset();
        }
    
        // Pad the key bytes to a block (see RFC 2104).
        byte block[] = new byte[64];
        for (int i = 0; i < key.length; ++i) block[i] = key[i];
        for (int i = key.length; i < block.length; ++i) block[i] = 0;
    
        // Calculate the inner hash, defined in RFC 2104 as
        // SHA-256(KEY ^ IPAD + MESSAGE)), where IPAD is 64 bytes of 0x36.
        for (int i = 0; i < 64; ++i) block[i] ^= 0x36;
        sha256.update(block);
        try {
            sha256.update(message.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new java.lang.AssertionError(
                    "ITunesU.hmacSH256(): UTF-8 encoding not supported!");
        }
        byte[] hash = sha256.digest();
        sha256.reset();
    
        // Calculate the outer hash, defined in RFC 2104 as
        // SHA-256(KEY ^ OPAD + INNER_HASH), where OPAD is 64 bytes of 0x5c.
        for (int i = 0; i < 64; ++i) block[i] ^= (0x36 ^ 0x5c);
        sha256.update(block);
        sha256.update(hash);
        hash = sha256.digest();
    
        // The outer hash is the message signature...
        // convert its bytes to hexadecimals.
        char[] hexadecimals = new char[hash.length * 2];
        for (int i = 0; i < hash.length; ++i) {
            for (int j = 0; j < 2; ++j) {
                int value = (hash[i] >> (4 - 4 * j)) & 0xf;
                char base = (value < 10) ? ('0') : ('a' - 10);
                hexadecimals[i * 2 + j] = (char)(base + value);
            }
        }
    
        // Return a hexadecimal string representation of the message signature.
        return new String(hexadecimals);
    }

Next, send the token data and digital signature, which make up the authorization token, to iTunes U.



© 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-11-04)