5bd2893debf4e293d75e02ee62f50b5fc31e7e11
[core.git] / contrib / chash / chash.php
1 <?php
2 error_reporting(E_ALL | E_STRICT);
3
4 /**
5  * Continued-hashing
6  *
7  * @author              Roland Haeder <roland@mxchange.org>
8  * @copyright   Copyright (c) 2013 by Core Developer Team
9  * @license             See LICENSE (public-domain)
10  */
11
12 /**
13  * Calculates a simple but stronger hash from given string. No salts are being
14  * added here.
15  *
16  * @param       $str    The string to be hashed
17  * @return      $hash   The hash from string $str
18  */
19 function hashString ($str) {
20         // Calculate strong hash from given string
21         $hash = mhash(MHASH_RIPEMD320, $str);
22
23         // Return it hexadecimal-encoded
24         return bin2hex($hash);
25 }
26
27 /**
28  * Double-hashes given string. This is done by hashing the given string and
29  * then hashing the generated hash again.
30  *
31  * @param       $str    The string to be hashed 4 times
32  * @return      $hash   The generated hash
33  */
34 function doubleHashString ($str) {
35         // Generate hash from given hash
36         $hash = hashString(hashString($str));
37
38         // Return it
39         return $hash;
40 }
41
42 /**
43  * Calculates a "modula-hash" based given two hashes.
44  *
45  * @param       $hash1  Hash 1
46  * @param       $hash2  Hash 2
47  */
48 function modulaHash ($hash1, $hash2) {
49         // Both must have same length
50         assert(strlen($hash1) === strlen($hash2));
51
52         // Init new hash
53         $modulaHash = '';
54
55         // "Walk" trough first hash and get every 2 byte of both hashes
56         for ($idx = 0; $idx < strlen($hash1); $idx += 2) {
57                 // Init modula value
58                 $mod = 0;
59
60                 // Get both hash parts and convert to ASCII number
61                 $part1 = hexdec(substr($hash1, $idx, 2));
62                 $part2 = hexdec(substr($hash2, $idx, 2));
63
64                 /*
65                  * If part1 is larget part2, part1 is divident and vise-versa. But don't do it
66                  * if one is zero
67                  */
68                 if (($part1 > $part2) && ($part2 > 0)) {
69                         // 'part1' is larger than 'part2'
70                         $mod = $part1 % $part2;
71                 } elseif (($part1 < $part2) && ($part1 > 0)) {
72                         // 'part2' is larger than 'part1'
73                         $mod = $part2 % $part1;
74                 }
75
76                 // "Invert" the result against 255
77                 $mod = 255 - $mod;
78
79                 // Encode to hex, pre-pad it with zeros and add to new hash
80                 $modulaHash .= padHex($mod);
81         } // END - for
82
83         // Modula hash must have same length as input hash
84         assert(strlen($modulaHash) === strlen($hash1));
85
86         // Return modula hash
87         return $modulaHash;
88 }
89
90 /**
91  * Calculates a "sqrt-hash" based given two hashes and single-hash it
92  *
93  * @param       $hash1  Hash 1
94  * @param       $hash2  Hash 2
95  */
96 function sqrtHash ($hash1, $hash2) {
97         // Both must have same length
98         assert(strlen($hash1) === strlen($hash2));
99
100         // Init new hash
101         $sqrtHash = '';
102
103         // "Walk" trough first hash and get every 2 byte of both hashes
104         for ($idx = 0; $idx < strlen($hash1); $idx += 2) {
105                 // Init modula value
106                 $mod = 0;
107
108                 // Get both hash parts and convert to ASCII number
109                 $part1 = hexdec(substr($hash1, $idx, 2));
110                 $part2 = hexdec(substr($hash2, $idx, 2));
111
112                 // Calculate square root of both parts being multiplied and round up, then "invert" it against 255
113                 $sqrt = intval(255 - ceil(sqrt($part1 * $part2)));
114
115                 // Encode to hex, pre-pad it with zeros and add to new hash
116                 $sqrtHash .= padHex($sqrt);
117         } // END - for
118
119         // "sqrt-hash" must have same length as input hash
120         assert(strlen($sqrtHash) === strlen($hash1));
121
122         // Hash reversed "sqrt-hash" again and return it
123         return hashString(strrev($sqrtHash));
124 }
125
126 /**
127  * Converts a number between 0 and 255 into a zero-padded hexadecimal string
128  *
129  * @param       $num    Number between 0 and 255
130  * @return      $hex    Hexadecimal string, padded with zeros
131  */
132 function padHex ($num) {
133         // Must be a integer number and between 0 and 255
134         assert(is_int($num));
135         assert($num >= 0);
136         assert($num <= 255);
137
138         // Convert it
139         $hex = str_pad(dechex($num), 2, '0', STR_PAD_LEFT);
140
141         // ... and return it
142         return $hex;
143 }
144
145 /*
146  * Calculate "genesis" hashes, please note that these "genesis strings" are now
147  * known to the public as you can read them here in source code and therefore I
148  * will not use them for the real genesis hashes.
149  */
150 $hashes = array(
151         // A famous quote from Deus Ex 2 - Invisible War
152         doublehashString('"Informations must be free." - AI Helios from Deus Ex'),
153         // My name + URL of my first StatusNet instance
154         doubleHashString('Roland Haeder, https://status.mxchange.org'),
155         // A famous quote from Linus Torwalds
156         doubleHashString('"Software is like sex. Its better when its free." - Linus Torwalds'),
157         // Possible truth ;-)
158         doubleHashString('September 11 is a big lie.'),
159
160         // GNU is not Uni*
161         doubleHashString('GNU is Not Uni*.'),
162         // WINE is not an emulator
163         doubleHashString('WINE Is Not an Emulator.'),
164         // FlightGear - Fly free!
165         doubleHashString('FlightGear - Fly free!'),
166         // Linus Torwalds Quote
167         doubleHashString('Your code is shit.. your argument is shit.'),
168 );
169
170 // Calculate "modula hash" from 1st/4th and 2nd/3rd
171 $modulaHashes = array(
172         // "Block" 0
173         modulaHash($hashes[0], $hashes[3]),
174         modulaHash($hashes[1], $hashes[2]),
175
176         // "Block" 1
177         modulaHash($hashes[4], $hashes[7]),
178         modulaHash($hashes[5], $hashes[6]),
179 );
180
181 // Calculate "sqrt hash"
182 $sqrtHashes = array(
183         sqrtHash($modulaHashes[0], $modulaHashes[1]),
184         sqrtHash($modulaHashes[2], $modulaHashes[3])
185 );
186
187 // Calulcate modula hash
188 $modulaHash = modulaHash($sqrtHashes[0], $sqrtHashes[1]);
189
190 // Output results
191 print ('hashes=' . print_r($hashes, TRUE));
192 print ('modulaHashes=' . print_r($modulaHashes, TRUE));
193 print ('sqrtHashes=' . print_r($sqrtHashes, TRUE));
194 print ('modulaHash=' . $modulaHash . PHP_EOL);
195
196 // [EOF]
197 ?>