+<?php
+error_reporting(E_ALL | E_STRICT);
+
+/**
+ * Continued-hashing
+ *
+ * @author Roland Haeder <roland@mxchange.org>
+ * @copyright Copyright (c) 2013 by Core Developer Team
+ * @license See LICENSE (public-domain)
+ */
+
+/**
+ * Calculates a simple but stronger hash from given string. No salts are being
+ * added here.
+ *
+ * @param $str The string to be hashed
+ * @return $hash The hash from string $str
+ */
+function hashString ($str) {
+ // Calculate strong hash from given string
+ $hash = mhash(MHASH_RIPEMD320, $str);
+
+ // Return it hexadecimal-encoded
+ return bin2hex($hash);
+}
+
+/**
+ * Double-hashes given string. This is done by hashing the given string and
+ * then hashing the generated hash again.
+ *
+ * @param $str The string to be hashed 4 times
+ * @return $hash The generated hash
+ */
+function doubleHashString ($str) {
+ // Generate hash from given hash
+ $hash = hashString(hashString($str));
+
+ // Return it
+ return $hash;
+}
+
+/**
+ * Calculates a "modula-hash" based given two hashes.
+ *
+ * @param $hash1 Hash 1
+ * @param $hash2 Hash 2
+ */
+function modulaHash ($hash1, $hash2) {
+ // Both must have same length
+ assert(strlen($hash1) === strlen($hash2));
+
+ // Init new hash
+ $modulaHash = '';
+
+ // "Walk" trough first hash and get every 2 byte of both hashes
+ for ($idx = 0; $idx < strlen($hash1); $idx += 2) {
+ // Init modula value
+ $mod = 0;
+
+ // Get both hash parts and convert to ASCII number
+ $part1 = hexdec(substr($hash1, $idx, 2));
+ $part2 = hexdec(substr($hash2, $idx, 2));
+
+ /*
+ * If part1 is larget part2, part1 is divident and vise-versa. But don't do it
+ * if one is zero
+ */
+ if (($part1 > $part2) && ($part2 > 0)) {
+ // 'part1' is larger than 'part2'
+ $mod = $part1 % $part2;
+ } elseif (($part1 < $part2) && ($part1 > 0)) {
+ // 'part2' is larger than 'part1'
+ $mod = $part2 % $part1;
+ }
+
+ // "Invert" the result against 255
+ $mod = 255 - $mod;
+
+ // Encode to hex, pre-pad it with zeros and add to new hash
+ $modulaHash .= padHex($mod);
+ } // END - for
+
+ // Modula hash must have same length as input hash
+ assert(strlen($modulaHash) === strlen($hash1));
+
+ // Return modula hash
+ return $modulaHash;
+}
+
+/**
+ * Calculates a "sqrt-hash" based given two hashes and single-hash it
+ *
+ * @param $hash1 Hash 1
+ * @param $hash2 Hash 2
+ */
+function sqrtHash ($hash1, $hash2) {
+ // Both must have same length
+ assert(strlen($hash1) === strlen($hash2));
+
+ // Init new hash
+ $sqrtHash = '';
+
+ // "Walk" trough first hash and get every 2 byte of both hashes
+ for ($idx = 0; $idx < strlen($hash1); $idx += 2) {
+ // Init modula value
+ $mod = 0;
+
+ // Get both hash parts and convert to ASCII number
+ $part1 = hexdec(substr($hash1, $idx, 2));
+ $part2 = hexdec(substr($hash2, $idx, 2));
+
+ // Calculate square root of both parts being multiplied and round up, then "invert" it against 255
+ $sqrt = intval(255 - ceil(sqrt($part1 * $part2)));
+
+ // Encode to hex, pre-pad it with zeros and add to new hash
+ $sqrtHash .= padHex($sqrt);
+ } // END - for
+
+ // "sqrt-hash" must have same length as input hash
+ assert(strlen($sqrtHash) === strlen($hash1));
+
+ // Hash reversed "sqrt-hash" again and return it
+ return hashString(strrev($sqrtHash));
+}
+
+/**
+ * Converts a number between 0 and 255 into a zero-padded hexadecimal string
+ *
+ * @param $num Number between 0 and 255
+ * @return $hex Hexadecimal string, padded with zeros
+ */
+function padHex ($num) {
+ // Must be a integer number and between 0 and 255
+ assert(is_int($num));
+ assert($num >= 0);
+ assert($num <= 255);
+
+ // Convert it
+ $hex = str_pad(dechex($num), 2, '0', STR_PAD_LEFT);
+
+ // ... and return it
+ return $hex;
+}
+
+/*
+ * Calculate "genesis" hashes, please note that these "genesis strings" are now
+ * known to the public as you can read them here in source code and therefore I
+ * will not use them for the real genesis hashes.
+ */
+$hashes = array(
+ // A famous quote from Deus Ex 2 - Invisible War
+ doublehashString('"Informations must be free." - AI Helios'),
+ // My name + URL of my first StatusNet instance
+ doubleHashString('Roland Haeder, http://status.mxchange.org'),
+ // A famous quote from Linus Torwalds
+ doubleHashString('"Software is like sex. Its better when its free." - Linus Torwalds'),
+ // Possible truth ;-)
+ doubleHashString('September 11 is a big lie.'),
+
+ // GNU is not Uni*
+ doubleHashString('GNU is Not Uni*.'),
+ // WINE is not an emulator
+ doubleHashString('WINE Is Not an Emulator.'),
+ // FlightGear - Fly free!
+ doubleHashString('FlightGear - Fly free!'),
+ // Linus Torwalds Quote
+ doubleHashString('Your code is shit.. your argument is shit.'),
+);
+
+// Calculate "modula hash" from 1st/4th and 2nd/3rd
+$modulaHashes = array(
+ // "Block" 0
+ modulaHash($hashes[0], $hashes[3]),
+ modulaHash($hashes[1], $hashes[2]),
+
+ // "Block" 1
+ modulaHash($hashes[4], $hashes[7]),
+ modulaHash($hashes[5], $hashes[6]),
+);
+
+// Calculate "sqrt hash"
+$sqrtHashes = array(
+ sqrtHash($modulaHashes[0], $modulaHashes[1]),
+ sqrtHash($modulaHashes[2], $modulaHashes[3])
+);
+
+// Calulcate modula hash
+$modulaHash = modulaHash($sqrtHashes[0], $sqrtHashes[1]);
+
+// Output results
+print ('hashes=' . print_r($hashes, TRUE));
+print ('modulaHashes=' . print_r($modulaHashes, TRUE));
+print ('sqrtHashes=' . print_r($sqrtHashes, TRUE));
+print ('modulaHash=' . $modulaHash . PHP_EOL);
+
+// [EOF]
+?>