加密 解密
密码学最早可以追溯到古希腊罗马时代,那时的加密方法很简单:替换字母。
早期的密码学
古希腊人用一种叫 Scytale 的工具加密。更快的工具是 transposition cipher—:只是把羊皮纸卷在一根圆木上,写下信息,羊皮纸展开后,这些信息就加密完成了。
虽然很容易被解密,但它确实是第一个在现实中应用加密的例子
Julius Caesar 用了另外一个类似的加密方法:把字母往右或往左移动几位;此法称为Caesar’s cipher. 比如“GEEK” 加密后就是“JHHN”.
Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Cipher: DEFGHIJKLMNOPQRSTUVWXYZABC
因为只有信息接受者知道如何解密,对其他人来说,那就是一段无意义的信息了。
还有像如下图的加密方法:每个字母放在坐标系里
这样 “G”就是 “23”, “GEEK”就是 “23 31 31 43”.
Enigma Machine
加密算法
加密算法有很多种,区别和衡量他们的方法就是看他们是否容易被破解的程度和加密的速度
如下图可见AES 是最快的强加密算法
当然有更快或比较慢的算法了,他们都有用处。如果你只是加密一段信息,也不是经常需要,那你可以用最强的加密算法,甚至也可以用不同的算法加密两次。如果想要加密速度快点,那就用AES.
加密类型
之前说过的加密算法绝大部分都属于以下两种加密类型之一:
· 对称加密:加密解密用的是同样的“钥匙”
· 非对称加密:加密解密用的是不同的“钥匙”
对称加密
用邮局的例子来解释下对称加密
Alice 在盒子里放有信息,盒子上有挂锁,她有钥匙。通过邮局她把这个盒子寄给Bob。Bob收到盒子后,用相同的钥匙打开盒子(钥匙之前就得到了,可能是Alice面对面给他的)。然后Bob可以用同样的方法回复。
对称加密可以分为两种:一种是一个一个加密信息,另一种是分块加密信息,通常分为64位加密为一块。块 Twofish, Serpent, AES (Rijndael), Blowfish, CAST5, RC4, TDES, and IDEA.
非对称加密
Bob和Alice各有自己的盒子。Alice要跟Bob秘密通信,她先让Bob把开着的盒子通过邮局发给她。Alice拿到盒子后放入信息锁上,然后发给Bob。Bob就可以用他自己的钥匙打开了。回复的话就用同样的方法。
此法最大的好处是你不必得到对方的“钥匙”,以防别人在钥匙发送过程中偷偷复制钥匙,进而窃取信息。。而且就算Bob的钥匙被窃取复制了,Alice跟别人的通信也是安全的,因为Alice用的是别人的钥匙。
非对称算法在加密和解密时用的是不同的钥匙。信息接受者有两把钥匙:一把“公匙”,一把“私匙”。公匙是给信息发送者用来加密的,私匙是自己用来解密的
这样最大的好处是:不必通过不安全的渠道发送私密的东西。公匙本来就是给别人用的,不用藏好。你的私匙在你产生私匙的电脑里保存着
网站如何通过加密和用户安全通信
SSL (Secure Sockets Layer) 是用来保障你的浏览器和网站服务器之间安全通信,免受网络“中间人”窃取信息。
SSL原理很简单。当你的浏览器向服务器请求一个安全的网页(通常是 https://)
服务器就把它的证书和公匙发回来
浏览器检查证书是不是由可以信赖的机构颁发的,确认证书有效和此证书是此网站的。
使用公钥加密了一个随机对称密钥,包括加密的URL一起发送到服务器
服务器用自己的私匙解密了你发送的钥匙。然后用这把对称加密的钥匙给你请求的URL链接解密。
服务器用你发的对称钥匙给你请求的网页加密。你也有相同的钥匙就可以解密发回来的网页了
对称加密 :
<?php
header("content-type:text/html;charset=utf-8");
/**
* 简单对称加密算法之加密
* @param String $string 需要加密的字串
* @param String $skey 加密EKY
* @author Anyon Zou <zoujingli@qq.com>
* @date 2013-08-13 19:30
* @update 2014-10-10 10:10
* @return String
*/
function encode($string = '', $skey = 'cxphp') {
$strArr = str_split(base64_encode($string));
$strCount = count($strArr);
foreach (str_split($skey) as $key => $value)
$key < $strCount && $strArr[$key].=$value;
return str_replace(array('=', '+', '/'), array('O0O0O', 'o000o', 'oo00o'), join('', $strArr));
}
/**
* 简单对称加密算法之解密
* @param String $string 需要解密的字串
* @param String $skey 解密KEY
* @author Anyon Zou <zoujingli@qq.com>
* @date 2013-08-13 19:30
* @update 2014-10-10 10:10
* @return String
*/
function decode($string = '', $skey = 'cxphp') {
$strArr = str_split(str_replace(array('O0O0O', 'o000o', 'oo00o'), array('=', '+', '/'), $string), 2);
$strCount = count($strArr);
foreach (str_split($skey) as $key => $value)
$key <= $strCount && isset($strArr[$key]) && $strArr[$key][1] === $value && $strArr[$key] = $strArr[$key][0];
return base64_decode(join('', $strArr));
}
echo '<pre>';
$str = '56,15123365247,54,四大古典风格';
echo "string : " . $str . " <br />";
echo "encode : " . ($enstring = encode($str)) . '<br />';
echo "decode : " . decode($enstring);
die();
非对称加密:
<?php
header("content-type:text/html;charset=utf-8");
/**
* 使用openssl实现非对称加密
*
* @since 2015-11-10
*/
class Rsa
{
/**
* 私钥
*
*/
private $_privKey;
/**
* 公钥
*
*/
private $_pubKey;
/**
* 保存文件地址
*/
private $_keyPath;
/**
* 指定密钥文件地址
*
*/
public function __construct($path)
{
if (empty($path) || !is_dir($path)) {
throw new Exception('请指定密钥文件地址目录');
}
$this->_keyPath = $path;
}
/**
* 创建公钥和私钥
*
*/
public function createKey()
{
$config = [
"config" => 'E:\phpStudy\Apache\conf\openssl.cnf',
"digest_alg" => "sha512",
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
];
// 生成私钥
$rsa = openssl_pkey_new($config);
openssl_pkey_export($rsa, $privKey, NULL, $config);
file_put_contents($this->_keyPath . DIRECTORY_SEPARATOR . 'priv.key', $privKey);
$this->_privKey = openssl_pkey_get_public($privKey);
// 生成公钥
$rsaPri = openssl_pkey_get_details($rsa);
$pubKey = $rsaPri['key'];
file_put_contents($this->_keyPath . DIRECTORY_SEPARATOR . 'pub.key', $pubKey);
$this->_pubKey = openssl_pkey_get_public($pubKey);
}
/**
* 设置私钥
*
*/
public function setupPrivKey()
{
if (is_resource($this->_privKey)) {
return true;
}
$file = $this->_keyPath . DIRECTORY_SEPARATOR . 'priv.key';
$privKey = file_get_contents($file);
$this->_privKey = openssl_pkey_get_private($privKey);
return true;
}
/**
* 设置公钥
*
*/
public function setupPubKey()
{
if (is_resource($this->_pubKey)) {
return true;
}
$file = $this->_keyPath . DIRECTORY_SEPARATOR . 'pub.key';
$pubKey = file_get_contents($file);
$this->_pubKey = openssl_pkey_get_public($pubKey);
return true;
}
/**
* 用私钥加密
*
*/
public function privEncrypt($data)
{
if (!is_string($data)) {
return null;
}
$this->setupPrivKey();
$result = openssl_private_encrypt($data, $encrypted, $this->_privKey);
if ($result) {
return base64_encode($encrypted);
}
return null;
}
/**
* 私钥解密
*
*/
public function privDecrypt($encrypted)
{
if (!is_string($encrypted)) {
return null;
}
$this->setupPrivKey();
$encrypted = base64_decode($encrypted);
$result = openssl_private_decrypt($encrypted, $decrypted, $this->_privKey);
if ($result) {
return $decrypted;
}
return null;
}
/**
* 公钥加密
*
*/
public function pubEncrypt($data)
{
if (!is_string($data)) {
return null;
}
$this->setupPubKey();
$result = openssl_public_encrypt($data, $encrypted, $this->_pubKey);
if ($result) {
return base64_encode($encrypted);
}
return null;
}
/**
* 公钥解密
*
*/
public function pubDecrypt($crypted)
{
if (!is_string($crypted)) {
return null;
}
$this->setupPubKey();
$crypted = base64_decode($crypted);
$result = openssl_public_decrypt($crypted, $decrypted, $this->_pubKey);
if ($result) {
return $decrypted;
}
return null;
}
/**
* __destruct
*
*/
public function __destruct() {
@fclose($this->_privKey);
@fclose($this->_pubKey);
}
}
需要把$config 里的配置路径改为自己的openssl.cnf 所在的路径
?>
<?php
$rsa = new Rsa('ssl-key');
$rsa->createKey();
$rsa->setupPrivKey();
$rsa->setupPubKey();
//私钥加密,公钥解密
// echo "待加密数据:segmentfault.com\n";
// echo "<br>";
// $pre = $rsa->privEncrypt("segmentfault.com");
// echo "<br>";
// echo "加密后的密文:\n" . $pre . "\n";
// echo "<br>";
// $pud = $rsa->pubDecrypt($pre);
// echo "<br>";
// echo "解密后数据:" . $pud . "\n";
// echo "<br>";
//公钥加密,私钥解密
echo "待加密数据:segmentfault.com\n";
echo "<br>";
$pue = $rsa->pubEncrypt("segmentfault.com");
echo "<br>";
echo "加密后的密文:\n" . $pue . "\n";
echo "<br>";
$prd = $rsa->privDecrypt($pue);
echo "<br>";
echo "解密后数据:" . $prd;