简介在互联网发展史上,安全一直是开发者非常重视的话题。为了实现数据传输安全,我们需要保证:数据来源(非伪造请求)、数据完整性(未修改)、数据隐私(密文,不能直接读取)等。虽然已经有HTTPS协议实现通过SSL/TLS协议,因为依赖于客户端浏览器的正确实现,效率很低,所以一般的敏感数据(比如交易支付信息等)还是需要我们使用加密的方式手动加密。虽然对于一般的WEB开发者来说,没有必要对一些安全相关的底层技术有很深的了解,但是学习加密的基础知识和使用现有的加密相关工具是很有必要的。由于工作需要,自己阅读了一些加密相关的文章,结合自己的经验完成了这篇文章。加密基础知识在学习如何使用加密之前,我们需要了解一些与加密相关的基础知识。加密算法一般分为两种:对称加密算法和非对称加密算法。对称加密对称加密算法是消息的发送方和接收方使用相同的密钥,发送方用密钥加密文件,接收方使用相同的密钥解密得到信息。常见的对称加密算法包括:des/aes/3des。对称加密算法的特点是:速度快,加密前后文件大小变化不大,但密钥存储是个大问题,因为无论是消息发送方还是接收方,如果密钥丢失,信息传输就会变得不安全。非对称加密和对称加密的对立面是非对称加密。非对称加密的核心思想是使用一对相对的密钥,分为公钥和私钥。私钥自己安全保管,公钥公开。公钥和私钥是一对。如果数据是用公钥加密的,则只能用对应的私钥解密;如果数据是用私钥加密的,就只能用对应的公钥解密。发送数据前,只需要用接收方的公钥加密即可。常见的非对称加密算法有RSA/DSA:非对称加密虽然没有密钥存储问题,但计算量大,加密速度慢。有时我们需要以块为单位对大块数据进行加密。为了保证数据的完整性,数字签名还需要通过哈希函数计算出一个哈希值,这个哈希值称为数字签名。它的特点是:无论原始数据有多大,结果的长度都是一样的;输入相同,输出也相同;输入的微小变化会导致结果的巨大变化;加密过程不可逆,无法通过哈希值得到原始值数据;常见的数字签名算法有md5、hash1等算法。PHP的openssl扩展openssl扩展使用openssl加密扩展包,里面封装了一些与加解密相关的PHP函数,极大的方便了数据的加解密。常用的函数有:对称加密相关stringopenssl_encrypt(string$data,string$method,string$password)其中$data为要加密的数据,$method为加密使用的方法,$password为密钥待使用,函数返回加密后的数据;$method列表可以使用openssl_get_cipher_methods()获取,我们选择其中一个来使用,$method列表的形式为:Array(0=>aes-128-cbc,//aesencryption1=>des-ecb,//desencryption2=>des-ede3,//3desencryption...)其解密函数为stringopenssl_encrypt(string$data,string$method,string$password)与非对称加密相关openssl_get_publickey();openssl_pkey_get_public();//从证书中导出公钥;openssl_get_privatekey();openssl_pkey_get_private();//从证书中导出私钥;他们都只需要传入证书文件(通常是.pem文件);openssl_public_encrypt(string$data,string&$crypted,mixed$key[,int$padding=OPENSSL\_PKCS1\_PADDING])使用公钥加密数据,其中$data为要加密的数据;$crypted是一个引用变量,加密后的数据会被放入这个变量中;$key为要导入的公钥数据;因为加密数据分组时,可能不正好是加密位数的整数倍,所以需要$padding(填充和填充),需要$padding选项有OPENSSL_PKCS1_PADDING,OPENSSL_NO_PADDING,分别为PKCS1填充,或不填充使用填充;与此方法相反(传入参数相同):openssl_private_encrypt();//使用私钥加密;打开ssl_private_decrypt();//使用私钥解密;openssl_public_decrypt();//使用公钥解密;签名和验证函数boolopenssl_sign(string$data,string&$signature,mixed$priv_key_id[,mixed$signature_alg=OPENSSL_ALGO_SHA1])intopenssl_verify(string$data,string$signature,mixed$pub_key_id[,mixed$signature_alg=OPENSSL_ALGO_SHA1])签名函数:$data为待签名的数据;$signature为签名结果的引用变量;$priv_key_id用于签名私钥;$signature_alg为签名要使用的算法,其算法列表可以通过openssl_get_md_methods()获取,如:array(0=>MD5,1=>SHA1,2=>SHA256,...)signature验证函数:与签名函数相反,只是需要传入私钥对应的公钥;result为签名校验结果,1表示成功,0表示失败,-1表示错误;下面是一个使用非对称加密的加密小例子://获取公钥$pub_key=openssl_get_publickey('test.pem');$encrypted='';//以块为单位加密数据for($offset=0,$length=strlen($raw_msg);$offset<$length;$offset+=$key_size){$encryptedBlock='';$data=substr($raw_msg,$offset,$key_size)if(!openssl_public_encrypt($data,$encryptedBlock,$pub_key,OPENSSL_PKCS1_PADDING)){返回'';}别的{$encrypted.=$encryptedBlock;}返回$encrypted;对称加密很简单,直接使用ssl_encrypt()函数即可;当然,有些接口可能对加密方式有不同的要求,比如padding不同,加密块大小等,这些都需要用户自行调整。因为我们在HTTP协议上处理数据,数据加密完成后,可以直接发送,不用考虑底层传输。使用cURL或SOAP扩展方法,您可以直接请求接口。结束语密码学是一门非常高深的学科,理论难度大,概念繁多。作为Web开发者,虽然我们不需要去研究它的底层实现,但是学会使用封装的方法对我们的开发是非常有好处的。即使了解了它的基本实现,也可以举一反三,对算法有新的认识。
