docker dev update
[openemr.git] / library / authentication / password_hashing.php
blob599a22d1948b6ae3106b90ef3422fff607cb5d38
1 <?php
2 /**
3 * Hashing and salt generation algorithms for use in password management.
5 * <pre>
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.
13 * </pre>
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>;.
27 * @package OpenEMR
28 * @author Kevin Yeh <kevin.y@integralemr.com>
29 * @link http://www.open-emr.org
32 define("SALT_PREFIX_SHA1", '$SHA1$');
34 /**
36 * Generate a salt to be used with the password_hash() function.
38 * <pre>
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.
44 * </pre>
47 * @return type The algorithm prefix + random data for salt.
49 function oemr_password_salt()
51 $Allowed_Chars ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./';
52 $Chars_Len = 63;
54 $Salt_Length = 22;
56 $salt = "";
58 for ($i=0; $i<$Salt_Length; $i++) {
59 $salt .= $Allowed_Chars[mt_rand(0, $Chars_Len)];
62 // This is the preferred hashing mechanism
63 if (CRYPT_BLOWFISH===1) {
64 $rounds='05';
65 //This string tells crypt to apply blowfish $rounds times.
66 $Blowfish_Pre = '$2a$'.$rounds.'$';
67 $Blowfish_End = '$';
69 return $Blowfish_Pre.$salt.$Blowfish_End;
72 error_log("Blowfish hashing algorithm not available. Upgrading to PHP 5.3.x or newer is strongly recommended");
74 return SALT_PREFIX_SHA1.$salt;
77 /**
78 * Hash a plaintext password for comparison or initial storage.
80 * <pre>
81 * This function either uses the built in PHP crypt() function, or sha1() depending
82 * on a prefix in the salt. This on systems without a strong enough built in algorithm
83 * for crypt(), sha1() can be used as a fallback.
84 * If the crypt function returns an error or illegal hash, then will die.
85 * </pre>
87 * @param type $plaintext
88 * @param type $salt
89 * @return type
91 function oemr_password_hash($plaintext, $salt)
93 // if this is a SHA1 salt, the use prepended salt
94 if (strpos($salt, SALT_PREFIX_SHA1)===0) {
95 return SALT_PREFIX_SHA1 . sha1($salt.$plaintext);
96 } else { // Otherwise use PHP crypt()
97 $crypt_return = crypt($plaintext, $salt);
98 if (($crypt_return == '*0') || ($crypt_return == '*1') || (strlen($crypt_return) < 6)) {
99 // Error code returned by crypt or not hash, so die
100 error_log("FATAL ERROR: crypt() function is not working correctly in OpenEMR");
101 die("FATAL ERROR: crypt() function is not working correctly in OpenEMR");
102 } else {
103 // Hash confirmed, so return the hash.
104 return $crypt_return;