Key Generation

Learn how to create keys for locked aliases
When an alias is locked, requesting an image from it will require a key parameter that will be validated to determine if the image should be served.

A key value consists of a SHA1 version of your token + querystring + secret
The querystring part should not contain the key parameter.

This technique is meant to be used server-side because the secret should not be revealed publicly.
The Account Secret is a secret that will unlock any and all of your aliases.
You can create secrets per alias, so you do not have to hand out the master key, but instead you can hand out secrets to specific aliases. You can also revoke these secrets at any time.

Pseudo-code for key generation

Have the values for token, querystring, and secret
Setup querystring (as qs):
- remove any leading '?' or '&'
- sort characters ascending
  This makes it so `width=90&height=90` and `height=90&width=90` both work.
  A known and harmless side-effect is that `width=9&height=900` will also be valid.
Concatenate token + qs + secret and create a hash SHA1 to produce key

Now the image can be requested as `?width=90&height=90&key=` + key

Simple Node.js implementation

//# file keymaker.js
const crypto = require('crypto'); //# node.js module
var keymaker = {
  generate: function (token, querystring, secret) {
    let qs = querystring;
    if (qs.startsWith('&')) qs = qs.substring(1);
    if (qs.startsWith('?')) qs = qs.substring(1);
    qs = qs.split('').sort().join('');
    let k = crypto.createHash('sha1').update(`${token}${qs}${secret}`);
    return k.digest('hex');
  }
};
module.exports = keymaker;
//# usage
const keymaker = require('./keymaker.js');
let key = keymaker.generate(token, querystring, secret);

Other Server-side implementations

php Testing Pending

//# file Keymaker.php
<?php
namespace App\Libs;
class Keymaker {
  public function generate ($token, $querystring, $secret) {
    $qs = $querystring;
    if (str_starts_with($qs, '&')) $qs = substr($qs, 1);
    if (str_starts_with($qs, '?')) $qs = substr($qs, 1);
    $sorted = str_split($qs);
    sort($sorted);
    $qs = implode($sorted);
    $key = sha1($token . $qs . secret, false);
    return $key;
  }
}
//# usage
$keymaker = new Keymaker();
$key = $keymaker->generate($token, $querystring, $secret);

C# Testing Pending

//# file Keymaker.cs
using System.Security.Cryptography;
namespace ixmage {
  public class Keymaker {
    public string generate (string token, string querystring, string secret) {
      string qs = querystring;
      if (qs.StartsWith("&")) qs = qs.Substring(1);
      if (qs.StartsWith("?")) qs = qs.Substring(1);
      char[] characters = qs.ToArray();
      Array.Sort(characters);
      qs = new string(characters);
      return this.getSha1(token + qs + secret);
    }
    private string getSha1 (string value) {
      var data = Encoding.ASCII.GetBytes(value);
      var hashData = new SHA1Manager().ComputeHash(data);
      string hash = string.Empty;
      foreach (var b in hashData) {
        hast += b.ToString("X2");
      }
      return hash;
    }
  }
}
//# usage
ixmage.Keymaker keymaker = new ixmage.Keymaker();
string key = keymaker.generate(token, querystring, secret);

Python

python

Ruby

ruby

JAVA

java
ok!