taracybersec/php-security

PHP Security - 一个现代且安全的PHP库,提供了一系列加密数据、解密数据、生成安全随机密码、清理数据等方法。它使用PHP内置的加密功能构建,设计简单易用且安全性高。

1.6.2 2024-05-17 17:45 UTC

This package is auto-updated.

Last update: 2024-09-17 18:38:19 UTC


README

简介

PHP Security是一个现代且安全的PHP库,提供了一系列加密数据、解密数据、生成安全随机密码等方法。它使用PHP内置的加密功能构建,设计简单易用且安全性高。

特性

  • 使用多种算法(AES-256-CBC、AES-128-GCM、ChaCha20-Poly1305等)安全加密和解密数据
  • 支持基于密码和密钥加密/解密
  • 生成具有各种特性(长度、大小写、数字、符号)的复杂且安全随机密码

要求

  • PHP 7.2或更高版本

安装

使用以下命令安装最新版本

composer require taracybersec/php-security

加密特性

1. 设置密钥

要设置用于加密和解密数据的密钥,可以使用以下方法。该方法接受一个字符串作为参数,并设置所有加密和解密方法使用的密钥。密钥用于对称加密和解密。建议在应用程序启动时设置密钥一次,并保存在安全的位置。

use TaraCyberSec\PhpSecurity\Crypto;

Crypto::setSecretKey('your_secret_key');

2. 生成密钥

要生成用于加密和解密数据的密钥,可以使用以下方法。该方法生成一个随机密钥,可用于使用指定的算法(AES-256-CBC等)加密和解密数据。该方法返回一个可存储在数据库或通过网络发送的编码字符串。密钥用于对称加密和解密。建议在应用程序启动时生成一个新的密钥一次,并保存在安全的位置。生成的密钥是加密安全的,适用于高安全应用程序。

use TaraCyberSec\PhpSecurity\Crypto;

Crypto::generateSecretKey(Crypto::ALGO_AES_256_CBC);

3. 加密数据

要使用密钥加密数据,可以使用以下方法。该方法使用AES-256-CBC算法(您可以选择自己的)和密钥加密数据。该方法返回一个base64编码的字符串,可以存储在数据库中或通过网络发送。

use TaraCyberSec\PhpSecurity\Crypto;

$data = "Sensitive information";
Crypto::setSecretKey('your_secret_key');
$encryptedData = Crypto::encrypt($data, Crypto::ALGO_AES_256_CBC);

4. 解密数据

要解密使用密钥加密的数据,可以使用以下方法。该方法使用指定的算法(AES-256-CBC等)和密钥解密数据。该方法返回一个解密字符串,可以被您的应用程序使用。解密过程使用setSecretKey方法设置的密钥。

use TaraCyberSec\PhpSecurity\Crypto;

$data = "your encrypted data";
Crypto::setSecretKey('your_secret_key');
$encryptedData = Crypto::decrypt($data, Crypto::ALGO_AES_256_CBC);

5. 检查算法是否受支持

要检查加密算法是否受当前PHP版本支持,可以使用以下方法。该方法检查指定的算法是否受当前PHP版本支持,如果不支持,则返回false。如果算法受支持,则返回true。此方法在您想在加密数据之前检查算法是否受支持时很有用。

use TaraCyberSec\PhpSecurity\Crypto;

echo Crypto::isAlgorithmSupported('algo_name');

6. 获取支持的算法

要获取当前PHP版本支持的加密算法列表,可以使用以下方法。此方法返回当前PHP版本支持的算法列表,在使用它加密数据之前检查算法是否支持是一种很好的方法。

支持的加密算法数量可能因PHP版本、操作系统和硬件而异。但是,支持的算法列表是稳定的,除非PHP有重大版本发布,否则不会改变。

use TaraCyberSec\PhpSecurity\Crypto;

$supportedEncAlgos = Crypto::getSupportedAlgorithms();

7. 生成随机字符串

要生成安全的随机字符串,请使用此方法。它将返回指定长度的随机字符串。如果您需要生成用于生成盐、生成令牌或其他任何需要随机字符串的场景,此方法非常有用。随机字符串中的字符数将是指定的长度。该方法将返回一个字符串。

use TaraCyberSec\PhpSecurity\Crypto;

echo Crypto::generateRandomString(32);

8. 生成安全的随机密码

要生成具有指定特征的随机密码,请使用此方法。它将返回一个指定长度的随机密码,至少包含一个小写字母、一个大写字母、一个数字和一个符号。该方法将返回一个字符串。

use TaraCyberSec\PhpSecurity\Crypto;

echo Crypto::generateSecureRandomPassword(24, Crypto::PASS_LOWERCASE_ON, Crypto::PASS_UPPERCASE_ON, Crypto::PASS_NUMBERS_ON, Crypto::PASS_SYMBOLS_ON);

9. 为CryptoJS加密数据

要为CryptoJS加密数据,请使用此方法。它使用支持JavaScript中CryptoJS库的指定算法加密数据。它返回一个JSON编码的字符串,可以安全地传递给JavaScript中使用的CryptoJS库。加密数据将兼容CryptoJS库,这是一个流行的JavaScript库,用于加密和解密数据。加密数据是JSON编码的,因此可以轻松地作为字符串传递到JavaScript中。加密数据将以包含加密数据的data属性和包含加密时使用的初始化向量的iv属性的JSON对象返回。加密数据的字符数将根据加密数据的长度而变化。该方法将返回一个字符串。

use TaraCyberSec\PhpSecurity\Crypto;

$data = "Sensitive information";
Crypto::setSecretKey('your_secret_key');
echo Crypto::encryptForCryptoJS($data, Crypto::ALGO_AES_256_CBC);

10. 从CryptoJS解密数据

要从CryptoJS解密数据,请使用此方法。它使用支持JavaScript中CryptoJS库的指定算法解密数据。它返回一个字符串,该字符串是使用JavaScript中CryptoJS库加密的。解密数据的字符数将与加密数据的字符数相同。该方法将返回一个字符串。

use TaraCyberSec\PhpSecurity\Crypto;

$data = "your encrypted data";
Crypto::setSecretKey('your_secret_key');
$encryptedData = Crypto::decryptFromCryptoJS($data, Crypto::ALGO_AES_256_CBC);

注意:为了确保在使用CryptoJS时加密数据具有兼容的格式,请按照以下步骤操作

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

const encrypt = (text, key) => {
    try {
        return CryptoJS.AES.encrypt(JSON.stringify(text), key, {
            format: {
                "encrypt": function (value, password) {
                    if (password.match(/[^\x00-\x7F]/)) {
                        console.warn("CryptoJSAES: Your passphrase contains non ASCII characters - This is not supported. Hash your passphrase with MD5 or similar hashes to prevent those issues");
                    }
                    return CryptoJS.AES.encrypt(JSON.stringify(value), password, { "format": CryptoJSAesJson }).toString();
                },
                "decrypt": function (jsonStr, password) {
                    if (password.match(/[^\x00-\x7F]/)) {
                        console.warn("CryptoJSAES: Your passphrase contains non ASCII characters - This is not supported. Hash your passphrase with MD5 or similar hashes to prevent those issues");
                    }
                    return JSON.parse(CryptoJS.AES.decrypt(jsonStr, password, { "format": CryptoJSAesJson }).toString(CryptoJS.enc.Utf8));
                },
                "stringify": function (cipherParams) {
                    var j = { "ct": cipherParams.ciphertext.toString(CryptoJS.enc.Base64) };
                    if (cipherParams.iv) j.iv = cipherParams.iv.toString();
                    if (cipherParams.salt) j.s = cipherParams.salt.toString();
                    return JSON.stringify(j).replace(/\s/g, "");
                },
                "parse": function (jsonStr) {
                    var j = JSON.parse(jsonStr);
                    var cipherParams = CryptoJS.lib.CipherParams.create({ "ciphertext": CryptoJS.enc.Base64.parse(j.ct) });
                    if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv);
                    if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s);
                    return cipherParams;
                }
            }
        }).toString();
    } catch (error) {
        console.log(error.stack);
        return false;
    }
}

Sanitize中的功能

1. 深度编码

为了安全地清理数据数组以防止XSS攻击,您可以使用deepEncode方法。此方法通过递归编码数组的每个元素来深度编码数据数组。它确保即使攻击者成功将恶意数据注入到数组元素中,它也将被HTML编码,并且不会被浏览器作为代码执行。编码数据的元素数量将与原始数据的元素数量相同。该方法将返回一个编码数据的数组。

use TaraCyberSec\PhpSecurity\Sanitize;

$data = $request->all();
$data = Sanitize::deepEncode($data);

$request->replace($data);

2. 编码

要编码输入字符串,您可以使用encode方法。它通过HTML编码输入字符串以防止XSS攻击。这意味着字符串中的任何特殊HTML字符,如"<"和">",将被其相应的HTML实体替换,如"<"和">",使其在HTML文档中使用时安全。编码字符串中的字符数将正好与原始字符串中的字符数相同。该方法将返回一个字符串。

use TaraCyberSec\PhpSecurity\Sanitize;

$data = "<script>alert("some data")</script> here is a script";
$data = Sanitize::encode($data);

3. 深度清理

为了清理数据数组,您可以使用deepClean方法。此方法通过递归地清理数组中的每个元素,无论其类型如何,来清理数组中的每个元素。这样,即使攻击者成功将恶意数据注入到数组中的某个元素,这些数据也会被清理,不会由浏览器作为代码执行。此外,它还会修剪字符串并从其中删除标签,使数据在您的应用程序中使用时更安全。清理后的数据中的元素数量将与原始数据中的元素数量相同。该方法将返回一个清理后的数据数组。

use TaraCyberSec\PhpSecurity\Sanitize;

$data = $request->all();
$data = Sanitize::deepClean($data);

$request->replace($data);

4. 清理

要清理输入字符串,您可以使用clean方法。它通过trim从字符串的两端删除空白字符,并使用strip_tags从字符串中删除标签,从而移除字符串中的HTML实体。这样,即使攻击者成功将恶意数据注入到字符串中,这些数据也会被修剪,且不带标签,使其无害。

use TaraCyberSec\PhpSecurity\Sanitize;

$data = "<script>alert("some data")</script> here is a script";
$data = Sanitize::clean($data);

5. 验证上传的文件

要验证上传的文件,您可以使用validateUploadedFiles方法。它通过扫描文件内容以查找恶意代码或文件来验证上传的文件,确保它们可以安全地上传到您的Web服务器。它递归地扫描请求体中的每个文件,并检查文件内容是否可以安全上传。此方法有助于防止文件上传攻击和代码注入攻击。它执行以下检查:

  • 根据文件的MIME类型检查文件是否是有效的图像、PDF或电子表格文件。
  • 扫描文件内容以查找常见的恶意模式。
  • 根据文件扩展名检查文件是否是有效的文件类型。

如果任何这些检查失败,方法将错误消息添加到错误数组中。然后,方法返回错误数组。如果错误数组为空,则表示请求体中的所有文件都可以安全上传。

use TaraCyberSec\PhpSecurity\Sanitize;

$errors = Sanitize::validateUploadedFiles();
if (!empty($errors)) {
    http_response_code(422);
    header('Content-Type: application/json');
    echo json_encode([
        'message' => $errors[0],
        'errors' => $errors
    ]);
    die;
}

服务器功能

1. 添加安全头

要向所有响应添加安全头,您可以使用addSecurityHeaders方法。通过设置Content-Security-Policy、X-Content-Type-Options、X-Frame-Options、X-XSS-Protection、Referrer-Policy、Strict-Transport-Security和Feature-Policy头,它有助于防止XSS攻击、点击劫持和其他安全威胁。

use TaraCyberSec\PhpSecurity\Server;

Server::addSecurityHeaders();

2. 设置速率限制存储路径

可选

要设置速率限制存储路径,您可以使用setRateLimitStoragePath方法。此方法设置库将存储速率限制数据的位置。该方法接受一个字符串作为参数,并将路径设置为指定的目录。该目录必须存在且可以被Web服务器写入。默认路径是当前工作目录。

use TaraCyberSec\PhpSecurity\Server;

$path = __DIR__ . "/rate_limit";
Server::setRateLimitStoragePath($path);

3. 强制执行速率限制

要强制执行速率限制,此方法检查请求是否在指定的速率限制内。如果请求在速率限制内,它返回true。如果请求超出速率限制,它停止脚本执行并返回一个带有429状态码的JSON响应。此方法接受两个参数:在指定间隔内允许的最大请求数量,以及间隔秒数。

use TaraCyberSec\PhpSecurity\Server;

Server::enforceRateLimiting();

您可以通过以下方式自定义速率限制默认值

use TaraCyberSec\PhpSecurity\Server;

$requestLimit = 200; // max requests allowed in the interval: like 200 requests per 30 seconds
$interval = 30; // in seconds
Server::enforceRateLimiting($requestLimit, $interval);