public function pbkdf2($p, $s, $c, $dkLen, $a = 'sha256') {
    $hLen = strlen(hash($a, null, true)); /* Hash length. */
    $l    = ceil($dkLen / $hLen);         /* Length in blocks of derived key. */
    $dk   = '';                           /* Derived key. */

    /* Step 1. Check dkLen. */
    if($dkLen > (2^32-1) * $hLen) {
      throw new \phpSec\Exception\GeneralSecurityException('Derived key too long');
      return false;
    }

    for ($block = 1; $block<=$l; $block ++) {
      /* Initial hash for this block. */
      $ib = $b = hash_hmac($a, $s . pack('N', $block), $p, true);
      /* Do block iterations. */
      for ($i = 1; $i<$c; $i ++) {
        /* XOR iteration. */
        $ib ^= ($b = hash_hmac($a, $b, $p, true));
      }
      /* Append iterated block. */
      $dk .= $ib;
    }
    /* Returned derived key. */
    return substr($dk, 0, $dkLen);
  }