post
poster: Jaguarstrike
description: PHP Expiring Hash Token done right
language: PHP
[download]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
define('HASHTOKEN_KEY', 'Whatever');

//Anything above this line should be done in a different file

class HashToken
{
    const KEY        = HASHTOKEN_KEY;
    const STD_EXPIRY = 300;
    
    public static function getToken($userKey, $life = self::STD_EXPIRY, $emergeTime = 0)
    {
        $time = time();
        
        $expiry = $time + $life + $emergeTime;
        $emerge = $time + $emergeTime;
        
        $source = implode('/',
            array($emerge, $expiry, $time, self::KEY, $userKey)
        );
        
        $hash   = hash('sha256', $source);
        
        $token  = implode( '/',
            array(dechex($time), dechex($emerge), $hash, dechex($expiry))
        );
        
        return $token;
    }
    
    public static function checkToken($token, $userKey)
    {
        $time = time();
        list($baseTimeHintHex, $emgHintHex, $tokenHash, $expHintHex) = explode('/', $token);
        
        $baseTimeHint = hexdec($baseTimeHintHex);
        $emgHint      = hexdec($emgHintHex);
        $expHint      = hexdec($expHintHex);
        
        $source   = implode('/', 
            array($emgHint, $expHint, $baseTimeHint, self::KEY, $userKey)
        );
        
        $testHash = hash('sha256', $source);
        
        return(
            ($tokenHash == $testHash)
            &&
            (
                ($expHint >  $time || $expHint == $baseTimeHint)
                &&
                ($emgHint <= $time || $emgHint == $baseTimeHint)
            )
        );
    }
}

//Anything below this line should be done in a different file

$username = 'username';

//echo "First try" . PHP_EOL;
$token = HashToken::getToken($username, 3); //Token expires after 3 seconds
//sleep(1);
  sleep(2);
//sleep(3);

echo $token . PHP_EOL;
echo (HashToken::checkToken($token, $username) ? 'Passed' : 'Failed') . PHP_EOL;

/*/
echo "Try again after two seconds" . PHP_EOL;
sleep(2);
echo $token . PHP_EOL;
echo (HashToken::checkToken($token, $username) ? 'Passed' : 'Failed') . PHP_EOL;
//*/