面向普通人的php加密_普通人PHP加密

面向普通人的php加密

想一想当今世界与20年前的世界有何不同。 很久以前,在1980年代,加密只是间谍活动 -您在汤姆·克兰西(Tom Clancy)的技术惊悚片中读到了这些东西。 如果有人想保密一些信息,他可以使用密码,密码短语或其他基本方法对数据进行加密。

快速发展到今天,加密无处不在。 密码以加密方式存储在数据库中。 可以通过SSL,SSH和其他技术(更不用说虚拟专用网络)通过网络空间加密隧道。 人们每天都可以并且确实使用“相当好的隐私”(PGP)来保护其敏感文件和电子邮件。

作为PHP开发人员,您应该意识到,强大的安全性实践不仅适用于异国情调的应用程序,还适用于您现在正在从事的项目。 这种意识从行人(例如在登录页面的密码字段中未显示纯文本)到令人眼花of乱的密码方法(例如DES,MD5,SHA1,Blowfish)。

这里没有足够的时间或空间来讨论加密的各个方面,但是您将学到涵盖大多数情况的基本知识。我们首先概述了加密和解密信息的含义,其次是使用PHP的内置功能的一些涉及密码和其他数据的实际示例。 贯穿整个过程,将在更大的安全范围内讨论加密。 最后,还将介绍其他PHP扩展和插件。

密码学入门

密码术是“秘密写作”的艺术,正如该词的希腊语根源所证明的那样。 最早的也是最简单的加密形式之一是Caesar密码 ,它采用纯文本消息,将字母移动n个位,并产生密文。 例如:

  • 纯文本: Veni Vidi Vici
  • 密文: Xgpk Xkfk Xkek

通过检查密文,您可以使用一些启发式技巧来弄清楚明文已移了两个字符。 凯撒密码很容易破解。 例如:检查此消息,看看X重复很多, k也是如此。 确定多少个四个字母的单词具有这么多的元音成为一种猜谜游戏。 有了元音后,您便知道该如何移动其余字母。 如果您知道明文是拉丁文,但也能找到图片,这也将有所帮助。

现代加密技术使用的算法远不止字母和符号的均匀移位,其功能更加强大。 本文不涉及这些算法的详细介绍,但几乎所有PHP安装都将包含保持适度(或极其)安全的数据所需的所有内容。

没有100%不可破解的,完全验证的加密方法。 似乎每个月,一些黑客小孩和他的朋友将1000台计算机绑在一起,并在几天的原始,蛮横的计算打击中破解了最新的加密方法。 但是,您可以使您的系统和数据不透水,以使黑客甚至都不会试图闯入。他们会在其他地方寻找更容易的选择。

考虑到这一点,让我们进入一个由简单登录表单保护的示例PHP应用程序。

没有安全性或加密PHP表单处理

假设您是一名新的Web应用程序开发人员,并且没有太多机会尝试使用安全功能。 您已经创建了第一个应用程序,该应用程序将用户名和密码存储在专用的用户表中,但是尚未对这些密码进行加密。 他们坐在那里对访问您的数据库的任何人都是显而易见的。 您将建立一个如下所示的登录页面。

清单1.简单的登录页面
<form action="verify.php" method="post">
<p><label for='username'>Username</label>
<input type='text' name='user' id='username'/>
</p>

<p><label for='password'>Password</label>
<input type='text' name='password' id='password'/>
</p>
<p><input type="submit" name="submit" value="log in"/>
</p>
</form>

HTML标记有什么问题? 为密码字段选择的输入类型是text ,这意味着用户在该字段中键入的任何内容在屏幕上均显示为纯文本。

您可以轻松地将类型更改为password ,并将该字段中的用户输入替换为一系列星号。 基本的? 绝对。 但是,在比您想象的更多的应用程序中都忽略了这一步骤,而正是这些小事情使人们对安全性感到不舒服。 您会把钱存到大厅窗户破损的银行吗? 也许。 但是您希望银行得到良好的照顾。 您的应用程序也是如此。

让我们继续处理表单提交的verify.php文件。

清单2.简单PHP登录验证
<?php
	$user = $_POST['user'];
	$pw = $_POST['password'];
	
	$sql = "select user,password from users 
		where user='$user' 
		and password='$pw' 
		limit 1';
	$result = mysql_query($sql);
	
	if (mysql_num_rows($result)){
		//we have a match!
	}else{
		//no match
	}

?>

当您读到这篇文章时,你们中间的精明人士在笑。 那些正在等待本文加密部分的人可能会不耐烦,但是加密只是安全难题的一部分 。 您还必须对如何处理传入的用户数据保持头脑清醒。 developerWorks教程“锁定PHP应用程序”(请参阅参考资料 )讨论了SQL注入:将格式错误的数据发送到数据库以引起损害或不必要的访问的艺术。 不管您使用多少加密,将该漏洞打开都无济于事。

您应该遵循“永远不要信任用户提供的数据”和“深入防御”的旧安全性原则。 通过转义传入的字符串来清理传入的数据并保护数据库(请参见清单3)。 深度防御就是要采取冗余的安全措施-不仅加密,而且还要智能处理用户提供的数据。

清单3.保护PHP表单解析免受用户数据操作
<?php
	$user = strip_tags(substr($_POST['user'],0,32));
	$pw = strip_tags(substr($_POST['password'],0,32));
	
	$sql = "select user,password from users 
		where user='". mysql_real_escape_string($user)."' 
		and password='". mysql_real_escape_string($pw)."' 
		limit 1';
	$result = mysql_query($sql);
	
	if (mysql_num_rows($result)){
		//we have a match!
	}else{
		//no match
	}
?>

明智地使用strip_tags()substr()mysql_real_escape_string() ,您已经删除了所有可能有害的命令,将字符串缩减为32个字符,并对数据库可能解释为a的一部分的所有特殊字符进行了转义。非预期的命令字符串。

在此过程结束时,数据库中仍然有一个纯文本密码。 你不能忍受。 最简单的解决方法是使用PHP的内置crypt()函数。

使用crypt()

PHP的内置crypt()函数实现单向加密或单向哈希 。 这是一种单向方式,因为一旦加密了某些内容,就永远无法将其恢复为纯文本格式。 乍一看,这个想法似乎很荒谬。 关键是要保护信息,然后能够使用该信息,这通常意味着能够对其进行解密。

别失望 单向加密方案crypt()尤其是crypt()是保护信息的极为流行的安全方法。 如果您的用户密码列表落入不正确的人手中,那么实际上就不可能将其解密为纯文本。

让我们回到密码示例。 PHP符号应用程序可能包括一个模块,系统管理员可以使用该模块创建,编辑和删除用户。 例如,在将用户记录存储到用户表中之前,PHP脚本很可能使用crypt()来加密密码。

清单4.使用crypt()加密密码
<?php
	$user = strip_tags(substr($_POST['user'],0,32));
	$pw = strip_tags(substr($_POST['password'],0,32));
	
	$cleanpw = crypt($pw);
	
	$sql = "insert into users (username,password) 
	values('".mysql_real_escape_string($user)."',
	'".mysql_real_escape_string($cleanpw)."')";
	//.....etc....
?>

crypt()将一串明文作为第一个参数,对它施加盐以影响加密算法的随机性,并生成输入明文的单向密文。 如果不提供盐,PHP通常默认使用其系统盐,该盐可以是以下值和长度之一:

CRYPT_STD_DES 两个字符(默认)
CRYPT_EXT_DES 九个字符
CRYPT_MD5 12个字符,以$1$开头
CRYPT_BLOWFISH 16个字符,以$2$开头

许多现代PHP安装都使用MD5或更高版本的盐,这些盐使用强12个字符的盐,但并不理会任何事情。 您所使用的系统可能根本不使用任何东西,所以最好知道。 您可以使用以下PHP代码段检查服务器的设置:

<?php echo "System salt size: ". CRYPT_SALT_LENGTH; ?>

答案将返回2、9、12或16,告诉您正在使用什么。 要使用MD5或更高版本,可以在纯文本和盐参数中显式调用crypt()函数和md5()函数,以获取随机密文(请参见清单5)。 md5()函数对输入的任何字符串进行哈希处理,然后将其转换为32个字符的定长字符串。 根据您的安全要求和个人喜好,您可能更喜欢另一种方法。

清单5.使用crypt()和md5()加密密码
<?php
	$user = strip_tags(substr($_POST['user'],0,32));
	$pw = strip_tags(substr($_POST['password'],0,32));
	
	$cleanpw = crypt(md5($pw),md5($user));
	
	$sql = "insert into users (username,password) 
	values('".mysql_real_escape_string($user)."',
	'".mysql_real_escape_string($cleanpw)."')";
	//.....etc....
?>

现在,您在数据库中拥有一个加密的密码,但是无法对其进行解密。 这有什么用? 简便:对输入的用户提供的密码使用相同的加密方法,并将结果与​​您存储的密码进行比较。

清单6.重新访问verify.php
<?php
	$user = strip_tags(substr($_POST['user'],0,32));
	$pw = strip_tags(substr($_POST['password'],0,32));
	$cleanpw = crypt(md5($pw),md5($user));
	
	$sql = "select user,password from users 
		where user='". mysql_real_escape_string($user)."' 
		and password='". mysql_real_escape_string($cleanpw)."' 
		limit 1';
	$result = mysql_query($sql);
	
	if (mysql_num_rows($result)){
		//we have a match!
	}else{
		//no match
	}
?>

例如,如果存储的加密密码是i83Uw28jKzBrZF ,则对输入的密码进行加密并将其与存储的密码进行比较。 攻击者唯一可能破坏您的加密的方法是一次将很长的字符串列表与您的加密密码进行比较,一次比较一次,直到匹配为止。 这被称为字典攻击 ,这是为什么您的密码不应该是密码 ,星际迷航角色的名称甚至狗的名字的众多原因之一。 仅仅因为您加密Fido并使其变得乱码,并不意味着您的密码不受这种攻击。 确保您的密码具有一定长度(八个或更多字符),并且包含大写字母,数字和特殊字符,例如!! 和$-将使您的数据更难以猜测。 甚至f1D0! 在短期内,它是比GandalftheGray等更长的密码更好的密码,后者更长,使用小写字母, 并且是“指环王”中字符的名称。

使用crypt()的一种不太好的方法

还有另一种使用crypt()方法不太好:将纯文本的前n个字符用作盐。

清单7.将纯文本中的字符用作盐
<?php
	$user = strip_tags(substr($_POST['user'],0,32));
	$pw = strip_tags(substr($_POST['password'],0,32));
	$cleanpw =crypt($pw, substr($user,0,2));
	
	$sql = "select user,password from users 
		where user='". mysql_real_escape_string($user)."' 
		and password='". mysql_real_escape_string($cleanpw)."' 
		limit 1';
	$result = mysql_query($sql);
	
	if (mysql_num_rows($result)){
		//we have a match!
	}else{
		//no match
	}
?>

如果您的用户名是tmyer ,则盐会以tm开头,这会使某人更容易确定您的盐是什么。 这不是一个好主意。

用PHP进行加密和解密

本文大部分内容讨论了使用crypt()的单向加密。 但是,如果您想发送消息给某人并提供一种解密消息的方式怎么办? 使用PHP支持的公共密钥加密 。

公钥加密的用户具有私钥和公钥,并且他们与其他用户共享其公钥。 如果您想向您的朋友John Doe发送私人笔记,请使用John Doe的公共密钥(已存储在您自己的密钥环中)对该消息进行加密。 一旦John Doe收到消息,只有他才能使用自己的私钥解密消息。 任何给定用户的公钥和私钥在数学上都不相关。 使用PGP和其他公共密钥加密方法,无法从公共密钥推断出某人的私有密钥。

PGP的一个附加功能是私钥的密码实际上不是密码。 这是一个密码短语 。 它可以是一句话,包括标点符号,空格和各种形式的字符。

使用基于PGP的公钥加密的一种方法是使用GNU Privacy Guard(GPG)。 任何使用GPG加密的邮件都可以使用GPG,PGP或支持任何一个程序的任意数量的电子邮件客户端插件解密。 在该示例中,在线表单接受用户输入,包括消息。 使用GPG为特定收件人加密该邮件; 然后将其发送。

清单8.使用GPG
<?php
	//set up users
	$from = "webforms@example.com";
	$to = "you@example.com";
	
	//cut the message down to size, remove HTML tags
	$messagebody = strip_tags(substr($_POST['msg'],0,5000));
	$message_body = escapeshellarg($messagebody);
	
	$gpg_path = '/usr/local/bin/gpg';
	$home_dir = '/htdocs/www';
	$user_env = 'web';

	$cmd = "echo $message_body | HOME=$home_dir USER=$user_env $gpg_path" .
		"--quiet --no-secmem-warning --encrypt --sign --armor " .
		"--recipient $to --local-user $from";
	
	$message_body = `$cmd`;
	
	mail($to,'Message from Web Form', $message_body,"From:$from\r\n");

?>

在此示例中,PHP调用/ usr / local / bin / gpg(此位置在您的服务器上可能会有所不同),以使用发件人的私钥和收件人的公钥对消息进行加密。 实际上,只有收件人才能解密邮件,并且知道该邮件来自发件人。 此外,设置HOMEUSER环境变量会告诉GPG在哪里可以找到存储这些密钥的密钥环。 其他标志执行以下操作:

  • --quiet--no-secmem-warning禁止来自GPG的警告。
  • --encrypt执行加密。
  • --sign添加签名以验证发件人的身份。
  • --armor产生ASCII输出而不是二进制输出,因此可以很容易地通过电子邮件发送。

通常,如前所述,秘密密钥受密码短语保护。 该特定实例不使用密码,因为需要在每次提交表单时手动输入该密码。 当然,您还有其他选择,例如在单独的文件中提供密码短语或使用其自己的身份验证方案保护表单不被公共使用(例如,如果表单只能由公司的销售代表访问)。

还要注意,除非您在允许用户输入电子邮件的表单上使用SSL,否则键入的内容均为明文形式。 换句话说:客户端计算机和服务器之间的任何人都可以看到。 但是,这是另一个主题。

摘要

我已经对安全性,加密技术甚至公共密钥密码学做了足够的解释,以帮助您成功完成下一个PHP项目。 使用加密和其他加密方法的目的不是要创建一个100%的万无一失,不可破解的系统。 唯一绝对不能被黑客入侵的系统是一台已关闭的计算机,即使这也不是保证,因为有人可能会亲自走到该计算机上,将其打开并对其进行黑客攻击。 所有这些工作的目的是使获取敏感数据变得如此困难,以至于黑客甚至无法尝试,或者他们在几次尝试失败后继续前进。

在便利性和保护性之间的范围内,所有安全考虑都必须存在。 要求使用强大的算法密钥对所有内容进行单向加密,这意味着您的数据非常安全,但使用起来并不方便。 相反的情况也很糟糕-不使用任何加密-因为无论您多么方便,其他人也都非常方便地使用它。 通过加密重要的机密数据(例如密码,信用卡号和机密消息)并添加良好的安全措施(例如,深入防御,过滤用户提供的数据和普通的常识)来取得良好的平衡。


翻译自: https://www.ibm.com/developerworks/opensource/library/os-php-encrypt/index.html

面向普通人的php加密

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值