使用已准备好的语句进行Openssl_Encryption

时间:2018-08-10 15:24:14

标签: php encryption openssl

我在下面写了一些代码,可以创建帐户。我想通过加密所有数据(密码和用户名除外)来添加额外的保护层。我有两个问题:

1。 Openssl是最好的php加密实践吗?

2。如何在我的代码中添加openssl?

在将openssl与准备好的语句代码集成时,我有些困难。

我的代码:

<?php
session_start();
require_once './config/config.php';
require_once 'includes/auth_validate.php';

//Only super admin is allowed to access this page
if ($_SESSION['admin_type'] !== 'super') {
    // show permission denied message
    echo 'Permission Denied';
    exit();
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') 
{
    $admin_type = mysqli_real_escape_string($conn, $_POST['admin_type']);
    $position = mysqli_real_escape_string($conn, $_POST['position']);
    $first_name = mysqli_real_escape_string($conn, $_POST['first_name']);
    $last_name = mysqli_real_escape_string($conn, $_POST['last_name']);
    $user_name = mysqli_real_escape_string($conn, $_POST['user_name']);
    $email = mysqli_real_escape_string($conn, $_POST['email']);
    $phone_number = mysqli_real_escape_string($conn, $_POST['phone_number']);
    $passwd = mysqli_real_escape_string($conn, $_POST['passwd']);
    $about = mysqli_real_escape_string($conn, $_POST['about']);

    //Error handlers 
    //Check for empty fields 
    if (empty($admin_type) || empty($position) || empty($first_name) || empty($last_name) || empty($user_name) || empty($passwd)){
        $_SESSION['failure'] = "Admin was not created, missing imporant details!";
        header('location: admin_users');
        exit();
    } else {
        $sql = "SELECT * FROM admin_accounts WHERE user_name='$user_name'";
        $result = mysqli_query($conn, $sql);
        $resultCheck = mysqli_num_rows($result);

        if ($resultCheck > 0) {
            $_SESSION['failure'] = "Admin was not created, username already used!";
            header('location: admin_users');
            exit();    
        } else {
            //Hashing password 
            $hashedPasswd = password_hash($passwd, PASSWORD_DEFAULT); 

            //Insert the user into the database 
            $sql = "INSERT INTO admin_accounts (admin_type, position, first_name, last_name, user_name, email, phone_number, passwd, about) VALUES (?,?,?,?,?,?,?,?,?);";

            $stmt = mysqli_stmt_init($conn);
            if (!mysqli_stmt_prepare($stmt, $sql)) {
                echo "SQL Error";
            } else {
                mysqli_stmt_bind_param($stmt, "sssssssss", $admin_type, $position, $first_name, $last_name, $user_name, $email, $phone_number, $hashedPasswd, $about);
                mysqli_stmt_execute($stmt);
              {
                    $_SESSION['success'] = "Admin user added successfully!";
                    header('location: admin_users');
                    exit();
                }     
            }
        }
    }
}
$edit = false;

Openssl_Encryption示例:

<?php
//$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$cipher = "aes-128-gcm";
if (in_array($cipher, openssl_get_cipher_methods()))
{
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
    //store $cipher, $iv, and $tag for decryption later
    $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
    echo $original_plaintext."\n";
}

我仅尝试加密名字:(这不起作用,在数据库中无效)

<?php
session_start();
require_once './config/config.php';
require_once 'includes/auth_validate.php';

//ONLY SUPER ADMINS ARE ALLOWED TO ACCESS THIS PAGE 
if ($_SESSION['admin_type'] !== 'super') {
    // show permission denied message
    echo 'Permission Denied';
    exit();
}


if ($_SERVER['REQUEST_METHOD'] == 'POST') 
{
$admin_type = mysqli_real_escape_string($conn, $_POST['admin_type']);
$position = mysqli_real_escape_string($conn, $_POST['position']);
$first_name = mysqli_real_escape_string($conn, $_POST['first_name']);
$last_name = mysqli_real_escape_string($conn, $_POST['last_name']);
$user_name = mysqli_real_escape_string($conn, $_POST['user_name']);
$email = mysqli_real_escape_string($conn, $_POST['email']);
$phone_number = mysqli_real_escape_string($conn, $_POST['phone_number']);
$passwd = mysqli_real_escape_string($conn, $_POST['passwd']);
$about = mysqli_real_escape_string($conn, $_POST['about']);
    
    //EROOR HANDLERS
    //CHECK FOR EMPTY FIELDS 
    if (empty($admin_type) || empty($position) || empty($first_name) || empty($last_name) || empty($user_name) || empty($passwd)){
        $_SESSION['failure'] = "Admin was not created, missing imporant details!";
        header('location: admin_users');
        exit();
    } else {
                $sql = "SELECT * FROM admin_accounts WHERE user_name='$user_name'";
                $result = mysqli_query($conn, $sql);
                $resultCheck = mysqli_num_rows($result);
                
                if ($resultCheck > 0) {
                    $_SESSION['failure'] = "Admin was not created, username already used!";
                    header('location: admin_users');
                    exit();    
                } else {
                    //HASHING PASSWORD 
                    $hashedPasswd = password_hash($passwd, PASSWORD_DEFAULT); 
                    
                    //INSERT THE USER INTO THE DATABASE  
                    $sql = "INSERT INTO admin_accounts (admin_type, position, first_name, last_name, user_name, email, phone_number, passwd, about) VALUES (?,?,?,?,?,?,?,?,?);";

                    $stmt = mysqli_stmt_init($conn);
                    if (!mysqli_stmt_prepare($stmt, $sql)) {
                        echo "SQL Error";
                    } else {
                        mysqli_stmt_bind_param($stmt, "sssssssss", $admin_type, $position, $first_name, $last_name, $user_name, $email, $phone_number, $hashedPasswd, $about);
                        mysqli_stmt_execute($stmt);
                        
                        {
                            $first_name = mysqli_real_escape_string($conn, $_POST['first_name']);
                            $cipher = "aes-128-gcm";
                            if (in_array($cipher, openssl_get_cipher_methods()))
                            {
                                $ivlen = openssl_cipher_iv_length($cipher);
                                $iv = openssl_random_pseudo_bytes($ivlen);
                                $ciphertext = openssl_encrypt($first_name, $cipher, $key, $options=0, $iv, $tag);
                            }

                        }
                        
                      {
                            $_SESSION['success'] = "Admin user added successfully!";
                            header('location: admin_users');
                            exit();
                        }     
                    }

                }
                
            }
            
        }
               

$edit = false;

?>

1 个答案:

答案 0 :(得分:1)

  

。我想通过加密所有数据来添加额外的保护层   (密码和用户名除外)。

正如我在评论中提到的那样,实用方面是您可能无法搜索使用AES加密的任何数据,这是因为每次加密某项时AES都会返回不同的值。这是一件好事,但几乎不可能进行搜索。除了AES之外,还可以使用SHA256之类的方法创建哈希,哈希可以每次返回相同的值(但是这是一种方法,没有解密)。因此,通过将散列存储在数据库中,您可以对数据进行散列并在先前存储的数据库中查找散列。这样做的缺点是,除了增加复杂性之外,还通常会削弱您的加密。如果他们不能攻击AES,则可以尝试强行使用HASH。

现在说,如果您真的需要加密一些数据。然后,我在用户表中创建一个字段,然后对数据进行JSON编码或序列化。这将基本上将数据数组转换为字符串。然后,您可以加密该字符串。

您将无法搜索数据,但是所有数据都将集中在一个位置,并且只需解密一次即可。

       $data = ['foo'=>'bar', 'stuff'=>'otherthing'];

       $json = json_encode($data); //'{"foo":"bar", "stuff":"otherthing"}'

       $encrypted = AESencrypt($json); //or whatever the function is

然后您将$encrypted保存在一个名为secure或类似内容的字段中。

最后一件事,我强烈建议使用PHPSecLib2.0

https://github.com/phpseclib/phpseclib

它不仅会为您提供一个更好的API,因为它是面向对象的,而且还具有SSL的本机植入(尽管安装open_ssl扩展会使其更快)。

使用PHPseclib,这就是您要做的一切

function encryptAES($key, $plaintext){
    $Cipher = new AES(AES::MODE_CBC);
    $Cipher->setKey($key);    

    //create the IV
    $iv = Random::string($Cipher->getBlockLength() >> 3);
    $Cipher->setIV($iv);

    //encrypt and combine (you have to know the IV to decode. this is the typical way it's done) the IV is like a salt.
    $encrypted = $iv_base64 . base64_encode($Cipher->encrypt($plaintext));
    return $encrypted;
}


function decryptAES($key, $plaintext){
    $Cipher = new AES(AES::MODE_CBC);
    $Cipher->setKey($key);
    //find and decode the iv
    $iv = base64_decode(substr($ciphertext, 0, 22) . '==');

    //remove the iv from ciphertext
    $encrypted = substr($ciphertext, 22);

    $Cipher->setIV($iv);

    $decrypted = $Cipher->decrypt(base64_decode($encrypted));
    return $decrypted;
}

您必须对其进行base64编码,因为它是二进制的,因此它将存储在文本字段中。您也许可以在数据库中使用某种类型的二进制字段。多数时候,我进行加密时都是在处理文件,所以我不确定。

注意

请注意,任何对称2向加密(使用1个密钥而不是公共/私有对的加密)都适用。是它的安全性仅与加密密钥一样安全。因为服务器必须知道该KEY,所以如果有人要访问文件系统和服务器的DB,那么他们很有可能能够找到用于加密的密钥。这严重限制了它提供的“真实”安全性。这并不是说不值得做,只是您在处理需要加密的数据时必须了解局限性并意识到风险。例如,我不会在服务器上使用AES来存储信用卡或其他PCI类型的数据。

基本上,它将安全性职责从数据库转移到了代码所在的服务器。原始数据是无用的,因为它已加密,但是代码必须可以访问KEY,如果有人可以访问,则他们同样可以解密数据。您可以采取一些措施来增强服务器的抵抗攻击能力(DMZ等),但这超出了此处的讨论范围。

干杯。