3 * Transparent SHA-256 Implementation for PHP 4 and PHP 5
5 * Author: Perry McGee (pmcgee@nanolink.ca)
6 * Website: http://www.nanolink.ca/pub/sha256
8 * Copyright (C) 2006,2007,2008,2009 Nanolink Solutions
10 * Created: Feb 11, 2006
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * or see <http://www.gnu.org/licenses/>.
29 * require_once("[path/]sha256.inc.php");
33 * 1) $shaStr = hash('sha256', $string_to_hash);
35 * 2) $shaStr = sha256($string_to_hash[, bool ignore_php5_hash = false]);
37 * 3) $obj = new nanoSha2([bool $upper_case_output = false]);
38 * $shaStr = $obj->hash($string_to_hash[, bool $ignore_php5_hash = false]);
40 * Reference: http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html
42 * 2007-12-13: Cleaned up for initial public release
43 * 2008-05-10: Moved all helper functions into a class. API access unchanged.
44 * 2009-06-23: Created abstraction of hash() routine
45 * 2009-07-23: Added detection of 32 vs 64bit platform, and patches.
46 * Ability to define "_NANO_SHA2_UPPER" to yeild upper case hashes.
47 * 2009-08-01: Added ability to attempt to use mhash() prior to running pure
50 * 2010-06-10: Added support for 16bytes char and utf8 in string
52 * NOTE: Some sporadic versions of PHP do not handle integer overflows the
53 * same as the majority of builds. If you get hash results of:
54 * 7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff
56 * If you do not have permissions to change PHP versions (if you did
57 * you'd probably upgrade to PHP 5 anyway) it is advised you install a
58 * module that will allow you to use their hashing routines, examples are:
59 * - mhash module : http://ca3.php.net/mhash
60 * - Suhosin : http://www.hardened-php.net/suhosin/
62 * If you install the Suhosin module, this script will transparently
63 * use their routine and define the PHP routine as _nano_sha256().
65 * If the mhash module is present, and $ignore_php5_hash = false the
66 * script will attempt to use the output from mhash prior to running
69 if (!class_exists('nanoSha2'))
73 // php 4 - 5 compatable class properties
76 var $bytesString = 16;
78 // Php 4 - 6 compatable constructor
79 function nanoSha2($toUpper = false) {
80 // Determine if the caller wants upper case or not.
81 $this->toUpper
= is_bool($toUpper)
83 : ((defined('_NANO_SHA2_UPPER')) ?
true : false);
85 // Deteremine if the system is 32 or 64 bit.
86 $tmpInt = (int)4294967295;
87 $this->platform
= ($tmpInt > 0) ?
64 : 32;
90 // Here are the bitwise and functions as defined in FIPS180-2 Standard
91 function addmod2n($x, $y, $n = 4294967296) // Z = (X + Y) mod 2^32
97 $x = (float)$x +
$mask;
102 $y = (float)$y +
$mask;
116 // Logical bitwise right shift (PHP default is arithmetic shift)
117 function SHR($x, $n) // x >> n
119 if ($n >= 32) { // impose some limits to keep it 32-bit
131 $mask = $mask >> ($n-1);
132 return ($x >> $n) |
$mask;
135 return (int)$x >> (int)$n;
138 function ROTR($x, $n) { return (int)(($this->SHR($x, $n) |
($x << (32-$n)) & 0xFFFFFFFF)); }
139 function Ch($x, $y, $z) { return ($x & $y) ^
((~
$x) & $z); }
140 function Maj($x, $y, $z) { return ($x & $y) ^
($x & $z) ^
($y & $z); }
141 function Sigma0($x) { return (int) ($this->ROTR($x, 2)^
$this->ROTR($x, 13)^
$this->ROTR($x, 22)); }
142 function Sigma1($x) { return (int) ($this->ROTR($x, 6)^
$this->ROTR($x, 11)^
$this->ROTR($x, 25)); }
143 function sigma_0($x) { return (int) ($this->ROTR($x, 7)^
$this->ROTR($x, 18)^
$this->SHR($x, 3)); }
144 function sigma_1($x) { return (int) ($this->ROTR($x, 17)^
$this->ROTR($x, 19)^
$this->SHR($x, 10)); }
147 function string2ordUTF8($s,&$byteSize){
149 // par defaut sur 8bits
152 while ($i<strlen($s)){
153 $chars[] = $this->ordUTF8($s, $i, $bytes);
155 // mais si un char necessite 16bits, on passe tout sur 16
156 // sinon on ne concorde pas avec le lecture de la chaine en js
158 if ($bytes>1) $byteSize = 16;
163 function ordUTF8($c, $index = 0, &$bytes)
171 $h = ord($c{$index});
178 // pas utf mais renvoyer quand meme ce qu'on a
182 else if ($h <= 0xDF && $index < $len - 1) {
184 return ($h & 0x1F) << 6 |
(ord($c{$index +
1}) & 0x3F);
186 else if ($h <= 0xEF && $index < $len - 2) {
188 return ($h & 0x0F) << 12 |
(ord($c{$index +
1}) & 0x3F) << 6
189 |
(ord($c{$index +
2}) & 0x3F);
191 else if ($h <= 0xF4 && $index < $len - 3) {
193 return ($h & 0x0F) << 18 |
(ord($c{$index +
1}) & 0x3F) << 12
194 |
(ord($c{$index +
2}) & 0x3F) << 6
195 |
(ord($c{$index +
3}) & 0x3F);
198 // pas utf mais renvoyer quand meme ce qu'on a
204 function string2binint ($str,$npad=512) {
206 $ords = $this->string2ordUTF8($str,$this->bytesString
);
207 $npad = $npad/$this->bytesString
;
208 $length = count($ords);
209 $ords[] = 0x80; // append the "1" bit followed by 7 0's
210 $pad = ceil(($length+
32/$this->bytesString
)/$npad)*$npad-32/$this->bytesString
;
211 $ords = array_pad($ords,$pad,0);
213 $pad *= $this->bytesString
;
214 $bin = array_pad(array(), $pad>>5, 0);
215 $mask = (1 << $this->bytesString
) - 1;
216 for($i = 0; $i < $pad ; $i +
= $this->bytesString
)
217 $bin[$i>>5] |
= ($ords[$i / $this->bytesString
] & $mask) << (24 - $i%32
);
218 $bin[] = $length*$this->bytesString
;
222 function array_split($a, $n) {
224 while (count($a)>$n) {
226 for($i = 0;$i<$n;$i++
)
227 $s[] = array_shift($a);
231 $a = array_pad($a,$n,0);
238 * Process and return the hash.
240 * @param $str Input string to hash
241 * @param $ig_func Option param to ignore checking for php > 5.1.2
242 * @return string Hexadecimal representation of the message digest
244 function hash($str, $ig_func = true)
246 unset($binStr); // binary representation of input string
247 unset($hexStr); // 256-bit message digest in readable hex format
249 // check for php's internal sha256 function, ignore if ig_func==true
250 if ($ig_func == false) {
251 if (version_compare(PHP_VERSION
,'5.1.2','>=') AND !defined('_NO_HASH_DEFINED')) {
252 return hash("sha256", $str, false);
253 } else if (function_exists('mhash') && defined('MHASH_SHA256')) {
254 return base64_encode(bin2hex(mhash(MHASH_SHA256
, $str)));
260 * Sequence of sixty-four constant 32-bit words representing the
261 * first thirty-two bits of the fractional parts of the cube roots
262 * of the first sixtyfour prime numbers.
264 $K = array((int)0x428a2f98, (int)0x71374491, (int)0xb5c0fbcf,
265 (int)0xe9b5dba5, (int)0x3956c25b, (int)0x59f111f1,
266 (int)0x923f82a4, (int)0xab1c5ed5, (int)0xd807aa98,
267 (int)0x12835b01, (int)0x243185be, (int)0x550c7dc3,
268 (int)0x72be5d74, (int)0x80deb1fe, (int)0x9bdc06a7,
269 (int)0xc19bf174, (int)0xe49b69c1, (int)0xefbe4786,
270 (int)0x0fc19dc6, (int)0x240ca1cc, (int)0x2de92c6f,
271 (int)0x4a7484aa, (int)0x5cb0a9dc, (int)0x76f988da,
272 (int)0x983e5152, (int)0xa831c66d, (int)0xb00327c8,
273 (int)0xbf597fc7, (int)0xc6e00bf3, (int)0xd5a79147,
274 (int)0x06ca6351, (int)0x14292967, (int)0x27b70a85,
275 (int)0x2e1b2138, (int)0x4d2c6dfc, (int)0x53380d13,
276 (int)0x650a7354, (int)0x766a0abb, (int)0x81c2c92e,
277 (int)0x92722c85, (int)0xa2bfe8a1, (int)0xa81a664b,
278 (int)0xc24b8b70, (int)0xc76c51a3, (int)0xd192e819,
279 (int)0xd6990624, (int)0xf40e3585, (int)0x106aa070,
280 (int)0x19a4c116, (int)0x1e376c08, (int)0x2748774c,
281 (int)0x34b0bcb5, (int)0x391c0cb3, (int)0x4ed8aa4a,
282 (int)0x5b9cca4f, (int)0x682e6ff3, (int)0x748f82ee,
283 (int)0x78a5636f, (int)0x84c87814, (int)0x8cc70208,
284 (int)0x90befffa, (int)0xa4506ceb, (int)0xbef9a3f7,
287 // Pre-processing: Padding the string
288 $binStr = $this->string2binint($str,512);
290 // Parsing the Padded Message (Break into N 512-bit blocks)
291 $M = $this->array_split($binStr, 16);
293 // Set the initial hash values
294 $h[0] = (int)0x6a09e667;
295 $h[1] = (int)0xbb67ae85;
296 $h[2] = (int)0x3c6ef372;
297 $h[3] = (int)0xa54ff53a;
298 $h[4] = (int)0x510e527f;
299 $h[5] = (int)0x9b05688c;
300 $h[6] = (int)0x1f83d9ab;
301 $h[7] = (int)0x5be0cd19;
303 // loop through message blocks and compute hash. ( For i=1 to N : )
305 for ($i = 0; $i < $N; $i++
)
307 // Break input block into 16 32bit words (message schedule prep)
310 // Initialize working variables
325 // Compute the hash and update
326 for ($t = 0; $t < 16; $t++
)
328 // Prepare the first 16 message schedule values as we loop
332 $_T1 = $this->addmod2n($this->addmod2n($this->addmod2n($this->addmod2n($_h, $this->Sigma1($_e)), $this->Ch($_e, $_f, $_g)), $K[$t]), $W[$t]);
333 $_T2 = $this->addmod2n($this->Sigma0($_a), $this->Maj($_a, $_b, $_c));
335 // Update working variables
336 $_h = $_g; $_g = $_f; $_f = $_e; $_e = $this->addmod2n($_d, $_T1);
337 $_d = $_c; $_c = $_b; $_b = $_a; $_a = $this->addmod2n($_T1, $_T2);
340 for (; $t < 64; $t++
)
342 // Continue building the message schedule as we loop
343 $_s0 = $W[($t+
1)&0x0F];
344 $_s0 = $this->sigma_0($_s0);
345 $_s1 = $W[($t+
14)&0x0F];
346 $_s1 = $this->sigma_1($_s1);
348 $W[$t&0xF] = $this->addmod2n($this->addmod2n($this->addmod2n($W[$t&0xF], $_s0), $_s1), $W[($t+
9)&0x0F]);
351 $_T1 = $this->addmod2n($this->addmod2n($this->addmod2n($this->addmod2n($_h, $this->Sigma1($_e)), $this->Ch($_e, $_f, $_g)), $K[$t]), $W[$t&0xF]);
352 $_T2 = $this->addmod2n($this->Sigma0($_a), $this->Maj($_a, $_b, $_c));
354 // Update working variables
355 $_h = $_g; $_g = $_f; $_f = $_e; $_e = $this->addmod2n($_d, $_T1);
356 $_d = $_c; $_c = $_b; $_b = $_a; $_a = $this->addmod2n($_T1, $_T2);
359 $h[0] = $this->addmod2n($h[0], $_a);
360 $h[1] = $this->addmod2n($h[1], $_b);
361 $h[2] = $this->addmod2n($h[2], $_c);
362 $h[3] = $this->addmod2n($h[3], $_d);
363 $h[4] = $this->addmod2n($h[4], $_e);
364 $h[5] = $this->addmod2n($h[5], $_f);
365 $h[6] = $this->addmod2n($h[6], $_g);
366 $h[7] = $this->addmod2n($h[7], $_h);
369 // Convert the 32-bit words into human readable hexadecimal format.
370 $hexStr = sprintf("%08x%08x%08x%08x%08x%08x%08x%08x", $h[0], $h[1], $h[2], $h[3], $h[4], $h[5], $h[6], $h[7]);
372 return ($this->toUpper
) ?
strtoupper($hexStr) : $hexStr;
378 if (!function_exists('str_split'))
381 * Splits a string into an array of strings with specified length.
382 * Compatability with older verions of PHP
384 function str_split($string, $split_length = 1)
386 $sign = ($split_length < 0) ?
-1 : 1;
387 $strlen = strlen($string);
388 $split_length = abs($split_length);
390 if (($split_length == 0) ||
($strlen == 0)) {
392 } elseif ($split_length >= $strlen) {
393 return array($string);
395 $length = $split_length;
397 for ($i = 0; $i < $strlen; $i++
)
399 $i = (($sign < 0) ?
$i +
$length : $i);
400 $result[] = substr($string, $sign*$i, $length);
402 $i = (($sign < 0) ?
$i : $i +
$length);
404 $length = (($i +
$split_length) > $strlen)
405 ?
($strlen - ($i +
1))
414 * Main routine called from an application using this include.
417 * require_once('sha256.inc.php');
418 * $hashstr = sha256('abc');
421 * PHP Strings are limitd to (2^31)-1, so it is not worth it to
422 * check for input strings > 2^64 as the FIPS180-2 defines.
424 function _nano_sha256($str, $ig_func = true) {
425 $obj = new nanoSha2((defined('_NANO_SHA2_UPPER')) ?
true : false);
426 return $obj->hash($str, $ig_func);
428 // 2009-07-23: Added check for function as the Suhosin plugin adds this routine.
429 if (!function_exists('sha256')) {
430 function sha256($str, $ig_func = true) { return _nano_sha256($str, $ig_func); }
433 // support to give php4 the hash() routine which abstracts this code.
434 if (!function_exists('hash'))
436 define('_NO_HASH_DEFINED',true);
437 function hash($algo, $data)
439 if (empty($algo) ||
!is_string($algo) ||
!is_string($data)) {
443 if (function_exists($algo)) {