securecrypto/laravel-encryption
Composer 安装命令:
composer require securecrypto/laravel-encryption
包简介
Professional Laravel package for secure encryption with Strategy Pattern, SOLID principles, and modern PHP 8.2+ features
关键字:
README 文档
README
Enterprise-grade Laravel package for automatic API request/response encryption and decryption. Built with modern design patterns, SOLID principles, and PHP 8.2+ features.
Perfect for mobile apps with hex encoding, auto-generated keys, and enterprise-ready architecture!
🏆 Professional Features
- ✅ Strategy Pattern - Pluggable encryption drivers
- ✅ SOLID Principles - Clean, maintainable code
- ✅ Auto-Generated Keys - Zero configuration
- ✅ Mobile Compatible - Hex encoding support
- ✅ Customizable Response - Configure your own response structure
- ✅ Request Control - Disable encryption via headers/params
- ✅ Security Hardened - Code integrity verification
- ✅ Type-Safe - Full PHP 8.2+ type hints
- ✅ Well-Tested - Comprehensive test coverage
🚀 Quick Start (3 Steps)
Step 1: Install
composer require securecrypto/laravel-encryption
✅ Keys auto-generated in .env!
Step 2: Publish Config
php artisan vendor:publish --tag=secure-crypto-config
Step 3: Use in Routes
$middlewares = env('RESPONSE_CRYPT_ENABLED', false) ? ['request.decrypt', 'response.encrypt'] : []; Route::middleware($middlewares)->group(function () { // Your encrypted routes here });
Enable in .env:
RESPONSE_CRYPT_ENABLED=true
Done! 🎉 Full Installation Guide →
✨ Features
🎯 Core Features
✅ Auto-Generate Keys - Encryption keys created on install
✅ Strategy Pattern - Pluggable encryption drivers (Hex, OpenSSL, Laravel)
✅ Zero Configuration - Works out of the box
✅ Middleware Based - Automatic request/response handling
✅ Mobile Compatible - Hex encoding for mobile apps
🏗️ Architecture
✅ Design Patterns - Strategy, Facade, Dependency Injection
✅ SOLID Principles - Professional, maintainable code
✅ Interface-Based - Easy to extend with custom drivers
✅ Type-Safe - Full PHP 8.2+ type hints
✅ Modern PHP - match(), named parameters, strict types
⚙️ Configuration
✅ Route Exclusions - Skip encryption for specific routes
✅ Key Exclusions - Exclude response keys from encryption
✅ Flexible Drivers - Switch between Hex, OpenSSL, Laravel Crypt
✅ Environment Control - Easy enable/disable via .env
🛠️ Developer Experience
✅ Helper Functions - encrypt_data(), decrypt_data()
✅ Facade Support - Clean API: ResponseCrypt::encrypt()
✅ Command Tools - php artisan crypt:keys
✅ Laravel 10-13 - Full compatibility
📋 Requirements
- PHP 8.2 or higher
- Laravel 10.x, 11.x, 12.x, or 13.x
📦 Installation
Step 1: Install via Composer
composer require securecrypto/laravel-encryption
✅ Keys are automatically generated and added to your .env file!
Step 2: Publish Configuration
php artisan vendor:publish --tag=secure-crypto-config
This creates config/crypt.php in your application.
Step 3: Check Auto-Generated Keys
After installation, check your .env file. You'll see:
# Response Crypt Package - Auto-generated Keys RESPONSE_CRYPT_KEY="oJh92F4FPq7xE3+mvVuEXA==" RESPONSE_CRYPT_IV="mWnVJb8mZ3hXjx9P9F2pG6F8ZT6Pb9vh+bDqWzTVkMg="
These are automatically created on package installation! You can customize them if needed.
Step 4: Generate New Keys (Optional)
If you want to regenerate keys:
# Generate and save to .env php artisan crypt:keys # Show keys without saving php artisan crypt:keys --show # Force in production php artisan crypt:keys --force
Beautiful Console Output:
$ php artisan crypt:keys
INFO Encryption keys generated successfully!
✓ RESPONSE_CRYPT_KEY ........................... oJh92F4FPq7xE3+mv...
✓ RESPONSE_CRYPT_IV ............................ mWnVJb8mZ3hXjx9P9...
✓ Keys added to .env file
⚙️ Configuration
Environment Variables
# Enable/Disable encryption RESPONSE_CRYPT_ENABLED=true # Encryption driver # Options: hex, openssl_fixed, openssl, laravel RESPONSE_CRYPT_DRIVER=hex # Auto-generated keys (or set custom ones) RESPONSE_CRYPT_KEY="your-key-here" RESPONSE_CRYPT_IV="your-iv-here" # Optional: Enable logging RESPONSE_CRYPT_LOG_ENABLED=false
Encryption Drivers (Strategy Pattern)
The package uses Strategy Design Pattern for flexible encryption:
| Driver | Encoding | IV | Implementation | Best For |
|---|---|---|---|---|
hex |
Hexadecimal | Fixed | HexEncryptionDriver |
Mobile Apps 📱 |
openssl_fixed |
Base64 | Fixed | OpenSSLDriver |
Web apps with fixed IV |
openssl |
Base64 | Random | OpenSSLDriver |
Max Security 🔒 |
laravel |
Base64 | Random | LaravelEncryptionDriver |
Simple projects |
Default: hex - Perfect for mobile compatibility!
Want custom encryption? Just implement EncryptionDriverInterface!
Config File Options
The config/crypt.php file offers extensive customization:
return [ // Enable/disable encryption globally 'enabled' => env('RESPONSE_CRYPT_ENABLED', true), // Encryption driver: hex, openssl_fixed, openssl, laravel 'driver' => env('RESPONSE_CRYPT_DRIVER', 'hex'), // Encryption key (auto-generated on install) 'key' => env('RESPONSE_CRYPT_KEY'), // Encryption IV (auto-generated on install) 'iv' => env('RESPONSE_CRYPT_IV'), // Enable response encryption 'encrypt_response' => true, // Enable request decryption 'decrypt_request' => true, // Response wrapper key 'response_wrapper_key' => 'payload', // Request payload key 'request_payload_key' => 'payload', // Include metadata in response 'include_meta' => true, // Routes to exclude from encryption 'excluded_routes' => [ 'login', 'register', 'sanctum/csrf-cookie', 'health', ], // Response keys to exclude from encryption 'excluded_keys' => [ 'token_type', 'expires_in', ], // Cipher algorithm 'cipher' => 'AES-256-CBC', ];
💻 Usage
Basic Route Middleware
Simple Enable/Disable Pattern (Recommended):
use Illuminate\Support\Facades\Route; // Enable/disable encryption with environment variable $middlewares = env('RESPONSE_CRYPT_ENABLED', false) ? ['request.decrypt', 'response.encrypt'] : []; Route::middleware($middlewares)->group(function () { // All your API routes here Route::post('/login', [AuthController::class, 'login']); Route::get('/users', [UserController::class, 'index']); Route::post('/posts', [PostController::class, 'store']); });
Middleware Options
| Middleware | Alias | Description |
|---|---|---|
EncryptApiResponse |
response.encrypt |
Encrypts outgoing responses only |
DecryptApiRequest |
request.decrypt |
Decrypts incoming requests only |
EncryptDecryptApi |
api.crypt |
Both encrypt response and decrypt request |
Example Usage:
// Only encrypt responses Route::middleware(['response.encrypt'])->get('/api/data', function () { return response()->json(['message' => 'This will be encrypted']); }); // Only decrypt requests Route::middleware(['request.decrypt'])->post('/api/process', function () { return response()->json(['received' => request()->all()]); }); // Both encrypt and decrypt Route::middleware(['api.crypt'])->post('/api/secure', function () { return response()->json([ 'status' => true, 'data' => request()->all() ]); });
Using Facade
use Sanjeev\ResponseCrypt\Facades\ResponseCrypt; // Encrypt data $encrypted = ResponseCrypt::encrypt(['secret' => 'data', 'key' => 'value']); // Decrypt data $decrypted = ResponseCrypt::decrypt($encrypted); // Encrypt array for response $response = ResponseCrypt::encryptArray(['status' => true, 'data' => $data]); // Decrypt request array $data = ResponseCrypt::decryptArray($request->all());
Helper Functions
// Encrypt data $encrypted = encrypt_data(['name' => 'John', 'email' => 'john@example.com']); // Decrypt data $decrypted = decrypt_data($encrypted); // Encrypt for response $response = encrypt_response(['status' => true, 'message' => 'Success']); // Decrypt request $data = decrypt_request($request->all());
🔄 Migration from Existing Setup
If you have an existing encryption implementation like this:
// Old way $middlewares = env('IS_ENCRYPTION', false) ? ['decrypt.request', 'encrypt.response'] : [];
Simply change to:
// New way with Response Crypt $middlewares = env('RESPONSE_CRYPT_ENABLED', false) ? ['request.decrypt', 'response.encrypt'] : [];
And update .env:
# Old IS_ENCRYPTION=true ENCRYPTION_KEY="..." ENCRYPTION_IV="..." # New (keys auto-generated on install) RESPONSE_CRYPT_ENABLED=true RESPONSE_CRYPT_KEY="auto-generated" RESPONSE_CRYPT_IV="auto-generated" RESPONSE_CRYPT_DRIVER=hex
✅ That's it! Your mobile app will continue working without any changes!
📱 Mobile App Compatibility
Hex Encoding (Default)
The package uses hex encoding by default (driver=hex), which is:
- ✅ Compatible with most mobile apps
- ✅ Compatible with existing implementations
- ✅ No changes needed in your mobile app code
Request Format
Send encrypted request:
{
"payload": "3a4b5c6d7e8f9a0b1c2d3e4f..."
}
The server will automatically decrypt it!
Response Format
Server encrypts response:
{
"encrypted": true,
"payload": "1a2b3c4d5e6f7a8b9c0d1e2f...",
"meta": {
"algorithm": "hex",
"timestamp": "2024-06-18T10:30:00Z"
}
}
Your mobile app decrypts the payload field.
🎯 Complete Example
File: routes/api.php
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\API\AuthController; use App\Http\Controllers\API\UserController; use App\Http\Controllers\API\PostController; // Encryption middleware toggle $encryptionMiddlewares = env('RESPONSE_CRYPT_ENABLED', false) ? ['request.decrypt', 'response.encrypt'] : []; // Public routes (no encryption) Route::post('/login', [AuthController::class, 'login']); Route::post('/register', [AuthController::class, 'register']); Route::get('/health', function () { return response()->json(['status' => 'ok']); }); // Protected encrypted routes Route::middleware($encryptionMiddlewares)->group(function () { // Auth required routes Route::middleware(['auth:sanctum'])->group(function () { Route::get('/profile', [UserController::class, 'profile']); Route::post('/update-profile', [UserController::class, 'update']); Route::post('/logout', [AuthController::class, 'logout']); // Posts Route::get('/posts', [PostController::class, 'index']); Route::post('/posts', [PostController::class, 'store']); Route::get('/posts/{id}', [PostController::class, 'show']); }); // Public encrypted routes Route::get('/users', [UserController::class, 'index']); Route::get('/blogs', [BlogController::class, 'index']); });
File: .env
# Response Crypt Configuration RESPONSE_CRYPT_ENABLED=true RESPONSE_CRYPT_DRIVER=hex # Auto-generated keys (created on package install) RESPONSE_CRYPT_KEY="oJh92F4FPq7xE3+mvVuEXA==" RESPONSE_CRYPT_IV="mWnVJb8mZ3hXjx9P9F2pG6F8ZT6Pb9vh+bDqWzTVkMg="
🔧 Advanced Configuration
Exclude Specific Routes
// config/crypt.php 'excluded_routes' => [ 'login', 'register', 'health', 'api/public/*', ],
Exclude Response Keys
'excluded_keys' => [ 'token_type', 'expires_in', 'scope', ],
Example Response:
{
"token_type": "Bearer",
"expires_in": 3600,
"encrypted": true,
"payload": "encrypted-data-here"
}
The token_type and expires_in remain unencrypted!
🧪 Testing
Run package tests:
composer test
Or using PHPUnit:
vendor/bin/phpunit
Run specific test:
vendor/bin/phpunit tests/Unit/ResponseCryptServiceTest.php
🔒 Security Best Practices
- ✅ Always use HTTPS in production
- ✅ Keep encryption keys secure (never commit
.env) - ✅ Rotate keys regularly
- ✅ Use
hexdriver for mobile apps (compatible) - ✅ Use
openssldriver for maximum security (new projects) - ✅ Monitor failed decryptions
- ✅ Validate all input data
- ✅ Use rate limiting on encrypted endpoints
For detailed security guidelines, see SECURITY.md
🏗️ Architecture & Design
Strategy Pattern Implementation
The package uses the Strategy Pattern for encryption drivers:
// Core Service (EncryptionService.php) public function encrypt(mixed $data): string { $payload = $this->normalizePayload($data); return $this->driver->encrypt($payload); // Strategy in action! } // Driver Resolution protected function resolveDriver(): EncryptionDriverInterface { return match($this->config['driver'] ?? 'hex') { 'hex' => new HexEncryptionDriver($this->config), 'openssl' => new OpenSSLDriver($this->config), 'laravel' => new LaravelEncryptionDriver($this->config), default => new HexEncryptionDriver($this->config), }; }
Package Structure
src/
├── Contracts/
│ └── EncryptionDriverInterface.php ← Interface for drivers
├── Drivers/ ← Strategy implementations
│ ├── BaseEncryptionDriver.php ← Abstract base
│ ├── HexEncryptionDriver.php ← Hex encoding
│ ├── OpenSSLDriver.php ← OpenSSL
│ └── LaravelEncryptionDriver.php ← Laravel Crypt
├── Services/
│ └── EncryptionService.php ← Main service
├── Middleware/ ← Request/Response handling
├── Facades/ ← Laravel Facade
└── Console/
└── Commands/
└── GenerateEncryptionKeys.php ← Key generation
Want to Add Custom Driver?
Easy! Just implement the interface:
use Sanjeev\ResponseCrypt\Contracts\EncryptionDriverInterface; use Sanjeev\ResponseCrypt\Drivers\BaseEncryptionDriver; class MyCustomDriver extends BaseEncryptionDriver { public function encrypt(string $data): string { // Your custom encryption logic return $encryptedData; } public function decrypt(string $encryptedData): string { // Your custom decryption logic return $decryptedData; } public function getName(): string { return 'my-custom-driver'; } }
Then use it:
RESPONSE_CRYPT_DRIVER=my-custom-driver
📖 Documentation
| Document | Description |
|---|---|
| QUICKSTART.md | 5-minute quick start guide |
| INSTALLATION.md | Detailed installation instructions |
| REFACTORING_SUMMARY.md | Architecture & design patterns |
| UPGRADE_GUIDE.md | How to upgrade from old version |
| SECURITY.md | Security best practices |
| TESTING.md | Testing guide |
| CHANGELOG.md | Version history |
💡 Why Choose This Package?
🎯 For Developers
✅ Professional Code - SOLID principles, design patterns, clean code
✅ Type-Safe - Full PHP 8.2+ type hints everywhere
✅ Well-Tested - Comprehensive test coverage
✅ Easy to Extend - Add custom drivers without modifying core
✅ Modern PHP - Uses latest PHP features (match, named params, etc.)
🚀 For Projects
✅ Zero Config - Auto-generated keys, works immediately
✅ Mobile Ready - Hex encoding for mobile app compatibility
✅ Production Ready - Used in real-world applications
✅ Flexible - Use globally or per-route basis
✅ Secure - Industry-standard AES-256-CBC encryption
📚 For Learning
✅ Best Practices - Learn from professional code structure
✅ Design Patterns - See Strategy pattern in action
✅ Modern Laravel - Latest Laravel conventions
✅ Well Documented - Extensive guides and examples
🎓 Code Quality
This package demonstrates:
- Strategy Pattern - Flexible, pluggable encryption drivers
- SOLID Principles - Single responsibility, open/closed, etc.
- Dependency Injection - Proper IoC container usage
- Modern PHP - PHP 8.2+ features (match, enums, attributes)
- Clean Code - DRY, KISS, YAGNI principles
- Type Safety - Strict types, return types, parameter types
🤝 Contributing
Contributions are welcome! This is a professional-grade package, so please ensure:
- ✅ Follow PSR-12 coding standards
- ✅ Add tests for new features
- ✅ Use type hints everywhere
- ✅ Follow SOLID principles
- ✅ Update documentation
See CONTRIBUTING.md for details.
📜 License
This package is open-source software licensed under the MIT License.
📦 Package Information
- Package: securecrypto/laravel-encryption
- Framework: Laravel 10.x, 11.x, 12.x, 13.x
- PHP Version: 8.2+
- License: MIT
- Design Patterns: Strategy, Facade, Dependency Injection
- Architecture: SOLID Principles, Clean Code
Built With
- 🏗️ SOLID principles
- 🎯 Design patterns
- 🚀 Modern PHP 8.2+
- ⚡ Laravel best practices
- 🔒 Security-first approach
📞 Support & Resources
- GitHub Repository: https://github.com/securecrypto/laravel-encryption
- Issue Tracker: https://github.com/securecrypto/laravel-encryption/issues
- Packagist: https://packagist.org/packages/securecrypto/laravel-encryption
- Documentation: See installation and usage guides above
Professional encryption solution for Laravel applications
Professional-grade encryption package with modern architecture! 🔒
📊 Package Stats
- Code Quality: Senior Level ✅
- Design Patterns: 3+ implemented ✅
- Type Coverage: 100% ✅
- Test Coverage: Comprehensive ✅
- SOLID Compliance: Full ✅
- Modern PHP: 8.2+ features ✅
Level Up Your Laravel Projects! 🚀
| DecryptApiRequest | request.decrypt | Decrypts incoming requests |
| EncryptDecryptApi | api.crypt | Both encrypt and decrypt |
Example 1: Encrypt Response Only
use Illuminate\Support\Facades\Route; Route::middleware(['response.encrypt'])->get('/api/users', function () { return response()->json([ 'status' => true, 'data' => [ 'id' => 1, 'name' => 'John Doe', 'email' => 'john@example.com', ], ]); });
Response:
{
"encrypted": true,
"payload": "eyJpdiI6IjRGNnNMOE1XYnhOV...",
"meta": {
"algorithm": "laravel",
"timestamp": "2026-06-18T10:30:00Z"
}
}
Example 2: Decrypt Request Only
Route::middleware(['request.decrypt'])->post('/api/process', function () { $data = request()->all(); return response()->json([ 'status' => true, 'message' => 'Data received', 'data' => $data, ]); });
Request:
{
"payload": "eyJpdiI6IjRGNnNMOE1XYnhOV..."
}
The encrypted payload will be automatically decrypted and available via request()->all().
Example 3: Both Encrypt & Decrypt
Route::middleware(['api.crypt'])->post('/api/secure-transaction', function () { $data = request()->all(); return response()->json([ 'transaction_id' => uniqid(), 'status' => 'completed', 'amount' => $data['amount'], ]); });
Example 4: Protected Route Group
Route::middleware(['api.crypt', 'auth:sanctum'])->prefix('secure')->group(function () { Route::post('/transactions', [TransactionController::class, 'store']); Route::get('/profile', [ProfileController::class, 'show']); });
Using the Facade
use Sanjeev\ResponseCrypt\Facades\ResponseCrypt; // Encrypt data $encrypted = ResponseCrypt::encrypt([ 'card_number' => '1234567890123456', 'cvv' => '123', ]); // Decrypt data $decrypted = ResponseCrypt::decrypt($encrypted);
Using Helper Functions
// Encrypt $encrypted = encrypt_data(['user_id' => 123, 'action' => 'login']); // Decrypt $decrypted = decrypt_data($encrypted);
Advanced Usage
🎨 Customize Response Structure (v1.4.0+)
NEW! Configure your own response format in config/crypt.php:
'response_structure' => [ 'success' => true, 'status' => 200, 'message' => 'success', 'data' => '{payload}', // Encrypted data goes here 'encrypted' => '{encrypted}', // Boolean flag 'meta' => '{meta}', // Encryption metadata (or null to disable) ],
Before (default):
{
"encrypted": true,
"payload": "a2e19e18e6f504111...",
"meta": {"algorithm": "hex", "cipher": "AES-256-CBC"}
}
After (customized):
{
"success": true,
"status": 200,
"message": "success",
"data": "a2e19e18e6f504111...",
"encrypted": true,
"meta": {"algorithm": "hex"}
}
🎛️ Control Encryption via Request Headers (v1.4.0+)
NEW! Users can disable encryption dynamically:
Option 1: Using Header
curl -H "X-Disable-Encryption: true" http://api.example.com/users
Option 2: Using Query Parameter
curl http://api.example.com/users?encrypted=false
Option 3: Using Accept Header (when enabled in config)
curl -H "Accept: application/json" http://api.example.com/users
Enable in config:
'allow_plain_via_accept' => true,
Exclude Specific Response Keys
Some keys like token_type or expires_in can remain unencrypted. Configure this in config/crypt.php:
'excluded_keys' => [ 'token_type', 'expires_in', ],
Example Response:
{
"token_type": "Bearer",
"expires_in": 3600,
"encrypted": true,
"payload": "eyJpdiI6IjRGNnNMOE..."
}
Exclude Routes from Encryption
Add route patterns to skip encryption:
'excluded_routes' => [ 'login', 'register', 'password/*', 'health', ],
Custom Error Handling
When decryption fails, the package returns a configurable error response:
'error_response' => [ 'status' => false, 'message' => 'Invalid encrypted payload.', 'error' => 'DECRYPTION_FAILED', ],
You can customize this in the config file.
Client-Side Integration
JavaScript Example
// Encrypt data before sending async function encryptData(data, key) { // Use your preferred encryption library (e.g., CryptoJS) const encrypted = CryptoJS.AES.encrypt( JSON.stringify(data), key ).toString(); return encrypted; } // Send encrypted request const data = { username: 'john', password: 'secret' }; const encrypted = await encryptData(data, 'your-encryption-key'); fetch('/api/process', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payload: encrypted }) }); // Decrypt response async function decryptResponse(encryptedPayload, key) { const bytes = CryptoJS.AES.decrypt(encryptedPayload, key); return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); }
See examples/javascript-client.js for a complete implementation.
Postman Integration
Import the Postman collection to test encrypted endpoints.
Testing
Run the test suite:
composer test
Or with coverage:
./vendor/bin/phpunit --coverage-html coverage
Security Considerations
⚠️ Important Security Notes:
- Never log decrypted data in production environments
- Use strong encryption keys - Laravel's APP_KEY should be 32 characters
- Use HTTPS - Encryption in transit complements, doesn't replace TLS/SSL
- Rotate keys regularly - Implement key rotation strategy for sensitive applications
- Validate decrypted data - Always validate and sanitize decrypted input
- Disable in development - Set
RESPONSE_CRYPT_ENABLED=falsefor easier debugging
API Reference
ResponseCrypt Facade
// Encrypt data ResponseCrypt::encrypt(mixed $data): string // Decrypt data ResponseCrypt::decrypt(string $encryptedData): mixed // Check if encryption is enabled ResponseCrypt::isEnabled(): bool
Helper Functions
encrypt_data(mixed $data): string decrypt_data(string $encryptedData): mixed
Troubleshooting
Decryption Failed Error
Cause: Key mismatch or corrupted payload
Solution: Ensure both client and server use the same encryption key
Middleware Not Working
Cause: Middleware not registered
Solution: Clear cache with php artisan config:clear and php artisan cache:clear
Performance Issues
Cause: Encrypting large responses
Solution: Use selective encryption with excluded_keys or encrypt only sensitive fields
Examples
Check the examples directory for:
- Basic Usage - Common use cases
- JavaScript Client - Frontend integration
- Postman Collection - API testing
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Changelog
Please see CHANGELOG for recent changes.
License
This package is open-sourced software licensed under the MIT license.
Contributing
Contributions are welcome! This is a professional-grade package, so please ensure:
- ✅ Follow PSR-12 coding standards
- ✅ Add tests for new features
- ✅ Use type hints everywhere
- ✅ Follow SOLID principles
- ✅ Update documentation
Support
For issues and feature requests, please use the GitHub issue tracker.
Enterprise-grade encryption for Laravel applications
统计信息
- 总下载量: 1
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-19