您的位置:首页 > 其它

L 关键数据加密,包含用户登陆注册

2017-03-08 11:26 393 查看
http://pan.baidu.com/s/1jHGXpGE 主流的高加密方案phpass

1. MD5加密

不需要引入任何文件,但是容易被破解,对于安全要求高的程序不能只用md5加密。

/**
* MD5加密操作
* @param string $str 原始字符串
* @param bool $raw_output 可选  被设置为 TRUE,以16字节长度的原始二进制格式返回,不进行加密。
* @return string 返回加密后的字符串
*/
string md5 ( string $str [, bool $raw_output = false ] )


这是一种不可逆加密,执行如下的代码

$password = '123456';
echo md5($password);


得到结果是e10adc3949ba59abbe56e057f20f883e

2. Crype加密

/**
* Crype加密操作
* @param string $str 原始字符串
* @param string $salt 可选的盐值字符串。如果没有提供,算法行为将由不同的算法实现决定,并可能导致不可预料的结束。
* @return string 返回一个基于标准 UNIX DES 算法或系统上其他可用的替代算法的散列字符串。
*/
string crypt ( string $str [, string $salt ] )


这是也一种不可逆加密,执行如下的代码

$password = '123456';
$salt = "test";// 只取前两个
echo crypt($password, $salt);


得到的结果是teMGKvBPcptKo

使用自动盐值的例子如下:

$password = crypt('mypassword'); // 自动生成盐值

/* 你应当使用 crypt() 得到的完整结果作为盐值进行密码校验,以此来避免使用不同散列算法导致的问题。(如上所述,基于标准 DES 算法的密码散列使用 2 字符盐值,但是基于 MD5 算法的散列使用 12 个字符盐值。)*/
if (crypt('mypassword', $password) == $password) {
echo "Password verified!";
}

执行结果是输出 Password verified!

以不同散列类型使用 crypt()的例子如下:

if (CRYPT_STD_DES == 1) {
echo 'Standard DES: ' . crypt(<
4000
span class="hljs-string">'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: 1rasmuslerISCgZzpwk3UhDidwXvin0Blowfish:2a07usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi

SHA-256: 5rounds=5000usesomesillystriKqJWpanXZHKq2BOB43TSaYhEWsQ1Lr5QNyPCDH/Tp.6

SHA-512: 6rounds=5000usesomesillystriD4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21

在 crypt() 函数支持多重散列的系统上,下面的常量根据相应的类型是否可用被设置为 0 或 1:

CRYPT_STD_DES – 基于标准 DES 算法的散列使用 “./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() 失败。

CRYPT_SHA256 – SHA-256 算法使用一个以 5 开头的 16 字符字符串盐值进行散列。如果盐值字符串以 “rounds=$” 开头,N 的数字值将被用来指定散列循环的执行次数,这点很像 Blowfish 算法的 cost 参数。默认的循环次数是 5000,最小是 1000,最大是 999,999,999。超出这个范围的 N 将会被转换为最接近的值。

CRYPT_SHA512 – SHA-512 算法使用一个以 6 开头的 16 字符字符串盐值进行散列。如果盐值字符串以 “rounds=$” 开头,N 的数字值将被用来指定散列循环的执行次数,这点很像 Blowfish 算法的 cost 参数。默认的循环次数是 5000,最小是 1000,最大是 999,999,999。超出这个范围的 N 将会被转换为最接近的值

3. SHA1加密

/**
* Crype加密操作
* @param string $str 原始字符串
* @param string $raw_output 如果可选的 raw_output 参数被设置为 TRUE,那么 sha1 摘要将以 20 字符长度的原始格式返回,否则返回值是一个 40 字符长度的十六进制数字。
* @return string 加密后的字符串。
*/
string sha1 ( string $str [, bool $raw_output = false ] )


这是也一种不可逆加密,执行如下代码:

$password = '123456';
echo sha1($password);


得到的结果是7c4a8d09ca3762af61e59520943dc26494f8941b

以上几种虽然是不可逆加密,但是也可以根据查字典的方式去解密。如下的地址中就提供了可以将上面的加密结果解密出来的功能。

所以不能简单的仅仅使用一种加密算法,加密越复杂,被破解出的可能性就越小。

4. URL加密

string urlencode (string $str)


此函数便于将字符串编码并将其用于 URL 的请求部分,同时它还便于将变量传递给下一页。

返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。由于历史原因,此编码在将空格编码为加号(+)方面与 RFC1738 编码不同。

string urldecode (string $str)

解码给出的已编码字符串中的任何 %##。 加号(’+’)被解码成一个空格字符。

这是一种可逆加密,urlencode方法用于加密,urldecode方法用于解密,执行如下代码:

$url = 'http://www.zmit.cn';
$encodeUrl = urlencode($url);
echo $encodeUrl . "\n";// 如果是在网页上展示的,就将\n修改为
echo urldecode($encodeUrl);


得到的结果如下

http%3A%2F%2Fwww.zmit.cn%2F

http://www.zmit.cn

5. Base64信息编码加密

/**
* Base64加密操作
* @param string $data 原始字符串
* @return string 加密后的字符串。
*/
string base64_encode (string $data)


使用 base64 对 data 进行编码。

设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输,例如电子邮件的主体。

Base64-encoded 数据要比原始数据多占用 33% 左右的空间。

/**
* Base64解密操作
* @param string $data 编码过的数据
* @param string $strict 如果输入的数据超出了 base64 字母表,则返回 FALSE。
* @return string 加密后的字符串。
*/
string base64_decode ( string $data [, bool $strict = false ] )


对 base64 编码的 data 进行解码。

执行如下代码:

$name = 'CraryPrimitiveMan';
$encodeName = base64_encode($name);
echo $encodeName . "\n";
echo base64_decode($encodeName);


其结果如下

Q3JhcnlQcmltaXRpdmVNYW4=

CraryPrimitiveMan

6.推荐phpass

经 phpass 0.3 测试,在存入数据库之前进行哈希保护用户密码的标准方式。 许多常用的哈希算法如 md5,甚至是 sha1 对于密码存储都是不安全的, 因为骇客能够使用那些算法轻而易举地破解密码。

对密码进行哈希最安全的方法是使用 bcrypt 算法。开源的 phpass 库以一个易于使用的类来提供该功能。

<?php
//包含防止sql注入以及用户名密码判断的注册、登录、修改密码
require '../PasswordHash.php';

// In a real application, these should be in a config file instead
$db_host = '127.0.0.1';
$db_port = 3306;
$db_user = 'mydbuser';
$db_pass = 'voulDyu0gue$s?';
$db_name = 'myapp';

// Base-2 logarithm of the iteration count used for password stretching
$hash_cost_log2 = 8;
// Do we require the hashes to be portable to older systems (less secure)?
$hash_portable = FALSE;

// Are we debugging this code?  If enabled, OK to leak server setup details.
$debug = TRUE;

function fail($pub, $pvt = '')
{
global $debug;
$msg = $pub;
if ($debug && $pvt !== '')
$msg .= ": $pvt";
/* The $pvt debugging messages may contain characters that would need to be
* quoted if we were producing HTML output, like we would be in a real app,
* but we're using text/plain here.  Also, $debug is meant to be disabled on
* a "production install" to avoid leaking server setup details. */
exit("An error occurred ($msg).\n");
}

function get_post_var($var)
{
$val = $_POST[$var];
if (get_magic_quotes_gpc())
$val = stripslashes($val); //去除提交的字段的斜杠,防止sql注入
return $val;
}

header('Content-Type: text/plain');

$op = $_POST['op'];
if ($op !== 'new' && $op !== 'login' && $op !== 'change')  //限制请求类型为注册、登录、改密码,如果不是新建与登陆请求则拒绝
fail('Unknown request');

$user = get_post_var('user');
/* 用户完整性检查,不能只依靠预处理sql,防止sql注入 */
if (!preg_match('/^[a-zA-Z0-9_]{1,60}$/', $user))
fail('Invalid username');

$pass = get_post_var('pass');
/* 为了节省cpu使用,我们这里设置长度上限为72 */
if (strlen($pass) > 72)
fail('The supplied password is too long');

$db = new mysqli($db_host, $db_user, $db_pass, $db_name, $db_port);
if (mysqli_connect_errno())
fail('MySQL connect', mysqli_connect_error());

$hasher = new PasswordHash($hash_cost_log2, $hash_portable);

if ($op === 'new') {                           //如果是新建用户则insert
$hash = $hasher->HashPassword($pass);
if (strlen($hash) < 20)                        //长度过小则判断为加密失败
fail('Failed to hash new password');
unset($hasher);								//加密完成后释放$hasher

($stmt = $db->prepare('insert into users (user, pass) values (?, ?)'))
|| fail('MySQL prepare', $db->error);
$stmt->bind_param('ss', $user, $hash)
|| fail('MySQL bind_param', $db->error);
if (!$stmt->execute()) {
/* 查询插入失败的原因,可能是用户名已经被占用。
* 从查询语句能够更准确方便地得到提示。 如果我们支持多种数据库就要从代码中找到出错原因。
* 然而我们大部分使用的是mysql */
if ($db->errno === 1062 /* ER_DUP_ENTRY */)    //1062字段值重复错误
fail('This username is already taken');
else
fail('MySQL execute', $db->error);
}

$what = 'User created';
} else {                                            //登录与修改都需要查询数据库,所以以下代码共用
$hash = '*'; // In case the user is not found
($stmt = $db->prepare('select pass from users where user=?'))
|| fail('MySQL prepare', $db->error);
$stmt->bind_param('s', $user)
|| fail('MySQL bind_param', $db->error);
$stmt->execute()
|| fail('MySQL execute', $db->error);
$stmt->bind_result($hash)
|| fail('MySQL bind_result', $db->error);
if (!$stmt->fetch() && $db->errno)
fail('MySQL fetch', $db->error);

if ($hasher->CheckPassword($pass, $hash)) {
$what = 'Authentication succeeded';
} else {
$what = 'Authentication failed';
$op = 'fail'; // Definitely not 'change'
}

if ($op === 'change') {                    //===是包括变量值与类型完全相等,而==只是比较两个数的值是否相等。
$stmt->close();

$newpass = get_post_var('newpass');
if (strlen($newpass) > 72)
fail('The new password is too long');
$hash = $hasher->HashPassword($newpass);
if (strlen($hash) < 20)
fail('Failed to hash new password');
unset($hasher);

($stmt = $db->prepare('update users set pass=? where user=?'))
|| fail('MySQL prepare', $db->error);
$stmt->bind_param('ss', $hash, $user)
|| fail('MySQL bind_param', $db->error);
$stmt->execute()
|| fail('MySQL execute', $db->error);

$what = 'Password changed';
}

unset($hasher);
}

$stmt->close();
$db->close();

echo "$what\n";

?>


phpass 在 HashPassword() 函数中已经对你的密码“加盐”了,这意味着你不需要自己“加盐”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: