查看原文
其他

网络安全之加密算法

计算机与网络安全 计算机与网络安全 2022-06-01

一次性进群,长期免费索取教程,没有付费教程。

教程列表见微信公众号底部菜单

进微信群回复公众号:微信群;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

【推荐书籍】

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存