3 * Hashing and salt generation algorithms for use in password management.
6 * These are the algorithms used for password hashing, including generation of salt and selection
7 * of a hashing algorithm. crypt() with blowfish will be used on systems that support it.
8 * If blowfish is not available, then SHA1 with a prepended salt will be used.
10 * When a system without blowfish (e.g. PHP 5.2) is upgraded to one with support (e.g. php 5.3),
11 * the passwords will continue to be stored and useable in SHA1 format until a user either changes
12 * his own password, or an administrator issues a new password.
14 * Copyright (C) 2013 Kevin Yeh <kevin.y@integralemr.com> and OEMR <www.oemr.org>
16 * LICENSE: This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 3
19 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
28 * @author Kevin Yeh <kevin.y@integralemr.com>
29 * @link http://www.open-emr.org
32 define("SALT_PREFIX_SHA1",'$SHA1$');
36 * Generate a salt to be used with the password_hash() function.
39 * This function checks for the availability of the preferred hashing algorithm (BLOWFISH)
40 * on the system. If it is available the salt returned is prefixed to indicate it is for BLOWFISH.
41 * If it is not available, then SHA1 will be used instead.
43 * See php documentation on crypt() for more details.
47 * @return type The algorithm prefix + random data for salt.
49 function oemr_password_salt()
51 $Allowed_Chars ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
58 for($i=0; $i<$Salt_Length; $i++
)
60 $salt .= $Allowed_Chars[mt_rand(0,$Chars_Len)];
63 // This is the preferred hashing mechanism
64 if(CRYPT_BLOWFISH
===1)
67 //This string tells crypt to apply blowfish $rounds times.
68 $Blowfish_Pre = '$2a$'.$rounds.'$';
71 return $Blowfish_Pre.$salt.$Blowfish_End;
73 error_log("Blowfish hashing algorithm not available. Upgrading to PHP 5.3.x or newer is strongly recommended");
75 return SALT_PREFIX_SHA1
.$salt;
81 * Hash a plaintext password for comparison or initial storage.
84 * This function either uses the built in PHP crypt() function, or sha1() depending
85 * on a prefix in the salt. This on systems without a strong enough built in algorithm
86 * for crypt(), sha1() can be used as a fallback.
87 * If the crypt function returns an error or illegal hash, then will die.
90 * @param type $plaintext
94 function oemr_password_hash($plaintext,$salt)
96 // if this is a SHA1 salt, the use prepended salt
97 if(strpos($salt,SALT_PREFIX_SHA1
)===0)
99 return SALT_PREFIX_SHA1
. sha1($salt.$plaintext);
101 else { // Otherwise use PHP crypt()
102 $crypt_return = crypt($plaintext,$salt);
103 if ( ($crypt_return == '*0') ||
($crypt_return == '*1') ||
(strlen($crypt_return) < 6) ) {
104 // Error code returned by crypt or not hash, so die
105 error_log("FATAL ERROR: crypt() function is not working correctly in OpenEMR");
106 die("FATAL ERROR: crypt() function is not working correctly in OpenEMR");
109 // Hash confirmed, so return the hash.
110 return $crypt_return;