
BCRYPT哈希(特别是PHP password_hash() 生成的)仅由固定31个ASCII字符组成:$、.、/、0–9、A–Z、a–z,共31个字符,不包含等号、空格、Unicode或任意其他ASCII符号。
bcrypt哈希(特别是php password_hash() 生成的)仅由固定31个ascii字符组成:$、.、/、0–9、a–z、a–z,共31个字符,不包含等号、空格、unicode或任意其他ascii符号。
在实际开发中,若需对BCRYPT哈希字符串进行清洗(例如从用户输入、日志片段或富文本中提取有效哈希),必须严格依据其规范字符集设计正则表达式——而非依赖经验观察或模糊猜测。根据PHP官方文档对 crypt() 函数中 CRYPT_BLOWFISH 的明确定义:
“Blowfish hashing with a salt as follows:
"$2a$","$2x$", or"$2y$", a two-digit cost parameter,"$", and 22 characters from the alphabet"./0-9A-Za-z".”
这意味着一个标准的PHP BCRYPT哈希(如 $2y$10$9vXQVqR7JkLmNpO1rStUvWxYzAbCdEfGhIjKlMnOpQrStUvWxYzAbC)整体结构为:
- 前缀:
$2a$/$2x$/$2y$(共4字符) - 成本因子:两位十进制数(如
10、12)+后续$(共3字符) - Salt:22字符,严格来自字符集
./0-9A-Za-z - Hash:31字符,同样严格来自同一字符集
./0-9A-Za-z
✅ 因此,整个BCRYPT哈希字符串(含前缀、成本、salt与hash)仅可能包含以下31个ASCII可打印字符:
$ ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
注意:$ 出现在固定位置(前缀分隔符和成本后分隔符),而 . 和 / 仅出现在base64-like编码的salt/hash主体中——它们是Blowfish自定义Base64编码表的一部分(非标准RFC 4648 Base64),该编码明确排除 +、=、_、- 等所有其他符号。
? 正确的清洗正则表达式(PHP示例):
// 保留且仅保留BCRYPT合法字符,移除所有干扰内容
$cleaned = preg_replace('/[^$\.\/0-9A-Za-z]/', '', $input);
// 注意:此操作不验证格式合法性,仅做字符过滤;后续仍需用 password_verify() 校验有效性⚠️ 重要提醒:
- 不要使用
\w或[a-zA-Z0-9]——它们遗漏.、/、$,会导致截断; - 不要假定哈希以字母开头——
$是必需起始符,.和/在salt/hash中高频出现; - PHP不同版本对
$2x$/$2y$支持有差异,但字符集始终不变; - 此规则适用于所有符合OpenBSD Blowfish规范的BCRYPT实现(包括PHP、bcrypt.js、py-bcrypt),与语言绑定无关。
综上,BCRYPT哈希是高度受限的ASCII字符串,其确定性字符集是安全解析、存储和传输的前提。坚持使用 [$\.\/0-9A-Za-z] 进行清洗,即可稳健应对各类脏数据场景。

















