treehouse : what would you like to learn today?
Web Design Web Development iOS Development

Generate Expiring Amazon S3 Link

Last updated on:

You don't have to make files on Amazon S3 public (they aren't by default). But you can generate special keys to allow access to private files. These keys are passed through the URL and can be made to expire.

<?php 

  if(!function_exists('el_crypto_hmacSHA1')){
    /**
    * Calculate the HMAC SHA1 hash of a string.
    *
    * @param string $key The key to hash against
    * @param string $data The data to hash
    * @param int $blocksize Optional blocksize
    * @return string HMAC SHA1
    */
    function el_crypto_hmacSHA1($key, $data, $blocksize = 64) {
        if (strlen($key) > $blocksize) $key = pack('H*', sha1($key));
        $key = str_pad($key, $blocksize, chr(0x00));
        $ipad = str_repeat(chr(0x36), $blocksize);
        $opad = str_repeat(chr(0x5c), $blocksize);
        $hmac = pack( 'H*', sha1(
        ($key ^ $opad) . pack( 'H*', sha1(
          ($key ^ $ipad) . $data
        ))
      ));
        return base64_encode($hmac);
    }
  }

  if(!function_exists('el_s3_getTemporaryLink')){
    /**
    * Create temporary URLs to your protected Amazon S3 files.
    *
    * @param string $accessKey Your Amazon S3 access key
    * @param string $secretKey Your Amazon S3 secret key
    * @param string $bucket The bucket (bucket.s3.amazonaws.com)
    * @param string $path The target file path
    * @param int $expires In minutes
    * @return string Temporary Amazon S3 URL
    * @see http://awsdocs.s3.amazonaws.com/S3/20060301/s3-dg-20060301.pdf
    */
    
    function el_s3_getTemporaryLink($accessKey, $secretKey, $bucket, $path, $expires = 5) {
      // Calculate expiry time
      $expires = time() + intval(floatval($expires) * 60);
      // Fix the path; encode and sanitize
      $path = str_replace('%2F', '/', rawurlencode($path = ltrim($path, '/')));
      // Path for signature starts with the bucket
      $signpath = '/'. $bucket .'/'. $path;
      // S3 friendly string to sign
      $signsz = implode("\n", $pieces = array('GET', null, null, $expires, $signpath));
      // Calculate the hash
      $signature = el_crypto_hmacSHA1($secretKey, $signsz);
      // Glue the URL ...
      $url = sprintf('http://%s.s3.amazonaws.com/%s', $bucket, $path);
      // ... to the query string ...
      $qs = http_build_query($pieces = array(
        'AWSAccessKeyId' => $accessKey,
        'Expires' => $expires,
        'Signature' => $signature,
      ));
      // ... and return the URL!
      return $url.'?'.$qs;
    }
  }

?>

Usage

<?php echo el_s3_getTemporaryLink('your-access-key', 'your-secret-key', 'bucket-name', '/path/to/file.mov'); ?>

Reference URL

View Comments

Comments

  1. You should mention the real author when you paste my code here.

    Without further ado… the original source of this snippet is:
    5ubliminal’s Amazon S3 Expiring Link Builder.

    Thank you!

    • Great, thanks for noting. I always try and do that. I was looking for this function for myself, found it on Snipplr, and it wasn’t clear who the original author was, so I just credited the page I found it on.

  2. Burke
    Permalink to comment#

    What is to stop someone from refreshing the screen and getting a new URL? I thought AWS was supposed to be able to provide a secure URL, but short of learning the PHP API is there not a way to deliver content securely?

    Thanks for this script. Both of you.

    • Nothing, but then that NEW link expires after the time limit too. The point is, in order to have a useful link to the file, you have to be viewing that particular page, because otherwise the link is pretty useless.

  3. Nick
    Permalink to comment#

    Chris,

    Can you please provide some more detailed instructions for a PHP noob like me?
    Got following questions:
    a) Where do I put the first file?
    b) How do I name it?
    c) Where exactly would I put the 2nd box that you show here?
    d) Won’t the bad guy be able to see my Access KEy etc when he opens that page?

    Thanks.

  4. Permalink to comment#

    Your way of explaining everything in this article is actually good, every
    one be capable of effortlessly know it, Thanks a lot. http://shop-computer.

    info Very very first, for every single store.Try to find the product or service be
    substituted for something you normally use?

  5. This is nice tutorial….it helps me a lot.. I have checked all over but didn’t get right solution.

    Here I find the right solution without wasting a time…

    Nice tutorial.. Kepp it up…

    5***** stars

  6. tray
    Permalink to comment#

    Is there a working version of this anywhere? I saw one on wordpress but the problem was that the temporary link actually revealed the access key if you mouse over it. Another on revealed the access key & secret key when you mouse over it.

    So yeah, is there a working version? And if not could someone make this into a workable WordPress plugin? :)

Leave a Comment

Use markdown or basic HTML and be nice.