标签归档:加密

Stunnel构建加密隧道

最新版本可到:http://www.stunnel.org/downloads.html下载,Stunnel工作过程就是在客户端和服务端之间建立一条加密通道,所有Stunnel有两个工作模式,默认工作模式是服务端,如果需要作为客户端,那么就是需要使用client=yes来指定。客户端加密数据需要一个证书(可以自签发),服务端需要私钥,以解密数据,这个工作过程就是HTTPS的工作流程。

一般使用yum或者apt-get安装即可。

##############################################
###
apt-get update
apt-get install openssl

###
apt-get install stunnel

#开机启动,ENABLED改为1
vi /etc/default/stunnel4
ENABLED=1

#
cd /etc/stunnel
vi stunnel.conf

[squid]
accept = 4041 
connect = 127.0.0.1:4040
cert = /etc/stunnel/stunnel.pem

#产生证书 私钥 - 实际就是产生一对RSA秘钥,公钥在证书中
openssl genrsa -out key.pem 2048
openssl req -new -x509 -key key.pem -out cert.pem -days 3650
cat key.pem cert.pem >> /etc/stunnel/stunnel.pem

#启动
/etc/init.d/stunnel4 restart


##############################################
## 客户端
client = yes
[squid]
accept = 127.0.0.1:4444
connect = [服务端IP]:4041
cert = D:/stunnel.pem

添加监控脚本:

cat stunnel.sh 
#!/bin/bash

live=`ps -efH | grep '/usr/bin/stunnel' | grep -v 'grep' | wc -l`
if [ $live -eq 0 ]; then
    /usr/bin/stunnel 2>&1 >> /dev/null
fi

Windows下下载一个GUI工具:
stunnel

默认Stunnel以服务器为工作模式,所以在作为客户端时务必添加client = yes。

对于客户端,可以开启多个端口,分别指向多个代理:

client = yes
cert= E:/var/stunnel.pem

[fq1]
accept = 4441
connect = 47.90.x.43:4041

[fq2]
accept = 4442
connect = 47.90.x.152:4041

[fq3]
accept = 4443
connect = 47.90.x.140:4041

[fq4]
accept = 4444
connect = 47.90.x.215:4041

Laravel 加解密详解

Laravel 中的加解密是PHP原生加解密扩展(OpenSSL,mcrypt)的简单封装。一个加解密类需要实现Illuminate\Contracts\Encryption\Encrypter接口:

namespace Illuminate\Contracts\Encryption;

interface Encrypter
{
    /**
     * Encrypt the given value.
     *
     * @param  string  $value
     * @return string
     */
    public function encrypt($value);

    /**
     * Decrypt the given value.
     *
     * @param  string  $payload
     * @return string
     */
    public function decrypt($payload);
}

对应加密 和 解密方法。除此,Laravel对加解密类提供了一个基类(抽象类,没有实现Illuminate\Contracts\Encryption\Encrypter接口,意味着最终的类可以继承这个类,并实现这个接口),这个类就不粘贴了,基本上,继承这个类的最终实现,在加密中携带解密需要的参数:

$data['iv'] = 
$data['value'] = 
$data['mac'] = 

这里的value就是密文,mac就是iv与value的签名。所以在解密时,需要验证这借个数据是存在的,并且通过mac验证密文的完整性。查看Illuminate\Encryption\Encrypter的encrypt方法的实现:

    public function encrypt($value)
    {
        $iv = Str::randomBytes($this->getIvSize());

        $value = openssl_encrypt(serialize($value), $this->cipher, $this->key, 0, $iv);

        if ($value === false) {
            throw new EncryptException('Could not encrypt the data.');
        }

        // Once we have the encrypted value we will go ahead base64_encode the input
        // vector and create the MAC for the encrypted value so we can verify its
        // authenticity. Then, we'll JSON encode the data in a "payload" array.
        $mac = $this->hash($iv = base64_encode($iv), $value);

        return base64_encode(json_encode(compact('iv', 'value', 'mac')));
    }

先随机获取iv,然后序列化明文,传递明文、加密算法、key、和$iv, 加密得到密文,然后组装一个有iv 密文 mac组成的数组,先json_encode后base64_encode。

最终,需要使用就仅仅两个方法,encrypt和decrypt(也是接口规定的两个方法)。不过这里需要注意,conf/app.php中的配置:

'key' => env('APP_KEY', 'SomeRandomString'),
'cipher' => 'AES-256-CBC',

如果需要使用AES-256-CBC,那么key必须是32个8bit的字符,AES-128-CBC对应的key是16位,因为这个方法限制:

    //Illuminate\Encryption\Encrypter
    public static function supported($key, $cipher)
    {
        $length = mb_strlen($key, '8bit');

        return ($cipher === 'AES-128-CBC' && $length === 16) || ($cipher === 'AES-256-CBC' && $length === 32);
    }

之所以有这个限制,那是因为这个加解密类使用open_ssl的原因。

然而,如果不符合这个要求,就会去实例化一个Illuminate\Encryption\McryptEncrypter(用到PHP的mcrypt扩展函数),它没有限制key的长度,原理上也类似,都是对称加密算法的实现。不过很明显,第一种使用open_ssl的方式是其推荐的方法。

以上所说的检测流程,是Illuminate\Encryption\EncryptionServiceProvider中提供的:

    public function register()
    {
        $this->app->singleton('encrypter', function ($app) {
            $config = $app->make('config')->get('app');

            $key = $config['key'];

            $cipher = $config['cipher'];

            if (Encrypter::supported($key, $cipher)) {
                return new Encrypter($key, $cipher);
            } elseif (McryptEncrypter::supported($key, $cipher)) {
                return new McryptEncrypter($key, $cipher);
            } else {
                throw new RuntimeException('No supported encrypter found. The cipher and / or key length are invalid.');
            }
        });
    }

全局用一个Facade对应了这个实例 — Crypt。系统内用到加解密的地方有cookie的数据加密,包括会话ID的加密(Laravel没有使用PHP的会话扩展)。

另外,需要知道,加解密有分对称和非对称加解密,这里提供的方法是对称加解密,不过是对称还是非对称,都是可逆的,而那些密码哈希,一般都是指单向不可逆的算法,跟这里说的加解密是两会事,密码哈希类,Lravel中提供了Hash Facade来操作这个(全局的bcrypt()方法)。

Laravel这里仅仅提供了对称加解密的实现,而实际可能用到非对称的加解密,所以只能说是它提供了够用的实现。类似Zend/Crypt组件就提供了相对比较丰富的实现。

PHP框架Phalcon 之 安全 加密解密

安全(Security)

This component aids the developer in common security tasks such as password hashing and Cross-Site Request Forgery protection (CSRF).
通用的安全任务比如密码哈希和跨站请求伪造保护(CSRF)

密码散列(Password Hashing)
Storing passwords in plain text is a bad security practice. Anyone with access to the database will immediately have access to all user accounts thus being able to engage in unauthorized activities. To combat that, many applications use the familiar one way hashing methods “md5” and “sha1”. However, hardware evolves each day, and becomes faster, these algorithms are becoming vulnerable to brute force attacks. These attacks are also known as rainbow tables.
硬件提升,密码容器破解。这些攻击工具有著名的彩虹表。

To solve this problem we can use hash algorithms as bcrypt. Why bcrypt? Thanks to its “Eksblowfish” key setup algorithm we can make the password encryption as “slow” as we want. Slow algorithms make the process to calculate the real password behind a hash extremely difficult if not impossible. This will protect your for a long time from a possible attack using rainbow tables.

This component gives you the ability to use this algorithm in a simple way:

<?php

use Phalcon\Mvc\Controller;

class UsersController extends Controller
{

    public function registerAction()
    {

        $user = new Users();

        $login = $this->request->getPost('login');
        $password = $this->request->getPost('password');

        $user->login = $login;

        //Store the password hashed
        $user->password = $this->security->hash($password);

        $user->save();
    }

}

We saved the password hashed with a default work factor. A higher work factor will make the password less vulnerable as its encryption will be slow. We can check if the password is correct as follows:

<?php

use Phalcon\Mvc\Controller;

class SessionController extends Controller
{

    public function loginAction()
    {

        $login = $this->request->getPost('login');
        $password = $this->request->getPost('password');

        $user = Users::findFirstByLogin($login);
        if ($user) {
            if ($this->security->checkHash($password, $user->password)) {
                //The password is valid
            }
        }

        //The validation has failed
    }

}

The salt is generated using pseudo-random bytes with the PHP’s function openssl_random_pseudo_bytes so is required to have the openssl extension loaded.
需要使用openssl扩展。

防止跨站点请求伪造攻击(Cross-Site Request Forgery (CSRF) protection)
This is another common attack against web sites and applications. Forms designed to perform tasks such as user registration or adding comments are vulnerable to this attack.

The idea is to prevent the form values from being sent outside our application. To fix this, we generate a random nonce (token) in each form, add the token in the session and then validate the token once the form posts data back to our application by comparing the stored token in the session to the one submitted by the form:
对每个表单产生一个随机的token,添加这个token到session中,如果有表单提交过来则验证这个token:

<?php echo Tag::form('session/login') ?>

    <!-- login and password inputs ... -->

    <input type="hidden" name="<?php echo $this->security->getTokenKey() ?>"
        value="<?php echo $this->security->getToken() ?>"/>

</form>

Then in the controller’s action you can check if the CSRF token is valid:

<?php

use Phalcon\Mvc\Controller;

class SessionController extends Controller
{

    public function loginAction()
    {
        if ($this->request->isPost()) {
            if ($this->security->checkToken()) {
                //The token is ok
            }
        }
    }

}

(三个方法,getTokenKey()和getToken()和checkToken())

Remember to add a session adapter to your Dependency Injector, otherwise the token check won’t work:

$di->setShared('session', function() {
    $session = new Phalcon\Session\Adapter\Files();
    $session->start();
    return $session;
});

Adding a captcha to the form is also recommended to completely avoid the risks of this attack.

设置组件(Setting up the component)
This component is automatically registered in the services container as ‘security’, you can re-register it to setup it’s options:
这个组件自动注册为‘security’:

<?php

$di->set('security', function(){

    $security = new Phalcon\Security();

    //Set the password hashing factor to 12 rounds
    $security->setWorkFactor(12);

    return $security;
}, true);

———————————————–
关于加密服务,默认Phalcon会注册一个叫crypt的服务,但是一般需要自定义一下,因为通过自定义可以设置一个key,那么在调用加密解密函数时就不需要指定key。
———————————————–
加密与解密(Encryption/Decryption)
Phalcon provides encryption facilities via the Phalcon\Crypt component. This class offers simple object-oriented wrappers to the mcrypt php’s encryption library.
Phalcon通过Phalcon\Crypt组件提供加密工具。这个类提供了简单的面向对象的针对php的加密库mcrypt的包装器。

By default, this component provides secure encryption using AES-256 (rijndael-256-cbc).

Basic Usage
This component is designed to provide a very simple usage:

<?php

//Create an instance
$crypt = new Phalcon\Crypt();

$key = 'le password';
$text = 'This is a secret text';

$encrypted = $crypt->encrypt($text, $key);

echo $crypt->decrypt($encrypted, $key);

You can use the same instance to encrypt/decrypt several times:

<?php

//Create an instance
$crypt = new Phalcon\Crypt();

$texts = array(
    'my-key' => 'This is a secret text',
    'other-key' => 'This is a very secret'
);

foreach ($texts as $key => $text) {

    //Perform the encryption
    $encrypted = $crypt->encrypt($text, $key);

    //Now decrypt
    echo $crypt->decrypt($encrypted, $key);
}

加密选项(Encryption Options)
The following options are available to change the encryption behavior:

Name Description
Cipher The cipher is one of the encryption algorithms supported by libmcrypt. You can see a list here
Mode One of the encryption modes supported by libmcrypt (ecb, cbc, cfb, ofb)
<?php

//Create an instance
$crypt = new Phalcon\Crypt();

//Use blowfish
$crypt->setCipher('blowfish');

$key = 'le password';
$text = 'This is a secret text';

echo $crypt->encrypt($text, $key);

提供 Base64(Base64 Support)
In order that encryption is properly transmitted (emails) or displayed (browsers) base64 encoding is usually applied to encrypted texts:
为了让加密文本更容器传送,可以把加密文本转换为Base64编码:

<?php

//Create an instance
$crypt = new Phalcon\Crypt();

$key = 'le password';
$text = 'This is a secret text';

$encrypt = $crypt->encryptBase64($text, $key);

echo $crypt->decryptBase64($text, $key);

配置加密服务(Setting up an Encryption service)
You can set up the encryption component in the services container in order to use it from any part of the application:

<?php

$di->set('crypt', function() {

    $crypt = new Phalcon\Crypt();

    //Set a global encryption key
    $crypt->setKey('%31.1e$i86e$f!8jz');

    return $crypt;
}, true);

Then, for example, in a controller you can use it as follows:

<?php

use Phalcon\Mvc\Controller;

class SecretsController extends Controller
{

    public function saveAction()
    {
        $secret = new Secrets();

        $text = $this->request->getPost('text');

        $secret->content = $this->crypt->encrypt($text);

        if ($secret->save()) {
            $this->flash->success('Secret was successfully created!');
        }

    }

}

PHP 安全

安全威胁:软件漏洞 用户输入 未能妥善保护的数据

1 安全配置PHP(与安全有关的配置参数)
1)disable_functions = string
作用域:PHP_INI_SYSTEM; 默认值:NULL
可以将disable_functions设置为一个希望禁用的函数名列表,各函数名之间用逗号分隔。

2)disable_classes = string
作用域:PHP_INI_SYSTEM; 默认值:NULL
可以禁止使用某些类。

3)display_errors = On | Off
作用域:PHP_INI_ALL; 默认值:On
PHP通过向浏览器窗口输出错误信息,从而暴露服务器配置或应用程序的一些详细信息。在生产环境下务必禁用。当然,也可以将错误信息保存到一个日志文件。

4)max_execution_time = integer
作用域:PHP_INI_ALL; 默认值:30
此指令指定脚本在终止前执行的秒数。这对于防止用户脚本占用过多CPU时间非常有用。如果设置为了则表示没有时间限制。

5)memory_limit = integer M
作用域:PHP_INI_ALL; 默认值:128M
此指令指定脚本可以使用的内存,以M为单位。此指令只有在配置PHP时启用 –enable-memory-limit后才可用。

6)open_basedir = string
作用域:PHP_INI_ALL; 默认值:NULL
PHP的open_basedir指令可以建立一个基目录,将限制所有文件操作只能在这个目录下进行。

7)sql.safe_mode = string
作用域:PHP_INI_SYSTEM; 默认值:0
当启用sql.safe_mode指令时,会忽略传给mysql_connect()和mysql_pconnect()的所有信息,而使用localhost作为目标主机。运行PHP的用户作为用户名,不使用密码。

8)user_dir = string
作用域:PHP_INI_SYSTEM; 默认值:NULL
此指令指定用户主目录中的一个目录名,PHP脚本必须放在这里才能执行。

2 隐藏配置细节
参阅:http://www.vfeelit.com/73.html

3 隐藏敏感数据
4 数据加密
1) PHP的加密函数
使用md5()散列函数加密数据。PHP的hash扩展支持数十种散列算法和相应变种。参见:http://us3.php.net/hash
注:为了确保PHP的哈希函数能用,在配置PHP时一般明确指定–with-mhash参数。

2) MCrypt包
MCrypt是一个PHP可用的流行数据加密包,它提供了加密和解密支持。要使用它前需要先安装mcrypt系统包:
(1)到http://mcrypt.sourceforge.net下载包的源代码
(2)编译安装这个包
(3)使用—with-mcrypt选项编译PHP

永久连接:http://blog.ifeeline.com/326.html