crypt 单向字符串散列
发表日期:2021-07-01 10:23:21 | 来源: | | 浏览(1355) 分类:字符串 函数
crypt
(PHP 4, PHP 5, PHP 7, PHP 8)
crypt — 单向字符串散列
说明
$str
, string $salt
= ?): stringcrypt() 返回一个基于标准 UNIX DES 算法或系统上其他可用的替代算法的散列字符串。
salt
参数是可选的。然而,如果没有salt
的话,crypt()创建出来的会是弱密码。 php 5.6及之后的版本会在没有它的情况下抛出一个 E_NOTICE 级别的错误。为了更好的安全性,请确保指定一个足够强度的盐值。
password_hash()使用了一个强的哈希算法,来产生足够强的盐值,并且会自动进行合适的轮次。password_hash()是crypt()的一个简单封装,并且完全与现有的密码哈希兼容。推荐使用password_hash()。
有些系统支持不止一种散列类型。实际上,有时候,基于 MD5 的算法被用来替代基于标准 DES 的算法。这种散列类型由盐值参数触发。在 5.3 之前,PHP 在安装时根据系统的 crypt() 决定可用的算法。如果没有提供盐值,PHP 将自动生成一个 2 个字符(DES)或者 12 个字符(MD5)的盐值 ,这取决于 MD5 crypt() 的可用性。PHP 设置了一个名为 CRYPT_SALT_LENGTH
的常量,用来表示可用散列允许的最长可用盐值。
基于标准 DES 算法的 crypt() 在输出内容的开始位置返回两个字符的盐值。它也只使用 str
的开始 8 个字符,所以更长的以相同 8 个字符开始的字符串也将生成相同的结果(当使用了相同的盐值时)。
在 crypt() 函数支持多重散列的系统上,下面的常量根据相应的类型是否可用被设置为 0 或 1:
-
CRYPT_STD_DES
- 基于标准 DES 算法的散列使用 "./0-9A-Za-z" 字符中的两个字符作为盐值。在盐值中使用非法的字符将导致 crypt() 失败。 -
CRYPT_EXT_DES
- 扩展的基于 DES 算法的散列。其盐值为 9 个字符的字符串,由 1 个下划线后面跟着 4 字节循环次数和 4 字节盐值组成。它们被编码成可打印字符,每个字符 6 位,有效位最少的优先。0 到 63 被编码为 "./0-9A-Za-z"。在盐值中使用非法的字符将导致 crypt() 失败。 -
CRYPT_MD5
- MD5 散列使用一个以 $1$ 开始的 12 字符的字符串盐值。 -
CRYPT_BLOWFISH
- Blowfish 算法使用如下盐值:“$2a$”,一个两位 cost 参数,“$” 以及 64 位由 “./0-9A-Za-z” 中的字符组合而成的字符串。在盐值中使用此范围之外的字符将导致 crypt() 返回一个空字符串。两位 cost 参数是循环次数以 2 为底的对数,它的范围是 04-31,超出这个范围将导致 crypt() 失败。 PHP 5.3.7 之前只支持 “$2a$” 作为盐值的前缀,PHP 5.3.7 开始引入了新的前缀来修正一个在Blowfish实现上的安全风险。可以参考» this document来了解关于这个修复的更多信息。总而言之,开发者如果仅针对 PHP 5.3.7及之后版本进行开发,那应该使用 “$2y$” 而非 “$2a$” -
CRYPT_SHA256
- SHA-256 算法使用一个以 $5$ 开头的 16 字符字符串盐值进行散列。如果盐值字符串以 “rounds=<N>$” 开头,N 的数字值将被用来指定散列循环的执行次数,这点很像 Blowfish 算法的 cost 参数。默认的循环次数是 5000,最小是 1000,最大是 999,999,999。超出这个范围的 N 将会被转换为最接近的值。 -
CRYPT_SHA512
- SHA-512 算法使用一个以 $6$ 开头的 16 字符字符串盐值进行散列。如果盐值字符串以 “rounds=<N>$” 开头,N 的数字值将被用来指定散列循环的执行次数,这点很像 Blowfish 算法的 cost 参数。默认的循环次数是 5000,最小是 1000,最大是 999,999,999。超出这个范围的 N 将会被转换为最接近的值。
注意:
从 PHP 5.3.0 起,PHP 包含了它自己的实现,并将在系统缺乏相应算法支持的时候使用它自己的实现。
参数
-
str
-
待散列的字符串。
警告使用
CRYPT_BLOWFISH
算法将导致str
被裁剪为一个最长72个字符的字符串。 -
salt
-
可选的盐值字符串。如果没有提供,算法行为将由不同的算法实现决定,并可能导致不可预料的结束。
返回值
返回散列后的字符串或一个少于 13 字符的字符串,从而保证在失败时与盐值区分开来。
当校验密码时,应该使用一个不容易被时间攻击的字符串比较函数来比较crypt()的输出与之前已知的哈希。出于这个目的,PHP5.6开始提供了hash_equals()。
更新日志
版本 | 说明 |
---|---|
5.6.5 |
When the failure string "*0" is given as the
salt , "*1" will now be returned for consistency
with other crypt implementations. Prior to this version, PHP 5.6 would
incorrectly return a DES hash.
|
5.6.0 |
Raise E_NOTICE security warning if salt is omitted.
|
5.5.21 |
When the failure string "*0" is given as the
salt , "*1" will now be returned for consistency
with other crypt implementations. Prior to this version, PHP 5.5 (and
earlier branches) would incorrectly return a DES hash.
|
5.3.7 |
Added $2x$ and $2y$ Blowfish
modes to deal with potential high-bit attacks.
|
5.3.2 | 基于 Ulrich Drepper 的» 实现,新增基于 SHA-256 算法和 SHA-512 算法的 crypt。 |
5.3.2 | 修正了 Blowfish 算法由于非法循环导致的问题,返回“失败”字符串(“*0” 或 “*1”)而不是转而使用 DES 算法。 |
5.3.0 | PHP 现在包含了它自己的 MD5 Crypt 实现,包括标准 DES 算法,扩展的 DES 算法以及 Blowfish 算法。如果系统缺乏相应的实现,那么 PHP 将使用它自己的实现。 |
范例
示例 #1 crypt() 范例
<?php $hashed_password = crypt('mypassword'); // 自动生成盐值/* 你应当使用 crypt() 得到的完整结果作为盐值进行密码校验,以此来避免使用不同散列算法导致的问题。(如上所述,基于标准 DES 算法的密码散列使用 2 字符盐值,但是基于 MD5 算法的散列使用 12 个字符盐值。)*/ if (hash_equals($hashed_password, crypt($user_input, $hashed_password))) { echo "Password verified!"; } ?>
示例 #2 利用 htpasswd 进行 crypt() 加密
<?php // 设置密码$password = 'mypassword'; // 获取散列值,使用自动盐值$hash = crypt($password); ?>
示例 #3 以不同散列类型使用 crypt()
<?php if (CRYPT_STD_DES == 1) { echo 'Standard DES: ' . crypt('rasmuslerdorf', 'rl') . "\n"; } if (CRYPT_EXT_DES == 1) { echo 'Extended DES: ' . crypt('rasmuslerdorf', '_J9..rasm') . "\n"; } if (CRYPT_MD5 == 1) { echo 'MD5: ' . crypt('rasmuslerdorf', '$1$rasmusle$') . "\n"; } if (CRYPT_BLOWFISH == 1) { echo 'Blowfish: ' . crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$') . "\n"; } if (CRYPT_SHA256 == 1) { echo 'SHA-256: ' . crypt('rasmuslerdorf', '$5$rounds=5000$usesomesillystringforsalt$') . "\n"; } if (CRYPT_SHA512 == 1) { echo 'SHA-512: ' . crypt('rasmuslerdorf', '$6$rounds=5000$usesomesillystringforsalt$') . "\n"; } ?>
以上例程的输出类似于:
Standard DES: rl.3StKT.4T8M Extended DES: _J9..rasmBYk8r9AiWNc MD5: $1$rasmusle$rISCgZzpwk3UhDidwXvin0 Blowfish: $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi SHA-256: $5$rounds=5000$usesomesillystri$KqJWpanXZHKq2BOB43TSaYhEWsQ1Lr5QNyPCDH/Tp.6 SHA-512: $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21
注释
注意: 由于 crypt() 使用的是单向算法,因此不存在 decrypt 函数。
参见
- hash_equals() - 可防止时序攻击的字符串比较
- password_hash() - 创建密码的散列(hash)
- md5() - 计算字符串的 MD5 散列值
- Mcrypt 扩展
- 更多关于 crypt 函数的信息,请阅读 Unix man 页面
- PHP(0)
- PHP杂项(34)
- PHP基础-李炎恢系列课程(20)
- 中文函数手册(0)
- 错误处理 函数(13)
- OPcache 函数(6)
- PHP 选项/信息 函数(54)
- Zip 函数(10)
- Hash 函数(15)
- OpenSSL 函数(63)
- Date/Time 函数(51)
- 目录函数(9)
- Fileinfo 函数(6)
- iconv 函数(11)
- 文件系统函数(81)
- 多字节字符串 函数(57)
- GD 和图像处理 函数(114)
- 可交换图像信息(5)
- Math 函数(50)
- 程序执行函数(11)
- PCNTL 函数(23)
- JSON 函数(4)
- SPL 函数(15)
- URL 函数(10)
- cURL 函数(32)
- 网络 函数(33)
- FTP 函数(36)
- Session 函数(23)
- PCRE 函数(11)
- PCRE 正则语法(19)
- 数组 函数(81)
- 类/对象 函数(18)
- 函数处理 函数(13)
- 变量处理 函数(37)
- SimpleXML 函数(3)
- 杂项 函数(31)
- 字符串 函数(101)
- addcslashes 以 C 语言风格使用反斜线转义字符串中的字符(0)
- addslashes 使用反斜线引用字符串(0)
- bin2hex 函数把包含数据的二进制字符串转换为十六进制值(0)
- chop rtrim() 的别名(0)
- chr 返回指定的字符(0)
- chunk_split 将字符串分割成小块(0)
- convert_cyr_string 将字符由一种 Cyrillic 字符转换成另一种(0)
- convert_uudecode 解码一个 uuencode 编码的字符串(0)
- convert_uuencode 使用 uuencode 编码一个字符串(0)
- count_chars 返回字符串所用字符的信息(0)
- crc32 计算一个字符串的 crc32 多项式(0)
- crypt 单向字符串散列(0)
- echo 输出一个或多个字符串(0)
- explode 使用一个字符串分割另一个字符串(0)
- fprintf 将格式化后的字符串写入到流(0)
- get_html_translation_table 返回使用 htmlspecialchars() 和 htmlentities() 后的转换表(0)
- hebrev 将逻辑顺序希伯来文(logical-Hebrew)转换为视觉顺序希伯来文(visual-Hebrew)(0)
- hebrevc 将逻辑顺序希伯来文(logical-Hebrew)转换为视觉顺序希伯来文(visual-Hebrew),并且转换换行符(0)
- hex2bin 转换十六进制字符串为二进制字符串(0)
- html_entity_decode Convert HTML entities to their corresponding characters(0)
- htmlentities 将字符转换为 HTML 转义字符(0)
- htmlspecialchars_decode 将特殊的 HTML 实体转换回普通字符(0)
- htmlspecialchars 将特殊字符转换为 HTML 实体(0)
- implode 将一个一维数组的值转化为字符串(0)
- join 别名 implode()(0)
- lcfirst 使一个字符串的第一个字符小写(0)
- levenshtein 计算两个字符串之间的编辑距离(0)
- localeconv Get numeric formatting information(0)
- ltrim 删除字符串开头的空白字符(或其他字符)(0)
- md5_file 计算指定文件的 MD5 散列值(0)
- md5 计算字符串的 MD5 散列值(0)
- metaphone Calculate the metaphone key of a string(0)
- money_format 将数字格式化成货币字符串(0)
- nl_langinfo Query language and locale information(0)
- nl2br 在字符串所有新行之前插入 HTML 换行标记(0)
- number_format 以千位分隔符方式格式化一个数字(0)
- ord 转换字符串第一个字节为 0-255 之间的值(0)
- parse_str 将字符串解析成多个变量(0)
- print 输出字符串(0)
- printf 输出格式化字符串(0)
- quoted_printable_decode 将 quoted-printable 字符串转换为 8-bit 字符串(0)
- quoted_printable_encode 将 8-bit 字符串转换成 quoted-printable 字符串(0)
- quotemeta 转义元字符集(0)
- rtrim 删除字符串末端的空白字符(或者其他字符)(0)
- setlocale 设置地区信息(0)
- sha1_file 计算文件的 sha1 散列值(0)
- sha1 计算字符串的 sha1 散列值(0)
- similar_text 计算两个字符串的相似度(0)
- soundex Calculate the soundex key of a string(0)
- sprintf 返回格式化字符串(0)
- sscanf 根据指定格式解析输入的字符(0)
- str_contains Determine if a string contains a given substring(0)
- str_ends_with Checks if a string ends with a given substring(0)
- str_getcsv 解析 CSV 字符串为一个数组(0)
- str_ireplace str_replace() 的忽略大小写版本(0)
- str_pad 使用另一个字符串填充字符串为指定长度(0)
- str_repeat 重复一个字符串(0)
- str_replace 子字符串替换(0)
- str_rot13 对字符串执行 ROT13 转换(0)
- str_shuffle 随机打乱一个字符串(0)
- str_split 将字符串转换为数组(0)
- str_starts_with Checks if a string starts with a given substring(0)
- str_word_count 返回字符串中单词的使用情况(0)
- strcasecmp 二进制安全比较字符串(不区分大小写)(0)
- strchr 别名 strstr()(0)
- strcmp 二进制安全字符串比较(0)
- strcoll 基于区域设置的字符串比较(0)
- strcspn 获取不匹配遮罩的起始子字符串的长度(0)
- strip_tags 从字符串中去除 HTML 和 PHP 标记(0)
- stripcslashes 反引用一个使用 addcslashes() 转义的字符串(0)
- stripos 查找字符串首次出现的位置(不区分大小写)(0)
- stripslashes 反引用一个引用字符串(0)
- stristr strstr() 函数的忽略大小写版本(0)
- strlen 获取字符串长度(0)
- strnatcasecmp 使用“自然顺序”算法比较字符串(不区分大小写)(0)
- strnatcmp 使用自然排序算法比较字符串(0)
- strncasecmp 二进制安全比较字符串开头的若干个字符(不区分大小写)(0)
- strncmp 二进制安全比较字符串开头的若干个字符(0)
- strpbrk 在字符串中查找一组字符的任何一个字符(0)
- strpos 查找字符串首次出现的位置(0)
- strrchr 查找指定字符在字符串中的最后一次出现(0)
- strrev 反转字符串(0)
- strripos 计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)(0)
- strrpos 计算指定字符串在目标字符串中最后一次出现的位置(0)
- strspn 计算字符串中全部字符都存在于指定字符集合中的第一段子串的长度。(0)
- strstr 查找字符串的首次出现(0)
- strtok 标记分割字符串(0)
- strtolower 将字符串转化为小写(0)
- strtoupper 将字符串转化为大写(0)
- strtr 转换指定字符(0)
- substr_compare 二进制安全比较字符串(从偏移位置比较指定长度)(0)
- substr_count 计算字串出现的次数(0)
- substr_replace 替换字符串的子串(0)
- substr 返回字符串的子串(0)
- trim 去除字符串首尾处的空白字符(或者其他字符)(0)
- ucfirst 将字符串的首字母转换为大写(0)
- ucwords 将字符串中每个单词的首字母转换为大写(0)
- vfprintf 将格式化字符串写入流(0)
- vprintf 输出格式化字符串(0)
- vsprintf 返回格式化字符串(0)
- wordwrap 打断字符串为指定数量的字串(0)