Php 散列一个密码,并将其和salt保存到mysql pdo utf8编码

Php 散列一个密码,并将其和salt保存到mysql pdo utf8编码,php,mysql,utf-8,pdo,Php,Mysql,Utf 8,Pdo,我有这个问题,请原谅,如果不合适,请在评论中告诉我,我会放弃它。事情是这样的: 我使用以下代码生成一个salt: $salt = mcrypt_create_iv(32); 密码是这样的: $password = hash('sha256', $_POST['password'] . $salt); $pdo = new PDO( 'mysql:host=hostname;dbname=defaultDbName', 'username', 'password' )

我有这个问题,请原谅,如果不合适,请在评论中告诉我,我会放弃它。事情是这样的: 我使用以下代码生成一个salt:

$salt = mcrypt_create_iv(32);
密码是这样的:

$password =  hash('sha256', $_POST['password'] . $salt);
$pdo = new PDO(
    'mysql:host=hostname;dbname=defaultDbName',
    'username',
    'password'
);
并将$salt和$password保存到MYSQL数据库中,到目前为止没有问题,如果我这样连接:

$password =  hash('sha256', $_POST['password'] . $salt);
$pdo = new PDO(
    'mysql:host=hostname;dbname=defaultDbName',
    'username',
    'password'
);
但如果我以另一种方式连接:

$pdo = new PDO(
    'mysql:host=hostname;dbname=defaultDbName;charset=utf8',
    'username',
    'password'
);
盐没有保存到数据库中,或使用错误的值和长度保存;除非我这样做: $salt=utf8_编码(mcrypt_创建_iv(32););
但我认为这是不对的,我的意思是为什么我应该编码,mcrypt_create_iv(32)和utf-8有什么问题

您的解决方案将起作用:

mcrypt\u create\u iv
返回一组字节,这些字节可以方便地放入字符串中。但由于它们可以有任何值,因此可能会导致错误的UTF-8序列
utf8\u encode
修复了这一问题,只要在从数据库读回后还记得使用
utf8\u decode
,就可以正常工作

如果您的连接不是utf8,那么每个字节都将被视为一个(完整的)ANSI字符,您不需要对其进行任何编码

最佳解决方案:保持二进制:

由于该数据实际上是二进制数据,而不是真正的字符串,因此二进制字段(binary、VARBINARY或BLOB)将是存储该数据的更好选择,以防止由于编码或解码而出现任何问题

BINARY
可能是最佳选择,因为此数据的长度既不可变,也不很大

备选方案:存储为实际文本,不带花哨字符:


另一种解决方案是使用将二进制数据转换为十六进制表示。字符串的长度将是原来的两倍,但它只包含字母和数字,并且可以安全地在任何类型的字符串字段中讲述故事。您可以使用hex2bin将其转换回来,因为其他海报提到mcrypt_create_iv可以生成utf8中不适合的字符。试着这样做:

function generate_random($length=16, $simple=false){
        $result='';
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()+=-_?~';
        if($simple)
            $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
        for ($i = 0; $i < $length; $i++)
            $result .= $chars[mt_rand(0, strlen($chars)-1)];
        return $result;
    }
函数生成随机($length=16,$simple=false){
$result='';
$chars='abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz1234567890!@$%^&*(+=-);
如果($simple)
$chars='abcdefghijklmnopqrstuvxyz1234567890';
对于($i=0;$i<$length;$i++)
$result.=$chars[mt_rand(0,strlen($chars)-1)];
返回$result;
}

字符集为78的16个字符产生1.877*10^30个组合。加上密码长度,对于像sha256这样的单向散列应该足够了。

好的,谢谢,我现在明白了,我也想问一下,用utf-8编码它是否没有安全问题?可能有。我会选择将此信息以原始二进制格式保存在
二进制
字段中。您的IV本质上是“随机”二进制垃圾。如果要将其放入text/varchar字段中,它将遵循该字段的字符集转换规则。二进制数据应该进入varbinary/blob字段。这两个字段都没有字符集,你在字段中输入的内容将是从字段中输出的内容。因此,将字段的tipe更改为blob将使连接的字符集变得不可知,这就是你所说的二进制/blob字段的意义所在。由于翻译规则的错误应用,没有字符集可以随机丢弃数据,而这些规则在一开始就不应该应用于数据。谢谢你的回答,这看起来像是DIY工作,没有括号的编码方式叫什么?