md5+salt与password_hash()

本文介绍了MD5+Salt的密码加密方法及其局限性,并详细讲解了PHP5.5中提供的PasswordHashingAPI,包括password_hash和password_verify函数的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

md5+salt

 

 直接使用MD5()加密,是很容易被破解的(犹记得曾经忘记密码,到处找免费的破解网站...),但加上salt想要破解就难上很多了,即使你获得salt和最终密文,想要破解也是十分困难的。

 如何实现md5+salt?很简单,密码连接一个随机字符串即可。

function md5_salt_hash($pass)
{
    $salt = ‘5f9901fc60b7669’; //定义一个salt值,最好足够长,或者随机
    return md5($pass, $salt);
}


password_hash

 

 PHP5.5引入了Password Hashing函数,内核自带无需安装扩展,使用起来十分方便。它属于Password Hashing API(创建和校验哈希密码)函数之一。

 Password Hashing API包含4个函数:

 password_hash()password_verify()password_get_info()password_needs_rehash()

 

 string password_hash(string $password, integer $algo [, array $options ])

 参数:

 $password 密码

 $algo  哈希算法

 $options  选项

 实例:

$pwd = "123456";
$hash = password_hash($pwd, PASSWORD_DEFAULT);
echo $hash;


 上例输出结果类似:$$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a,并且刷新页面该哈希值也会不断的变化。


 哈希值创建完毕,我们可以用password_verify()来校验密码是否和哈希值匹配。


 boolean password_verify ( string $password , string $hash )

 它接收2个参数:密码和哈希值,并返回布尔值。检查之前生成的哈希值是否和密码匹配,代码:

if (password_verify($pwd,'$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a')) {  
    echo "密码正确";
} else {  
    echo "密码错误";
}


 基本上使用以上这2个函数就能安全的创建和校验hash密码了。

 

总结


MD5+salt加密 可跨语言加密解密。

password_hash加密 只能通过phppassword_verfiy校验。




在注释的格式和层次以及清晰度上进一步调整下: static bool login_sm3_psw(PgSocket *server, const uint8_t *salt) { char txt[SM3_DIGEST_LENGTH * 2 + 4]; // "sm3" + 64 hex chars + null char step1_hex[SM3_DIGEST_LENGTH * 2 + 1]; const char *src; PgUser *user = get_srv_psw(server); slog_debug(server, "P: send sm3 password"); switch (get_password_type(user->passwd)) { case PASSWORD_TYPE_PLAINTEXT: /* 第一步:计算 sm3(password + username) */ { size_t user_len = strlen(user->name); size_t pass_len = strlen(user->passwd); char *combined = malloc(user_len + pass_len); if (!combined) return false; memcpy(combined, user->passwd, pass_len); memcpy(combined + pass_len, user->name, user_len); if (!pg_sm3_hash(combined, pass_len + user_len, step1_hex)) { free(combined); return false; } free(combined); src = step1_hex; } break; case PASSWORD_TYPE_SM3: // 直接使用存储的SM3哈希值 if (strlen(user->passwd) < 3 + SM3_DIGEST_LENGTH * 2) { slog_error(server, "invalid SM3 password format"); return false; } src = user->passwd + 3; // 跳过"sm3"前缀 break; default: slog_error(server, "cannot do SM3 authentication: wrong password type"); kill_pool_logins(server->pool, "server login failed: wrong password type"); return false; } /* 第二步: 计算 sm3(hex_hash + salt) */ char step2_input[SM3_DIGEST_LENGTH * 2 + SM3_SALT_LENGTH + 1]; memcpy(step2_input, src, SM3_DIGEST_LENGTH * 2); memcpy(step2_input + SM3_DIGEST_LENGTH * 2, (char*)salt, SM3_SALT_LENGTH); // 计算最终哈希 char final_hash[SM3_DIGEST_LENGTH * 2 + 1]; if (!pg_sm3_hash(step2_input, SM3_DIGEST_LENGTH * 2 + SM3_SALT_LENGTH, final_hash)) { return false; } // 构造 "sm3" + hex_hash 格式 memcpy(txt, "sm3", 3); memcpy(txt + 3, final_hash, SM3_DIGEST_LENGTH * 2); txt[3 + SM3_DIGEST_LENGTH * 2] = '\0'; return send_password(server, txt); }
最新发布
07-18
根据上次回复, pgbouncer/include/util.h 里做了调整: #define MD5_PASSWD_LEN 35 #define SM3_PASSWD_LEN 83 // (3 + SM3_SALT_LENGTH*2 + SM3_DIGEST_LENGTH*2) pgbouncer/src/client.c 里做了调整: bool validate_sm3_password(const char *passwd) { if (strlen(passwd) != SM3_PASSWD_LEN) return false; if (strncmp(passwd, "sm3", 3) != 0) return false; const char *hash_part = passwd + 3; for (int i = 0; i < 64; i++) { if (!isxdigit(hash_part[i])) return false; } return true; } static bool check_client_passwd(PgSocket *client, const char *passwd) { char md5[MD5_PASSWD_LEN + 1]; PgUser *user = client->auth_user; int auth_type = client->client_auth_type; /* disallow empty passwords */ if (!*passwd || !*user->passwd) return false; switch (auth_type) { case AUTH_PLAIN: switch (get_password_type(user->passwd)) { case PASSWORD_TYPE_PLAINTEXT: return strcmp(user->passwd, passwd) == 0; case PASSWORD_TYPE_MD5: pg_md5_encrypt(passwd, user->name, strlen(user->name), md5); return strcmp(user->passwd, md5) == 0; case PASSWORD_TYPE_SCRAM_SHA_256: return scram_verify_plain_password(client, user->name, passwd, user->passwd); case PASSWORD_TYPE_SM3: { char calc_buf[SM3_DIGEST_LENGTH*2 + 4]; // "sm3" + 64位哈希 // 生成带前缀的哈希 ("sm3...") if (!pg_sm3_encrypt(passwd, "", 0, calc_buf, sizeof(calc_buf))) { return false; } // 直接比较完整字符串(包含"sm3"前缀) return strcmp(user->passwd, calc_buf) == 0; } default: return false; } case AUTH_MD5: if (strlen(passwd) != MD5_PASSWD_LEN) return false; if (get_password_type(user->passwd) == PASSWORD_TYPE_PLAINTEXT) pg_md5_encrypt(user->passwd, user->name, strlen(user->name), user->passwd); pg_md5_encrypt(user->passwd + 3, (char *)client->tmp_login_salt, 4, md5); return strcmp(md5, passwd) == 0; case AUTH_SM3: { if (!validate_sm3_password(user->passwd)) return false; // 提取存储密码中的盐和哈希(跳过"sm3"前缀) const char *stored_hex = user->passwd + 3; // 将十六进制字符串转换为二进制 uint8_t stored_bin[SM3_SALT_LENGTH + SM3_DIGEST_LENGTH]; // 40字节 if (!hex2bin(stored_hex, stored_bin, sizeof(stored_bin))) return false; uint8_t stored_salt[SM3_SALT_LENGTH]; uint8_t stored_hash[SM3_DIGEST_LENGTH]; memcpy(stored_salt, stored_bin, SM3_SALT_LENGTH); memcpy(stored_hash, stored_bin + SM3_SALT_LENGTH, SM3_DIGEST_LENGTH); char client_response_hex[SM3_DIGEST_LENGTH*2 + 4]; if (!pg_sm3_encrypt(passwd, (char*)client->tmp_login_salt, SM3_SALT_LENGTH, client_response_hex, sizeof(client_response_hex))) return false; uint8_t client_response_bin[SM3_DIGEST_LENGTH]; if (!hex2bin(client_response_hex + 3, client_response_bin, sizeof(client_response_bin))) return false; return pg_sm3_verify(stored_salt,client->tmp_login_salt,client_response_bin,stored_hash); } } return false; } 讲下正确性
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值