scratch – Blame information for rev 66
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | <?php |
2 | /** |
||
3 | * PseudoCrypt by KevBurns (http://blog.kevburnsjr.com/php-unique-hash) |
||
4 | * Reference/source: http://stackoverflow.com/a/1464155/933782 |
||
5 | * |
||
6 | * I want a short alphanumeric hash that’s unique and who’s sequence is difficult to deduce. |
||
7 | * I could run it out to md5 and trim the first n chars but that’s not going to be very unique. |
||
8 | * Storing a truncated checksum in a unique field means that the frequency of collisions will increase |
||
9 | * geometrically as the number of unique keys for a base 62 encoded integer approaches 62^n. |
||
10 | * I’d rather do it right than code myself a timebomb. So I came up with this. |
||
11 | * |
||
12 | * Sample Code: |
||
13 | * |
||
14 | * echo "<pre>"; |
||
15 | * foreach(range(1, 10) as $n) { |
||
16 | * echo $n." - "; |
||
17 | * $hash = PseudoCrypt::hash($n, 6); |
||
18 | * echo $hash." - "; |
||
19 | * echo PseudoCrypt::unhash($hash)."<br/>"; |
||
20 | * } |
||
21 | * |
||
22 | * Sample Results: |
||
23 | * 1 - cJinsP - 1 |
||
24 | * 2 - EdRbko - 2 |
||
25 | * 3 - qxAPdD - 3 |
||
26 | * 4 - TGtDVc - 4 |
||
27 | * 5 - 5ac1O1 - 5 |
||
28 | * 6 - huKpGQ - 6 |
||
29 | * 7 - KE3d8p - 7 |
||
30 | * 8 - wXmR1E - 8 |
||
31 | * 9 - YrVEtd - 9 |
||
32 | * 10 - BBE2m2 - 10 |
||
33 | */ |
||
34 | |||
35 | class PseudoCrypt |
||
36 | { |
||
37 | |||
38 | /* Key: Next prime greater than 62 ^ n / 1.618033988749894848 */ |
||
39 | /* Value: modular multiplicative inverse */ |
||
40 | private static $golden_primes = array( |
||
41 | '1' => '1', |
||
42 | '41' => '59', |
||
43 | '2377' => '1677', |
||
44 | '147299' => '187507', |
||
45 | '9132313' => '5952585', |
||
46 | '566201239' => '643566407', |
||
47 | '35104476161' => '22071637057', |
||
48 | '2176477521929' => '294289236153', |
||
49 | '134941606358731' => '88879354792675', |
||
50 | '8366379594239857' => '7275288500431249', |
||
51 | '518715534842869223' => '280042546585394647' |
||
52 | ); |
||
53 | |||
54 | /* Ascii : 0 9, A Z, a z */ |
||
55 | /* $chars = array_merge(range(48,57), range(65,90), range(97,122)) */ |
||
56 | private static $chars62 = array( |
||
57 | 0=>48,1=>49,2=>50,3=>51,4=>52,5=>53,6=>54,7=>55,8=>56,9=>57,10=>65, |
||
58 | 11=>66,12=>67,13=>68,14=>69,15=>70,16=>71,17=>72,18=>73,19=>74,20=>75, |
||
59 | 21=>76,22=>77,23=>78,24=>79,25=>80,26=>81,27=>82,28=>83,29=>84,30=>85, |
||
60 | 31=>86,32=>87,33=>88,34=>89,35=>90,36=>97,37=>98,38=>99,39=>100,40=>101, |
||
61 | 41=>102,42=>103,43=>104,44=>105,45=>106,46=>107,47=>108,48=>109,49=>110, |
||
62 | 50=>111,51=>112,52=>113,53=>114,54=>115,55=>116,56=>117,57=>118,58=>119, |
||
63 | 59=>120,60=>121,61=>122 |
||
64 | ); |
||
65 | |||
66 | public static function base62($int) |
||
67 | { |
||
68 | $key = ""; |
||
69 | while (bccomp($int, 0) > 0) { |
||
70 | $mod = bcmod($int, 62); |
||
71 | $key .= chr(self::$chars62[$mod]); |
||
72 | $int = bcdiv($int, 62); |
||
73 | } |
||
74 | return strrev($key); |
||
75 | } |
||
76 | |||
77 | public static function hash($num, $len = 5) |
||
78 | { |
||
79 | $ceil = bcpow(62, $len); |
||
80 | $primes = array_keys(self::$golden_primes); |
||
81 | $prime = $primes[$len]; |
||
82 | $dec = bcmod(bcmul($num, $prime), $ceil); |
||
83 | $hash = self::base62($dec); |
||
84 | return str_pad($hash, $len, "0", STR_PAD_LEFT); |
||
85 | } |
||
86 | |||
87 | public static function unbase62($key) |
||
88 | { |
||
89 | $int = 0; |
||
90 | foreach (str_split(strrev($key)) as $i => $char) { |
||
91 | $dec = array_search(ord($char), self::$chars62); |
||
92 | $int = bcadd(bcmul($dec, bcpow(62, $i)), $int); |
||
93 | } |
||
94 | return $int; |
||
95 | } |
||
96 | |||
97 | public static function unhash($hash) |
||
98 | { |
||
99 | $len = strlen($hash); |
||
100 | $ceil = bcpow(62, $len); |
||
101 | $mmiprimes = array_values(self::$golden_primes); |
||
102 | $mmi = $mmiprimes[$len]; |
||
103 | $num = self::unbase62($hash); |
||
104 | $dec = bcmod(bcmul($num, $mmi), $ceil); |
||
105 | return $dec; |
||
106 | } |
||
107 | } |