PHP加密函数输出长度由算法、密钥、填充和编码共同决定:md5()恒32字符,sha1()恒40,sha256()恒64;password_hash()用bcrypt时恒60字符,argon2id则96–120字符不等;openssl_encrypt()输出二进制,需base64或hex编码后才可安全测长,且须校验结构合法性。

PHP中常见加密函数输出长度规律
加密后的字符串长度不是随机的,而是由算法、密钥、填充方式和编码格式共同决定。直接用 strlen() 测长度没问题,但必须清楚底层逻辑,否则会误判“加密失败”或“数据截断”。
-
md5()固定输出 32 字符(十六进制),sha1()是 40 字符,sha256()是 64 字符 —— 这些是哈希,不可逆,且长度恒定 -
password_hash()使用bcrypt时默认输出 60 字符;改用argon2id则长度不固定(通常 96–120 字符),取决于参数 - 对称加密如
openssl_encrypt()输出的是二进制数据,若未用base64_encode()或bin2hex()编码,直接strlen()会出错(含 \0 字节)
检测加密字符串是否被意外截断
数据库字段太短、HTTP 参数截断、日志自动 truncation 都会导致加密串损坏。不能只看长度“是不是预期值”,还要验证结构合法性。
- 对
password_hash()输出,用password_get_info()检查是否返回有效数组,而非空或 false - 对 base64 编码的密文,先用
base64_decode($str, true)的 strict 模式解码,返回 false 说明格式非法(不只是长度不对) - 对 hex 字符串(如
bin2hex()结果),用ctype_xdigit()+strlen()双重校验:长度为偶数且全为 0-9a-f
openssl_encrypt() 后长度计算容易踩的坑
很多人以为 openssl_encrypt() 输出长度 = 明文长度 + 填充,实际还受 IV、模式、编码影响。
- 使用
CBC模式时,输出长度一定是 block size(如 AES-128 是 16 字节)的整数倍;原始明文 1 字节也会变成 16 字节 - 如果调用后直接
strlen(),得到的是二进制长度;若存数据库或传 API,大概率用了base64_encode(),此时长度 ≈ceil(密文字节数 * 4 / 3) - IV 不参与加密输出,但必须和密文一起保存;若只存密文而丢 IV,解密必然失败——这不是长度问题,但常被误认为“密文损坏”
写入前做长度防御性检查的实用代码
别等报错才处理,入库或序列化前主动拦截异常长度。
立即学习“PHP免费学习笔记(深入)”;
// 示例:校验 password_hash 输出
$hash = password_hash('123', PASSWORD_ARGON2ID);
if (empty($hash) || strlen($hash) < 96 || !password_get_info($hash)['algo']) {
throw new InvalidArgumentException('Invalid hash generated');
}
// 示例:校验 base64 编码的 openssl 密文
$ciphertext = base64_encode(openssl_encrypt($data, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv));
if (!base64_decode($ciphertext, true) || strlen($ciphertext) % 4 !== 0) {
throw new RuntimeException('Ciphertext corrupted or improperly encoded');
}
真正麻烦的不是长度本身,而是不同环节对“长度”的理解不一致:数据库 varchar(255) 存的是字符数,但 base64 编码后每 4 字符对应 3 字节原始密文——这个换算关系,漏掉一次就可能让整个加密链路失效。











