网络安全之加密算法
一次性进群,长期免费索取教程,没有付费教程。
教程列表见微信公众号底部菜单
进微信群回复公众号:微信群;QQ群:16004488
微信公众号:计算机与网络安全
ID:Computer-network
加密是指将明文直接可见的数据以特定的算法进行混淆,以保证数据的安全掩蔽性。加密一直是一个很热的话题,在密码学中占很大一块比例,目前常见的加密算法可以分为对称加密、非对称加密以及单向加密(哈希算法),这些加密算法大量运用在各种系统和应用中,最常见的是我们访问使用HTTPS的网站流量是经过加密的,密码保存在网站数据库中大多也是经过MD5或者DES加密,而通常不推荐使用可逆的加密算法来加密保存用户登录密码,因为黑客在拿到密钥的情况下可对数据进行还原。下面我们来看看常用的加解密算法的实现方式。
一、对称加密
对称加密指的是采用单密钥进行加密,并且该密钥可以对数据进行加密和解密处理,目前这类加密算法安全性均比较高,数据的实际安全性取决于密钥的管理,就算黑客拿到加密后的数据,如果没有密钥,这些数据对于黑客来说也是垃圾数据而已,而拿到密钥之后可以对加密数据进行还原,所以不建议使用对称加密对用户密码进行加密存储。它的原理比较简单,如下图所示。
明文数据123456可以在加密算法的作用下使用密钥0s9ansk2处理后变成d2fm83jjf,同样使用这个密钥也能把d2fm83jjf解密回123456。
在对称加密算法中常用的算法有DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。
1、3DES加密
DES(Data Encrypt Standard)又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密。DES加密算法是美国的一种由来已久的加密标准,这种算法通常用于加密需要传输的数据。
PHP中需要在php.ini中打开php_mcrypt.dll以及php_mcrypt_filter.dll两个lib库的引用,即去掉以下代码前面的分号:
;extension=php_mcrypt.dll
;extension=php_mcrypt_filter.dll
PHP的3DES已经有很简洁成熟的加密,我们来看一个简单的3DES加解密类,代码如下:
<?php
class Crypt3Des {public $key = "xxxx";
//加密密钥
function Crypt3Des($key)
{
$this->key=$key;
}
//加密函数
function encrypt($input)
{
$size = mcrypt_get_block_size(MCRYPT_3DES,'ecb');
$input = $this->pkcs5_pad($input,$size);
$key = str_pad($this->key,24,'0');
$td = mcrypt_module_open(MCRYPT_3DES,'','ecb','');
$iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_RAND);
@mcrypt_generic_init($td,$key,$iv);
$data = mcrypt_generic($td,$input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
//解密函数
function decrypt($encrypted)
{
$encrypted = base64_decode($encrypted);
$key = str_pad($this->key,24,'0');
$td = mcrypt_module_open(MCRYPT_3DES,'','ecb','');
$iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_RAND);
$ks = mcrypt_enc_get_key_size($td);
@mcrypt_generic_init($td,$key,$iv);
$decrypted = mdecrypt_generic($td,$encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$y=$this->pkcs5_unpad($decrypted);
return $y;
}
function pkcs5_pad($text,$blocksize)
{
$pad = $blocksize -(strlen($text)% $blocksize);
return $text . str_repeat(chr($pad),$pad);
}
function pkcs5_unpad($text)
{
$pad = ord($text{strlen($text)-1});
if($pad > strlen($text))
{
return false;
}
if(strspn($text,chr($pad),strlen($text)- $pad)!= $pad)
{
return false;
}
return substr($text,,-1 * $pad);
}
function PaddingPKCS7($data)
{
$block_size = mcrypt_get_block_size(MCRYPT_3DES,MCRYPT_MODE_CBC);
$padding_char = $block_size -(strlen($data)% $block_size);
$data .= str_repeat(chr($padding_char),$padding_char);
return $data;
}
}
?>
使用方法很简单,只要实例化这个类,直接调用相应函数即可,如下所示:
$rep=new Crypt3Des('加密key');
$input="hello 3des";
echo "原文:".$input."<br/>";
$encrypt_card=$rep->encrypt($input);
echo "加密:".$encrypt_card."<br/>";
echo "解密:".$rep->decrypt($rep->encrypt($input));
我们来看看经过它处理后的数据,如下图所示。
2、AES加密
AES(Advanced Encryption Standard)加密在密码学中又称Rijndael加密法,比3DES更加安全,密钥长度的最少支持为128、192、256位,所以逐渐替代原先的DES。
PHP中需要在php.ini中打开php_mcrypt.dll库的引用,设置方法我们已在前面介绍过,我们来看一个PHP中AES的加解密实例:
<?php
class Aes{public $_secrect_key='';
//密钥
function Aes($key)
{
$this->_secrect_key = $key;
}
/***加密方法* @param string $str* @return string*/
function encrypt($str)
{
//AES,128 ECB模式加密数据
$screct_key = $this->_secrect_key;
$screct_key = base64_decode($screct_key);
$str = trim($str);
$str = $this->addPKCS7Padding($str);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_ECB),MCRYPT_RAND);
$encrypt_str = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$screct_key,$str,MCRYPT_MODE_ECB,$iv);
return base64_encode($encrypt_str);
}
/***解密方法* @param string $str* @return string*/
function decrypt($str)
{
//AES,128 ECB模式加密数据
$screct_key = $this->_secrect_key;
$str = base64_decode($str);
$screct_key = base64_decode($screct_key);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_ECB),MCRYPT_RAND);
$encrypt_str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$screct_key,$str,MCRYPT_MODE_ECB,$iv);
$encrypt_str = trim($encrypt_str);
$encrypt_str = $this->stripPKSC7Padding($encrypt_str);
return $encrypt_str;
}
/***填充算法* @param string $source* @return string*/
function addPKCS7Padding($source)
{
$source = trim($source);
$block = mcrypt_get_block_size('rijndael-128','ecb');
$pad = $block -(strlen($source)% $block);
if($pad <= $block)
{
$char = chr($pad);
$source .= str_repeat($char,$pad);
}
return $source;
}
/***移去填充算法* @param string $source* @return string*/
function stripPKSC7Padding($source)
{
$source = trim($source);
$char = substr($source,-1);
$num = ord($char);
if($num==62)
return $source;
$source = substr($source,,-$num);
return $source;
}
}
这个加密类使用起来也相当简单:
$rep=new Aes('xxxx');
$input="hello aes";
echo "原文:".$input."<br/>";
$encrypt_card=$rep->encrypt($input);
echo "加密:".$encrypt_card."<br/>";
echo "解密:".$rep->decrypt($rep->encrypt($input));
我们来看看使用它加解密后的效果,如下图所示。
二、非对称加密
非对称加密与对称加密不一样的地方在于,非对称加密算法有两个密钥,分别为公钥和私钥,它的安全性比对称加密更好,公钥用来加密,私钥用来解密,如果用公钥对数据进行加密,只有用对应的私钥才能解密,两个密钥不一致,所以叫非对称加密。
它的使用流程原理如下图所示。
RSA加密
RSA公钥加密算法在1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出,RSA正是他们三人的姓氏开头字母拼接。RSA是目前公认最有影响力的加密算法,不过并不是不可破解的,在短密钥的情况下,基于现在越来越强大的云计算,也存在被爆破的可能。早在1999年,就有花了五个月时间在一台有3.2G中央内存的Cray C916计算机上成功分解RSA-155(512位)。
RSA的最大问题在于加解密速度慢,整个运算过程相对要消耗不少时间,不过这一些问题在今后计算资源横向扩展的条件下,也不是很大的问题。
我们来测试一下PHP下的RSA加解密,如果希望简单一点,PHP上可以使用phpseclib,下载地址http://phpseclib.sourceforge.net/,不需要配置即可直接使用,首先下载phpseclib,文件结构如下图所示。
然后生成密钥,代码如下:
<?php
include('./Crypt/RSA.php');
$rsa = new Crypt_RSA();
extract($rsa->createKey());
echo "$privatekey<br />$publickey";
生成密钥后,我们来看看加解密代码:
<?php
$PUBLIC_KEY ='-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm418GwRwXmYOC6eb6G6NzCMRtnan7Jt76kygfmfa2mGRu1Ff8t3bjyrrRPra8LQgcGxO1KZkDPxODsfX2fblXCNCzEXxYerZIrcQXR4utTMXkQCN7E7egNDlQOqrP0awFZ5OWrYcbDdmgxa2jAEGtR3Fam+GpAAH94H1crvcbSwIDAQAB-----END PUBLIC KEY-----';
$PRIVATE_KEY = '-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQCm418GwRwXmYOC6eb6G6NzCMRtnan7Jt76kygfmfa2mGRu1Ff8t3bjyrrRPra8LQgcGxO1KZkDPxODsfX2fblXCNCzEXxYerZIrcQXR4utTMXkQCN7E7egNDlQOqrP0awFZ5OWrYcbDdmgxa2jAEGtR3Fam+GpAAH94H1crvcbSwIDAQABAoGBAKYm+RTgbfeQ/z33Yd7gZXrB387Cidlied0/ZVMRFm/0iQlOn8sbXWKtFBH/Pi9bJhfVXWmgYJa61dLn+tnNkhdYsWCHxN3eMlLJ8XuQjvmrofWb1yZtWVblGhbdO9fSX2RH8m7DOxrV85/oP0qYTKfla8R21hKmdgo9JDeqMRUBAkEA2ZLqpnqXJ2qpFE3OHnQydnJQllAG7l1egYheQh0JmeI8CVrWjv40sK5clQK6kONj9JscD0ZPdCqqEVQb5dSWtQJBAMRc0hzEVpgo544lSIZV1sMiWwxVhDLpvuEUJZtSLh52FIt07Rt7mVV0IExq7Z2bDX1yhHiqYPen7ck0GC0KKf8CQCTp3zPVkrWWTA9sz+6syi78YB3QgAyK/NC/QTa4VHuuPX9c0RA7otbjDkQdzWdtnPTQKCeTR0GvR2FfQshwlA0CQGCZzWALkxI+JVQ/sUMtHX9X+nTB6Uxmw9nU4H9d2YRw0MCeoDsB/jgU7gLKI+WCLwvE97ipERUlDw0JzM7zjh8CQEz541yxg7sttBtEV2RZOd+8bMBaRJWXYqN86vn+dSjqds4vY6KgESImQ7Y+o30TcgxgjGZlujZMLgqv9E4VmwY=-----END RSA PRIVATE KEY-----';
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey($PUBLIC_KEY);
//载入公钥
$plaintext = 'phpsec';
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$ciphertext = $rsa->encrypt($plaintext);
$rsa->loadKey($PRIVATE_KEY);
//载入私钥
echo $ciphertext.'<br />'.'<br />'.'<br />';
echo $rsa->decrypt($ciphertext);
可以看到$rsa->encrypt($plaintext);函数用来加密,最终用$rsa->decrypt($ciphertext)来解密并输出明文字符串“phpsec”,效果如下图所示。
第一行的乱码就是加密后的“phpsec”,通常保存的时候还会用Base64转码一下才好。
三、单向加密
前面我们介绍的加密算法都是双向的,也就是加密后可以再逆向算出明文数据,而在加密算法里面,还有单向加密,也就是不可逆算法,常见的有MD系列(md4、md5)和sha1等。因为存在不可逆的性质,所以这类哈希算法通常用来保存密码和做数字签名,不过因为相同的字符串的哈希值是一样的,所以存在碰撞的问题,目前全球公开的最大MD5解密库cmd5.com号称有24万亿条数据,解密率全球第一,在实际应用中也感受到普通人常用的密码破解成功率也在90%以上。
MD5/sha1加密
MD5是目前使用最多的密码存储加密算法,几乎95%以上的网站都在使用MD5算法,MD5分为16位和32位,实际上它们的安全性并没有什么不一样的地方。根据实际经验来看,用单纯MD5(不加salt)来存储用户密码是非常不安全的,提供MD5解密的网站随处可见,如cmd5.com、xmd5.com,等等。
在PHP中进行MD5计算很简单,PHP提供了md5()函数,只要传入一个字符串即可返回加密后的结果。
同样,sha1加密也被部分网站用来保存密码,它比MD5更长,足足有40位,支持sha1解密的网站相对较少,碰撞的数据量也相对较少,所以实际中它的“安全性”比MD5更好。我们来看看它的使用方法,代码如下:
<?php
echo 'phpsec md5:'.md5('phpsec');
echo '<br />';
echo 'phpsec sha1:'.sha1('phpsec');
执行结果如下图所示。
微信公众号:计算机与网络安全
ID:Computer-network
【推荐书籍】