定制 chrisvpearse/code-encrypter-laravel 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

chrisvpearse/code-encrypter-laravel

Composer 安装命令:

composer require chrisvpearse/code-encrypter-laravel

包简介

A code encrypter for the Laravel framework.

README 文档

README

The goal of this open source package is security through obscurity.

It aims to offer an alternative to delivering your closed source projects in plain text. Instead, you can opt to deliver your files encrypted, alongside a binary PHP extension which will decrypt them on the fly.

This package uses symmetric encryption, which means that the key itself has to be embedded within the binary PHP extension. However, the code for the extension which holds the key and handles the decryption is open source (and is included within this package).

The key is generated by you and only known to you (as the developer). It can be unique per project and/or customer which opens up the possibility of additional functionality later down the line, such as setting expiry dates (for free trials) and/or whitelisting by IP/MAC address.

Requirements

  1. macOS
  2. PHP 8.1
  3. Laravel 10
  4. Zephir

Installation

The below assumes that you're currently in your application's root directory.

$ composer require chrisvpearse/code-encrypter-laravel

Publish the Config File

$ php artisan vendor:publish --tag=code-encrypter-config

Zephir Quickstart

You should be able to get started with Zephir by downloading the latest release PHAR from GitHub, followed by these commands:

$ cd ~ && pecl install zephir_parser
$ cd ~/Downloads && mv zephir.phar /usr/local/bin/zephir && chmod +x /usr/local/bin/zephir

A "Hello, World!" Walkthrough

Again, the below assumes that you're currently in your application's root directory.

Make an Invokable Controller

$ php artisan make:controller HelloWorld --invokable

📄 ./app/Http/Controllers/HelloWorld.php

<?php

namespace App\Http\Controllers;

class HelloWorld extends Controller
{
    public function __invoke()
    {
        return 'Hello, World!';
    }
}

Update the Web Routes File

📄 ./routes/web.php

<?php

use App\Http\Controllers\HelloWorld;
use Illuminate\Support\Facades\Route;

Route::get('/', HelloWorld::class);

Update the Config File

The default configuration file is shown below.

  • The * wildcard matches all files within the specified directory
  • The ** wildcard is recursive and matches all files within the specified directory and subdirectories

📄 ./config/code-encrypter.php

<?php

return [
    'paths' => [
        app_path('Http/Controllers/Foo/*'),
        app_path('Http/Controllers/Bar/**'),
        app_path('Http/Controllers/HelloWorld.php'),
    ],
    'cipher' => config('app.cipher') ?: 'AES-256-CBC',
    'minify' => false,
];

A PHP file is considered valid provided that the following conditions are met:

  • The extension is: .php
  • It contains an opening PHP tag: <?php
  • It does not contain a closing PHP tag: ?>

First Run

You should confirm that you can see "Hello, World!" after running the following command:

$ php artisan serve

Run the Encrypt Command

$ php artisan code:encrypt

The output from the above command will be similar to the following:

Encrypted ....................................................... app/Http/Controllers/HelloWorld.php

[ INFO ] Command successfully completed.

Key ............................................. base64:8dsiWW4Ue016d1TBalTlJAE46vfO91y5/Xu9UFZzhmc=
Cipher .................................................................................. AES-256-CBC
Zephir File .......................................... tmp/code-encrypter/zephir/zephir/encrypter.zep
Zephir Temp Directory (Must Delete) .............................................. tmp/code-encrypter

❗ Please remember to make a note of your key.

On this run, one file has been successfully encrypted:

📄 ./app/Http/Controllers/HelloWorld.php

<?php \Zephir\Encrypter::decrypt("c3DHmSPBpjBUQcZ...8+SePRyCXaKbg==", "hj54ztR3KB+7cWKVJFP0QA==");
// base64:eyJpdiI6ImhqNTR6dFIzS0IrN2NXS1...UwZGVhYTY2MDRhIiwidGFnIjoiIn0=

The decrypt() static method in \Zephir\Encrypter takes the value and iv (initialization vector) from the payload returned by the encryptString() method in \Illuminate\Encryption\Encrypter.

The commented-out base64 encoded string contains the entire JSON payload returned by the encryptString() method in \Illuminate\Encryption\Encrypter and is used in the decryption process.

A "Utils" Gist

For your convenience, I have published a GitHub Gist which exposes a small number of utilities which will be used throughout the rest of this document.

Build the PHP Extension

At this point, you must build the PHP extension because Laravel will no longer be able to find \App\Http\Controllers\HelloWorld (which will result in an error).

You should switch to the Zephir Temp Directory as detailed on the output from the previous command:

$ cd tmp/code-encrypter

From there, you should initialize Zephir into the zephir directory which has already been created for you:

$ zephir init zephir

Finally, you should step into the zephir directory and build the extension from there:

$ cd zephir && zephir build

Once the extension has been built, you should be prompted to add extension=zephir.so to your php.ini file. For this, I will use the ini utility exposed by the GitHub Gist:

$ php ~/Downloads/utils.php ini

Next, we can take a look at the Zephir code itself:

📄 ./tmp/code-encrypter/zephir/zephir/encrypter.zep

namespace Zephir;

class Encrypter
{
    public static function decrypt(var gLIEokrXlBB6s, var LxARS8923aokLv)
    {
        return eval(self::ssjgKzuSCrh9Zjhom1P(gLIEokrXlBB6s, LxARS8923aokLv));
    }

    ...

    protected static function ssjgKzuSCrh9Zjhom1P(var gLIEokrXlBB6s, var LxARS8923aokLv)
    {
        var ZURmZSyHXCWAwv;

        let ZURmZSyHXCWAwv = ["f1","db","22","59","6e","14",..."bd","50","56","73","86","67"];

        return openssl_decrypt(
            gLIEokrXlBB6s,
            "AES-256-CBC",
            hex2bin(implode(ZURmZSyHXCWAwv)),
            0,
            base64_decode(LxARS8923aokLv)
        );
    }

    ...
}

The above code is not minified, which can (and should) be changed in ./config/code-encrypter.php. During the minifying process, whitespace is randomly added to ensure that the key is never in the same place twice (within the binary PHP extension).

In an effort to further randomize the binary, the \Illuminate\Support\Str::password() helper is used to name the variables and methods. Additionally, the method which holds the key is shuffled with 4–8 unused methods (each containing their own key). Each key is stored within its own array to avoid being detected by the strings command:

$ strings /path/to/zephir.so

Now, let's use the tmp utility exposed by the GitHub Gist to delete the Zephir Temp Directory:

$ php ~/Downloads/utils.php tmp "/path/to/app/root/"

Second Run

You should confirm that you are still able to see "Hello, World!" after running the following command:

$ cd ../../../ && php artisan serve

Congratulations 🎉 Your encrypted files are now being decrypted on the fly!

Run the Decrypt Command

In order to decrypt your code, you must supply the key as the first argument:

$ php artisan code:decrypt base64:8dsiWW4Ue016d1TBalTlJAE46vfO91y5/Xu9UFZzhmc=

The output from the above command will be similar to the following:

Decrypted ....................................................... app/Http/Controllers/HelloWorld.php

[ INFO ] Command successfully completed.

On this run, one file has been successfully decrypted:

📄 ./app/Http/Controllers/HelloWorld.php

<?php

namespace App\Http\Controllers;

class HelloWorld extends Controller
{
    public function __invoke()
    {
        return 'Hello, World!';
    }
}

Run the Encrypt Command (Again)

Once the PHP extension has been built by Zephir, you can decrypt and encrypt your code as many times as you like without rebuilding the extension (provided that you use the same key). The key should be supplied via an option to the command:

$ php artisan code:encrypt --key=base64:8dsiWW4Ue016d1TBalTlJAE46vfO91y5/Xu9UFZzhmc=

Note. When encrypting code, the ./tmp/code-encrypter directory will always be generated for you.

NativePHP

At the time of writing, NativePHP ships with a static PHP binary, therefore it is not possible to install additional extensions.

However, as a PoC, we can swap out the NativePHP binary with a copy of our local PHP binary (NativePHP must already be installed). For this, I will use the bin utility exposed by the GitHub Gist:

$ php ~/Downloads/utils.php bin "/path/to/app/root/"

Third Run

You should confirm that you are still able to see "Hello, World!" after running the following command:

$ php artisan native:serve

Congratulations, again 🎊 Your encrypted files are now being decrypted on the fly within NativePHP!

Credits

  • Aleksandar Jevremović, et al. (2013). Using Cryptology Models for Protecting PHP Source Code.

chrisvpearse/code-encrypter-laravel 适用场景与选型建议

chrisvpearse/code-encrypter-laravel 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 8 次下载、GitHub Stars 达 8, 最近一次更新时间为 2023 年 12 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「code-encrypter-laravel」 「chrisvpearse」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 chrisvpearse/code-encrypter-laravel 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 chrisvpearse/code-encrypter-laravel 我们能提供哪些服务?
定制开发 / 二次开发

基于 chrisvpearse/code-encrypter-laravel 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

与 chrisvpearse/code-encrypter-laravel 相关的其它包

同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:

统计信息

  • 总下载量: 8
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 8
  • 点击次数: 11
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 8
  • Watchers: 1
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-12-20