什么是PHP的输出长度crypt()?
md5()输出是128位并产生一个包含32个字符的字符串,所以在数据库中你将它放在一char(32)列中,那么crypt()?
首先,上下文:我正在尝试创建一个需要登录的基于命令行的工具(Linux).此工具的帐户与系统级帐户无关 - 这些帐户都不会查看/ etc/passwd.
我打算使用与/ etc/passwd相同的格式(大致)将用户帐户存储在文本文件中.
尽管没有使用系统级密码文件,但使用crypt似乎是一种很好的做法,而不是以明文形式存储密码.(虽然crypt肯定比以明文形式存储密码更好,但我对其他方式持开放态度.)
我的隐藏知识基于此:https: //docs.python.org/2/library/crypt.html
文档似乎要求一些不可能的东西:"建议在检查密码时使用完整的加密密码作为盐."
咦?如果我正在创建加密密码(如在创建用户记录时),我如何使用加密密码作为盐?它还不存在.(我假设你必须使用相同的盐来创建和检查密码.)
我曾尝试使用明文密码作为盐.这确实有效,但有两个问题; 一个容易克服,一个严重:
1)明文密码的前两个字母包含在加密密码中.您可以通过不将前两个字符写入文件来解决此问题:
user_record = '%s:%s:%s' % (user_name, crypted_pw[2:], user_type)
Run Code Online (Sandbox Code Playgroud)
2)通过使用明文密码作为salt,您似乎可以减少系统中的熵量.可能我误解了盐的目的.
我能够推导出的最佳实践是使用用户名中的前两个字符作为salt.这是否合适,或者是否有一些我错过的东西让这个行动变得糟糕?
我对盐的理解是它可以防止从字典中预先计算密码哈希值.我可以为所有密码使用标准盐(例如我的首字母缩写,"JS"),但对于攻击者而言,这似乎比使用每个用户的用户名中的两个字符要少.
我想我在这里丢失了我的弹珠......我的网站上有一个问题,它随机停止接受登录.我现在能够将它跟踪到crypt()表现得非常奇怪.
在我的数据库中,我已经获得了用户密码的加密版本 - 所以让我们说Og12345678.
当用户登录时,他们输入他们的密码,我从数据库中读取盐然后加密他们输入的内容并进行比较 - 通常这种方法非常有效.
所以我正在做crypt($ enteredPassword,$ saltFromDb) - 在这种情况下,盐当然是Og.通常对于给定用户,密码crypt工作正常.
当出现问题时(并且当他们重新启动Apache时,他们这样做是永久性的更改)我发现crypt开始为相同的输入使用相同的盐返回一个不同的答案.
然而,它是一致的,即一旦系统出错,crypt将返回错误的答案,但它始终返回相同的错误答案.重复刷新页面显示相同的输出.同样的盐在新的不正确的隐藏结果中也是明显的,所以并不是盐在某处丢失了.
如果我然后重新启动Apache并重新运行脚本而没有任何更改,那么来自crypt的结果将返回到应该如何.
我很欣赏它不是最新的PHP(5.2.8),但会重视任何观点,包括它是否是在更高版本中修复的已知错误(升级PHP并不是一个快乐的任务,其中许多网站仍然使用不幸的怪癖,每次升级都需要重新测试 - 如果它是一个已知的固定bug,那么很明显我会尽快升级它,除此之外,将外部资源外包可能更容易,因为我只在一个地方使用它我网站的常见地方.
任何输入赞赏.
马特佩德莱斯登
---更新:2011年3月11日
以前给出的关于操作系统的评论的更正... - 操作系统是Windows Server 2008 SP1 64位.道歉我应该仔细检查,而不是假设我记得!该机是戴尔2950 8gb Ram,Xeon处理器.
我开始考虑Krtek所建议的 - 当系统变得不稳定时,如果我生成新的crypt()(即一个非常简单的例子,我将变量设置为字符串,加密它然后与地穴进行比较) - 一切都很棒.当我重新启动服务器时,它再次回到之前的计算中.所以我肯定倾向于改变用于计算crypt()结果的算法 ...对可能导致这种情况发生的原因的任何想法?我打印出CRYPT_STD_DES等的值,它们在重新启动之间不会改变.
任何人都有可能导致这种情况发生的线索?
无论它在昨天的某一天似乎发生了两次,最奇怪的是.
谢谢你到目前为止的答案.
---更新:2011年3月16日
只是想提供另一个更新.
这仍然在发生,仍然没有进一步了解原因.
如果将来有人遇到这种情况,我认为我的解决方案将是做一些讨厌的黑客将所有crypt()执行推送到外部C#应用程序并且不再依赖PHP来执行它们.某处出现问题,此时我能看到的唯一解决办法是将其从等式中完全删除.
当然,如果它仍然发生,那也将是有趣的!:)
谢谢大家.
我一直在研究,但我一无所知.我知道MD5可以同时包含数字和字母但是如果我发现MD5只有数字或只有字母的情况下它会破坏我的脚本
可能重复:
使用PHP加密和解密密码的最佳方式?
我最近用PHP做了很多事情,想要建立我的第一个登录/注册系统.因此,我一直在网上做很多阅读,以找出实现这一目标的最佳方法.我遇到了几个指南,我对几个实例感到困惑,在开始这条路之前我想确定一下.
我的问题是我究竟如何使用河豚?我已经读过如果提供适当的盐,crypt()将自动选择河豚.如果是这样的话,是什么让盐河豚适合?
现在,我有一个脚本,它从日期和时间中取出一个盐,一个随机数,然后哈希为盐.那是否可以与河豚一起使用?
我正在学习PHP的crypt()函数,并且已经用它运行了一些测试.根据这篇文章,我应该使用长度为22个字符的盐.但是,我可以使用长度为23个字符的字符串,但有一些限制.当我使用22个字符长的字符串时,我总是得到'$ 2y $ xxStringStringStringStri.HashHashHashHashHashHashHashHas'的结果.我知道这个时期只是盐的一部分.
似乎如果我使用23个字符而不是22个字符,我可以成功生成不同的哈希值,但所有64个字符只有4种不同的结果.第23个字符"向下舍入"到64字符字母表中最接近的1/4(例如,第23个字符为"W"并向下舍入为"O"或任何数字向下舍入为"u")
v---------------v---------------v---------------v---------------
./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890
Run Code Online (Sandbox Code Playgroud)
所有这四个crypt函数都生成相同的salt:
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAq');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAr');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAs');
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAt');
Run Code Online (Sandbox Code Playgroud)
但这个是不同的:
crypt('Test123','$2y$09$AAAAAAAAAAAAAAAAAAAAAu');
Run Code Online (Sandbox Code Playgroud)
那么为什么我不能使用第23个字符才能成功产生不同的结果呢?在PHP中是否存在一些应该通过不使用它来避免的错误行为?
为了澄清我如何计算盐中的第23个字符:
crypt('Test123','$2y$08$ABCDEFGHIJKLMNOPQRSTUV');
// The salt is '$ABCDEFGHIJKLMNOPQRSTUV'
// Which will be treated as '$ABCDEFGHIJKLMNOPQRSTUO'
Run Code Online (Sandbox Code Playgroud) 不确定这是否可行,但我希望能够以字符串开头,然后找出输入必须输入的内容crypt才能获得此字符串.
或者也许这是不可能的,无论如何,这将是事情的全部目的?
是的,代码中有一个盐,我正在尝试这个.
我正在使用下面的代码,我在网络的某个地方找到了,当我尝试构建它时,我收到了一个错误.编译还可以.
这是错误:
/tmp/ccCnp11F.o: In function `main':
crypt.c:(.text+0xf1): undefined reference to `crypt'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
这是代码:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <crypt.h>
int main()
{
unsigned long seed[2];
char salt[] = "$1$........";
const char *const seedchars =
"./0123456789ABCDEFGHIJKLMNOPQRST"
"UVWXYZabcdefghijklmnopqrstuvwxyz";
char *password;
int i;
/* Generate a (not very) random seed.
You should do it better than this... */
seed[0] = time(NULL);
seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
/* Turn it into printable characters …Run Code Online (Sandbox Code Playgroud) 可能重复:
PHP密码的安全散列和盐
我正在建立一个网站,我需要一个安全的算法来存储密码.我第一次想到bcrypt,但后来发现我的主机不支持它,我无法更改主机.
我的主机允许这种加密:
而这些哈希:
那么,你们中的任何人都能用这个和一个盐来修复一个好的算法吗?
PHP中的这行代码求值为true
echo '$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2' == crypt("enter-new-password",'$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2');
Run Code Online (Sandbox Code Playgroud)
我需要的是Golang中的crypt函数,它也将评估为true.
ATTEMPT 1
我尝试了这个,但它评估为false:
import "github.com/nyarla/go-crypt"
log.Println("$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2" == crypt.Crypt("enter-new-password","$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2"))
Run Code Online (Sandbox Code Playgroud)
ATTEMPT 2
我还尝试定义和使用我在其他地方找到的这个crypt函数,但它也返回false:
package main
import (
"fmt"
"unsafe"
)
// #cgo LDFLAGS: -lcrypt
// #define _GNU_SOURCE
// #include <crypt.h>
// #include <stdlib.h>
import "C"
// crypt wraps C library crypt_r
func crypt(key, salt string) string {
data := C.struct_crypt_data{}
ckey := C.CString(key)
csalt := C.CString(salt)
out := C.GoString(C.crypt_r(ckey, csalt, &data))
C.free(unsafe.Pointer(ckey))
C.free(unsafe.Pointer(csalt))
return out
}
Run Code Online (Sandbox Code Playgroud)
尝试3
我也试过这个,但它似乎没有支持CRYPT_BLOWFISH,这是旧的PHP5.3及更早版本所使用的:
所以我的问题是:
我如何获得一个golang地穴功能完全一样的琴弦的PHP crypt函数enter-new-password和$2a$09$f5561d2634fb28a969f2dO8QeQ70f4bjCnF/.GvPpjj.8jgmtzZP2?