MySQL/MariaDB Changes and Passwords from MD5 to BCrypt 2026/04/17
by Ami Sapphire
Last Updated: 2026/09/16
WARNING: You will need to manually create a hash of your password and insert
them to the database if you are insane enough to use the BCrypt side of the
script changes, as it does not check for the previous MD5 password hash!
UPDATE 2026/04/18: There is now a fallback check for accounts with old insecure
unsalted MD5 passwords! No warning messages for those, however (as of yet).
UPDATE 2026/08/20: Added missing steps for user/login.php.
UPDATE 2026/09/16: Password check and warning for users for MD5-hashed
passwords in user/editbio.php. Also, adds two messages for languages/en.php.
Also... add the one prerequisite explicitly for the database.
Prerequisite
Please convert the password column in [tableprefix'd] fanfiction_authors of
your existing database from varchar(40) to varchar(255). Otherwise the
resultant bcrypt password hash will be truncated!
docs/settingstable.sql
Line 62
Original line:
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Change to:
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
docs/tables.sql
Lines 15, 29, 53, 75, 92, 112, 141, 158, 172, 186, 198, 212, 228, 243, 259,
275, 290, 304, 320, 337, 356, 371, 397, 423, 441, 483, 552
Original line:
) ENGINE=MyISAM;
Change to:
) ENGINE=InnoDB;
Line 71
Original line:
`password` varchar(40) NOT NULL default '0',
Replace with:
`password` varchar(255) NOT NULL default '0',
--
install/install.php
Line 195
Original Line:
if ($_POST['password'] == $_POST['password2']) $encryptpassword = md5($_POST['password']);
Replace with:
if ($_POST['password'] == $_POST['password2']) $encryptpassword = password_hash($_POST['password'], PASSWORD_BCRYPT, ['cost' => 12]);
Lines 496, 522, 537, 548, 562, 585, 596, 604, 612, 618, 627, 637, 646, 656,
666, 675, 694, 706, 719, 728, 758, 768, 781, 816, 956
Original lines:
) ENGINE=MyISAM;");
Replace with:
) ENGINE=InnoDB;");
Line 503
Original line:
KEY `uid` (`uid`)) ENGINE=MyISAM;");
Replace with:
KEY `uid` (`uid`)) ENGINE=InnoDB;");
--
admin/update.php
Line 84
Original line:
) ENGINE=MyISAM;
Replace with:
) ENGINE=InnoDB;
--
admin/members.php
Line 90
Original line:
$encryppass = md5($pass);
Replace with:
$encryppass = password_hash($pass, PASSWORD_BCRYPT, ['cost' => 12]);
--
user/editbio.php
Line 53
Add this segment:
// check for MD5 password hashes after a user logs in to edit their bio and warn them if their password is insecure
// all MD5 hashes are 32 exact characters long, hexadecimal, 0-9 and a-f random
// this set is a bit cursed... but it works
$pwdcharlengthquery = dbquery("SELECT CHAR_LENGTH(password) FROM ".TABLEPREFIX."fanfiction_authors WHERE uid = ".USERUID.";");
$pwdlengthfetch = mysqli_fetch_row($pwdcharlengthquery);
$pwdlengthstring = end($pwdlengthfetch);
$pwdcheck = (int) $pwdlengthstring;
if ($pwdcheck == 32) $output .= "
"._INSECUREPWD."
";
Lines 81, 92 [formerly Lines 71, 82]
Original lines:
$encryppass = md5($pass);
Replace with:
$encryppass = password_hash($pass, PASSWORD_BCRYPT, ['cost' => 12]);
Line 166 [formerly Line 156]
Original line:
$encryppassword = md5($_POST['password']);
Replace with:
$encryppassword = password_hash($_POST['password'], PASSWORD_BCRYPT, ['cost' => 12]);
Line 196 [formerly Line 186]
Original line:
$output .= write_message(_ACTIONSUCCESSFUL." ".(isset($_GET['uid']) ? _BACK2ADMIN : _BACK2ACCT));
Replace with:
$output .= write_message(_ACTIONSUCCESSFUL." ".(isset($_GET['uid']) ? _BACK2ADMIN : _BACK2ACCT."
"._LOGINAGAIN));
--
user/login.php [WARNING: HAS NO FALLBACK TO CHECK FOR MD5 PASSWORDS!]
Line 55
Original line:
$encryptedpassword = md5($_POST['password']);
Replace with:
$encryptedpassword = $passwd['password'];
Line 68
Original line:
if($passwd['password'] == $encryptedpassword) {
Replace with:
if(password_verify($_POST['password'], $encryptedpassword) == $encryptedpassword) {
user/login.php [UPDATE: Now comes with fallback check for MD5 passwords!]
Line 55
Original line:
$encryptedpassword = md5($_POST['password']);
Replace with:
$encryptedpasswordb = $passwd['password'];
Add this line under Line 55:
$encryptedpasswordm = md5($_POST['password']);
Line 69
Original line:
if($passwd['password'] == $encryptedpassword) {
Replace with:
if(password_verify($_POST['password'], $encryptedpasswordb) == $encryptedpasswordb) {
Line 72
Original line:
setcookie($sitekey."_salt", md5($passwd['email'] . $encryptedpassword), time()+60*60*24*30, "/");
Replace with:
setcookie($sitekey."_salt", md5($passwd['email'] . $encryptedpasswordb), time()+60*60*24*30, "/");
Line 76
Original line:
$_SESSION[$sitekey."_salt"] = md5($passwd['email'] . $encryptedpassword);
Replace with:
$_SESSION[$sitekey."_salt"] = md5($passwd['email'] . $encryptedpasswordb);
Add this segment under line 83:
else if($passwd['password'] == $encryptedpasswordm) {
if(isset($_POST['cookiecheck'])) {
setcookie($sitekey."_useruid",$passwd['uid'], time()+60*60*24*30, "/");
setcookie($sitekey."_salt", md5($passwd['email'] . $encryptedpasswordm), time()+60*60*24*30, "/");
}
if(!isset($_SESSION)) session_start( );
$_SESSION[$sitekey."_useruid"] = $passwd['uid'];
$_SESSION[$sitekey."_salt"] = md5($passwd['email'] . $encryptedpasswordm);
$logincode = dbquery("SELECT * FROM ".TABLEPREFIX."fanfiction_codeblocks WHERE code_type = 'login'");
while($code = dbassoc($logincode)) {
eval($code['code_text']);
}
}
--
user/lostpassword.php
Line 57
Original line:
$encryppass = md5($_POST['password']);
Replace with:
$encryppass = password_hash($_POST['password'], PASSWORD_BCRYPT, ['cost' => 12]);
--
languages/en.php
Line 297
Add this line between ICQ and INVALIDEMAIL:
define ("_INSECUREPWD", "Your password is hashed using unsalted MD5, a known insecure hashing algorithm. Please update your password so it can be converted to the more secure bcrypt.");
Line 299
Add this line between INVALIDEMAIL and NEWACCOUNT:
define ("_LOGINAGAIN", "However, if you have changed your password, you will have to login again.");