宗小宗-PHP程序猿

欢迎各位朋友前来,如果我的文章中有不对的地方,还望指正;如需转载,请注明原处

PHP对称加密类

<?php
/**
 * Created by PhpStorm.
 * User: zongbinghuang
 * Date: 2017/7/31
 * Time: 15:13
 */

namespace app\common;

use Exception;

class BizEncrypt
{
    const IV_SIZE = 16;
    const CIPHER = 'AES-256-CBC';

    private $key;#length:32

    public function __construct($key)
    {
        $key = (string)$key;

        if (static::supported($key, self::CIPHER)) {
            $this->key = $key;
        } else {
            throw new Exception('The only supported ciphers are AES-256-CBC with the correct key lengths.');
        }
    }

    public function encrypt($value)
    {
        $iv = self::random_bytes(self::IV_SIZE);

        $value = openssl_encrypt(serialize($value), self::CIPHER, $this->key, 0, $iv);

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

        $iv = base64_encode($iv);
        $mac = hash_hmac('sha256', $iv . $value, $this->key);
        $json = json_encode(compact('iv', 'value', 'mac'));

        if (!is_string($json)) {
            throw new Exception('Could not encrypt the data.');
        }

        return base64_encode($json);
    }

    public function decrypt($payload)
    {
        $payload = $this->getJsonPayload($payload);

        $iv = base64_decode($payload['iv']);

        $decrypted = openssl_decrypt($payload['value'], self::CIPHER, $this->key, 0, $iv);

        if ($decrypted === false) {
            throw new Exception('Could not decrypt the data.');
        }

        return unserialize($decrypted);
    }

    private static function supported($key, $cipher)
    {
        $length = mb_strlen($key, '8bit');

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

    private function getJsonPayload($payload)
    {
        $payload = json_decode(base64_decode($payload), true);

        if (!$payload || $this->invalidPayload($payload)) {
            throw new Exception('The payload is invalid.');
        }

        return $payload;
    }

    private function invalidPayload($data)
    {
        return !is_array($data) || !isset($data['iv']) || !isset($data['value']) || !isset($data['mac']);
    }

    private static function random_bytes($bytes)
    {
        try {
            $bytes = self::RandomCompareInteger($bytes);
        } catch (Exception $ex) {
            throw new Exception('random_bytes(): $bytes must be an integer');
        }

        if ($bytes < 1) {
            throw new Exception('Length must be greater than 0');
        }

        $secure = true;
        $buf = openssl_random_pseudo_bytes($bytes, $secure);
        if ($buf !== false && $secure && mb_strlen($buf, '8bit') === $bytes) {
            return $buf;
        }

        throw new Exception('Could not gather sufficient random data');
    }

    private static function RandomCompareInteger($number, $fail_open = false)
    {
        if (is_numeric($number)) {
            $number += 0;
        }

        if (is_float($number) && $number > ~PHP_INT_MAX && $number < PHP_INT_MAX) {
            $number = (int)$number;
        }

        if (is_int($number) || $fail_open) {
            return $number;
        }

        throw new Exception('Expected an integer.');
    }
}

 

posted @ 2017-08-31 11:32  宗小宗  阅读(554)  评论(0编辑  收藏  举报