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 $ords = array_pad($ords,ceil(($length+
32/$this->bytesString
)/$npad)*$npad-32/$this->bytesString
,0);
211 $mask = (1 << $this->bytesString
) - 1;
212 for($i = 0; $i < count($ords) * $this->bytesString
; $i +
= $this->bytesString
)
213 $bin[$i>>5] |
= ($ords[$i / $this->bytesString
] & $mask) << (24 - $i%32
);
214 $bin[] = $length*$this->bytesString
;
218 function array_split($a, $n) {
220 while (count($a)>$n) {
222 for($i = 0;$i<$n;$i++
)
223 $s[] = array_shift($a);
227 $a = array_pad($a,$n,0);
234 * Process and return the hash.
236 * @param $str Input string to hash
237 * @param $ig_func Option param to ignore checking for php > 5.1.2
238 * @return string Hexadecimal representation of the message digest
240 function hash($str, $ig_func = true)
242 unset($binStr); // binary representation of input string
243 unset($hexStr); // 256-bit message digest in readable hex format
245 // check for php's internal sha256 function, ignore if ig_func==true
246 if ($ig_func == false) {
247 if (version_compare(PHP_VERSION
,'5.1.2','>=') AND !defined('_NO_HASH_DEFINED')) {
248 return hash("sha256", $str, false);
249 } else if (function_exists('mhash') && defined('MHASH_SHA256')) {
250 return base64_encode(bin2hex(mhash(MHASH_SHA256
, $str)));
256 * Sequence of sixty-four constant 32-bit words representing the
257 * first thirty-two bits of the fractional parts of the cube roots
258 * of the first sixtyfour prime numbers.
260 $K = array((int)0x428a2f98, (int)0x71374491, (int)0xb5c0fbcf,
261 (int)0xe9b5dba5, (int)0x3956c25b, (int)0x59f111f1,
262 (int)0x923f82a4, (int)0xab1c5ed5, (int)0xd807aa98,
263 (int)0x12835b01, (int)0x243185be, (int)0x550c7dc3,
264 (int)0x72be5d74, (int)0x80deb1fe, (int)0x9bdc06a7,
265 (int)0xc19bf174, (int)0xe49b69c1, (int)0xefbe4786,
266 (int)0x0fc19dc6, (int)0x240ca1cc, (int)0x2de92c6f,
267 (int)0x4a7484aa, (int)0x5cb0a9dc, (int)0x76f988da,
268 (int)0x983e5152, (int)0xa831c66d, (int)0xb00327c8,
269 (int)0xbf597fc7, (int)0xc6e00bf3, (int)0xd5a79147,
270 (int)0x06ca6351, (int)0x14292967, (int)0x27b70a85,
271 (int)0x2e1b2138, (int)0x4d2c6dfc, (int)0x53380d13,
272 (int)0x650a7354, (int)0x766a0abb, (int)0x81c2c92e,
273 (int)0x92722c85, (int)0xa2bfe8a1, (int)0xa81a664b,
274 (int)0xc24b8b70, (int)0xc76c51a3, (int)0xd192e819,
275 (int)0xd6990624, (int)0xf40e3585, (int)0x106aa070,
276 (int)0x19a4c116, (int)0x1e376c08, (int)0x2748774c,
277 (int)0x34b0bcb5, (int)0x391c0cb3, (int)0x4ed8aa4a,
278 (int)0x5b9cca4f, (int)0x682e6ff3, (int)0x748f82ee,
279 (int)0x78a5636f, (int)0x84c87814, (int)0x8cc70208,
280 (int)0x90befffa, (int)0xa4506ceb, (int)0xbef9a3f7,
283 // Pre-processing: Padding the string
284 $binStr = $this->string2binint($str,512);
286 // Parsing the Padded Message (Break into N 512-bit blocks)
287 $M = $this->array_split($binStr, 16);
289 // Set the initial hash values
290 $h[0] = (int)0x6a09e667;
291 $h[1] = (int)0xbb67ae85;
292 $h[2] = (int)0x3c6ef372;
293 $h[3] = (int)0xa54ff53a;
294 $h[4] = (int)0x510e527f;
295 $h[5] = (int)0x9b05688c;
296 $h[6] = (int)0x1f83d9ab;
297 $h[7] = (int)0x5be0cd19;
299 // loop through message blocks and compute hash. ( For i=1 to N : )
301 for ($i = 0; $i < $N; $i++
)
303 // Break input block into 16 32bit words (message schedule prep)
306 // Initialize working variables
321 // Compute the hash and update
322 for ($t = 0; $t < 16; $t++
)
324 // Prepare the first 16 message schedule values as we loop
328 $_T1 = $this->addmod2n($this->addmod2n($this->addmod2n($this->addmod2n($_h, $this->Sigma1($_e)), $this->Ch($_e, $_f, $_g)), $K[$t]), $W[$t]);
329 $_T2 = $this->addmod2n($this->Sigma0($_a), $this->Maj($_a, $_b, $_c));
331 // Update working variables
332 $_h = $_g; $_g = $_f; $_f = $_e; $_e = $this->addmod2n($_d, $_T1);
333 $_d = $_c; $_c = $_b; $_b = $_a; $_a = $this->addmod2n($_T1, $_T2);
336 for (; $t < 64; $t++
)
338 // Continue building the message schedule as we loop
339 $_s0 = $W[($t+
1)&0x0F];
340 $_s0 = $this->sigma_0($_s0);
341 $_s1 = $W[($t+
14)&0x0F];
342 $_s1 = $this->sigma_1($_s1);
344 $W[$t&0xF] = $this->addmod2n($this->addmod2n($this->addmod2n($W[$t&0xF], $_s0), $_s1), $W[($t+
9)&0x0F]);
347 $_T1 = $this->addmod2n($this->addmod2n($this->addmod2n($this->addmod2n($_h, $this->Sigma1($_e)), $this->Ch($_e, $_f, $_g)), $K[$t]), $W[$t&0xF]);
348 $_T2 = $this->addmod2n($this->Sigma0($_a), $this->Maj($_a, $_b, $_c));
350 // Update working variables
351 $_h = $_g; $_g = $_f; $_f = $_e; $_e = $this->addmod2n($_d, $_T1);
352 $_d = $_c; $_c = $_b; $_b = $_a; $_a = $this->addmod2n($_T1, $_T2);
355 $h[0] = $this->addmod2n($h[0], $_a);
356 $h[1] = $this->addmod2n($h[1], $_b);
357 $h[2] = $this->addmod2n($h[2], $_c);
358 $h[3] = $this->addmod2n($h[3], $_d);
359 $h[4] = $this->addmod2n($h[4], $_e);
360 $h[5] = $this->addmod2n($h[5], $_f);
361 $h[6] = $this->addmod2n($h[6], $_g);
362 $h[7] = $this->addmod2n($h[7], $_h);
365 // Convert the 32-bit words into human readable hexadecimal format.
366 $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]);
368 return ($this->toUpper
) ?
strtoupper($hexStr) : $hexStr;
374 if (!function_exists('str_split'))
377 * Splits a string into an array of strings with specified length.
378 * Compatability with older verions of PHP
380 function str_split($string, $split_length = 1)
382 $sign = ($split_length < 0) ?
-1 : 1;
383 $strlen = strlen($string);
384 $split_length = abs($split_length);
386 if (($split_length == 0) ||
($strlen == 0)) {
388 } elseif ($split_length >= $strlen) {
391 $length = $split_length;
393 for ($i = 0; $i < $strlen; $i++
)
395 $i = (($sign < 0) ?
$i +
$length : $i);
396 $result[] = substr($string, $sign*$i, $length);
398 $i = (($sign < 0) ?
$i : $i +
$length);
400 $length = (($i +
$split_length) > $strlen)
401 ?
($strlen - ($i +
1))
411 * Main routine called from an application using this include.
414 * require_once('sha256.inc.php');
415 * $hashstr = sha256('abc');
418 * PHP Strings are limitd to (2^31)-1, so it is not worth it to
419 * check for input strings > 2^64 as the FIPS180-2 defines.
421 function _nano_sha256($str, $ig_func = true) {
422 $obj = new nanoSha2((defined('_NANO_SHA2_UPPER')) ?
true : false);
423 return $obj->hash($str, $ig_func);
425 // 2009-07-23: Added check for function as the Suhosin plugin adds this routine.
426 if (!function_exists('sha256')) {
427 function sha256($str, $ig_func = true) { return _nano_sha256($str, $ig_func); }
430 // support to give php4 the hash() routine which abstracts this code.
431 if (!function_exists('hash'))
433 define('_NO_HASH_DEFINED',true);
434 function hash($algo, $data)
436 if (empty($algo) ||
!is_string($algo) ||
!is_string($data)) {
440 if (function_exists($algo)) {