This is an example of how to derive the authentication key. This example uses Python. Authentication is required where you connect to the codec over IP.

# Copyright (c) StarLeaf Ltd. 2015

import hashlib
import hmac
import pbkdf2
import binascii

def endpoint_api_key(password, salt_hex, iterations, verbose=False):
  if verbose:
    print "Key is PBKDF2(HMAC-SHA256, '%s', '%s', %d, 32)." % (password, salt_hex, iterations)

  salt = binascii.unhexlify(salt_hex)
  key = pbkdf2.PBKDF2(passphrase=password, salt=salt, iterations=iterations,
                      digestmodule=hashlib.sha256, macmodule=hmac)
  key_hex = key.hexread(32)
  if verbose:
    print "Key is '%s'." % key_hex

  return key_hex

def endpoint_api_response(key, challenge, verbose=False):
  if verbose:
    print "Response is HMAC-SHA256('%s', '%s')." % (key, challenge)

  key_bytes = binascii.unhexlify(key)
  hash =, challenge, hashlib.sha256)
  response = hash.hexdigest()
  if verbose:
    print "Response is '%s'." % response

  return response

if __name__ == '__main__':
  from optparse import OptionParser

  parser = OptionParser()

  parser.add_option("--password", dest='password', help="API password, as set in portal.")
  parser.add_option("--salt", dest='salt', help="Salt to apply to the password during key derivation.")
  parser.add_option("--iterations", dest='iterations', type='int', help="Number of iterations to hash during key derivation.")
  parser.add_option("--key", dest='key', help="Key derived from password.")
  parser.add_option("--challenge", dest='challenge', help="Challenge returned by server.")

  parser.add_option("--mode", type='choice', choices=['key', 'respond'], dest='mode', default='respond',
                    help="Mode: key (derive key from password) or respond (build response to challenge).")
  parser.add_option("--format", type='choice', choices=['text', 'query', 'json'], dest='format', default='text',
                    help="Output format for response: (text (plain text), query (HTTP URI query format) or json (JSON object)).")

  parser.add_option("--verbose", action='store_true', dest='verbose', help="Print details of intermediate steps.")

  (opt, args) = parser.parse_args()

  if opt.key:
    key = opt.key
    key = endpoint_api_key(opt.password, opt.salt, opt.iterations, opt.verbose)

  if opt.mode == 'key':
    print key

  elif opt.mode == 'respond':
    response = endpoint_api_response(key, opt.challenge, opt.verbose)

    if opt.format == 'query':
      print "challenge=%s&response=%s" % (opt.challenge, response)
    elif opt.format == 'json':
      print "{\n  \"challenge\": \"%s\",\n  \"response\": \"%s\"\n}" % (opt.challenge, response)
      print opt.response

    print "Invalid mode '%s'." % opt.mode