CookieCloud Fixed IV Decryption - PHP
This is a PHP implementation for decrypting CookieCloud's aes-128-cbc-fixed encrypted data using PHP's OpenSSL functions.
Requirements
- PHP 7.0 or higher
- OpenSSL extension (usually enabled by default)
- JSON extension (usually enabled by default)
Installation
Using Composer
cd php
composer install
Manual Installation
No external dependencies required - uses built-in PHP functions.
Usage
Command Line
php decrypt.php
# or using composer
composer run decrypt
As Library
<?php
require_once 'src/Decrypt.php';
use CookieCloud\Decrypt\Decrypt;
$uuid = 'your-uuid';
$encrypted = 'base64-encrypted-data';
$password = 'your-password';
try {
$data = Decrypt::decrypt($uuid, $encrypted, $password);
print_r($data);
} catch (Exception $e) {
echo "Decryption failed: " . $e->getMessage() . "\n";
}
Web API Integration
Simple API
<?php
header('Content-Type: application/json');
require_once 'src/Decrypt.php';
use CookieCloud\Decrypt\Decrypt;
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
exit;
}
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['uuid'], $input['encrypted'], $input['password'])) {
http_response_code(400);
echo json_encode(['error' => 'Missing required fields']);
exit;
}
try {
$data = Decrypt::decrypt($input['uuid'], $input['encrypted'], $input['password']);
echo json_encode(['success' => true, 'data' => $data]);
} catch (Exception $e) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
Laravel Integration
<?php
// Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use CookieCloud\Decrypt\Decrypt;
class DecryptController extends Controller
{
public function decrypt(Request $request)
{
$request->validate([
'uuid' => 'required|string',
'encrypted' => 'required|string',
'password' => 'required|string'
]);
try {
$data = Decrypt::decrypt(
$request->uuid,
$request->encrypted,
$request->password
);
return response()->json([
'success' => true,
'data' => $data
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'error' => $e->getMessage()
], 400);
}
}
}
// Route (routes/api.php)
Route::post('/decrypt', [DecryptController::class, 'decrypt']);
Symfony Integration
<?php
// Controller
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use CookieCloud\Decrypt\Decrypt;
class DecryptController extends AbstractController
{
#[Route('/api/decrypt', name: 'decrypt', methods: ['POST'])]
public function decrypt(Request $request): JsonResponse
{
$data = json_decode($request->getContent(), true);
if (!$data || !isset($data['uuid'], $data['encrypted'], $data['password'])) {
return $this->json(['error' => 'Missing required fields'], 400);
}
try {
$result = Decrypt::decrypt($data['uuid'], $data['encrypted'], $data['password']);
return $this->json(['success' => true, 'data' => $result]);
} catch (\Exception $e) {
return $this->json(['success' => false, 'error' => $e->getMessage()], 400);
}
}
}
WordPress Plugin Integration
<?php
// Plugin file: cookiecloud-decrypt.php
add_action('wp_ajax_cookiecloud_decrypt', 'cookiecloud_decrypt_handler');
add_action('wp_ajax_nopriv_cookiecloud_decrypt', 'cookiecloud_decrypt_handler');
function cookiecloud_decrypt_handler()
{
require_once plugin_dir_path(__FILE__) . 'src/Decrypt.php';
if (!wp_verify_nonce($_POST['nonce'], 'cookiecloud_decrypt')) {
wp_die('Security check failed');
}
$uuid = sanitize_text_field($_POST['uuid']);
$encrypted = sanitize_textarea_field($_POST['encrypted']);
$password = sanitize_text_field($_POST['password']);
try {
$data = CookieCloud\Decrypt\Decrypt::decrypt($uuid, $encrypted, $password);
wp_send_json_success($data);
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
}
Testing
PHPUnit Tests
Create tests/DecryptTest.php:
<?php
namespace CookieCloud\Decrypt\Tests;
use PHPUnit\Framework\TestCase;
use CookieCloud\Decrypt\Decrypt;
class DecryptTest extends TestCase
{
public function testDecrypt()
{
$uuid = 'test-uuid';
$password = 'test-password';
// Add test encrypted data here
$encrypted = '...';
$result = Decrypt::decrypt($uuid, $encrypted, $password);
$this->assertIsArray($result);
$this->assertArrayHasKey('cookie_data', $result);
}
public function testInvalidBase64()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Base64 decode failed');
Decrypt::decrypt('uuid', 'invalid-base64!', 'password');
}
public function testOpenSSLSupport()
{
$this->assertTrue(extension_loaded('openssl'));
$this->assertTrue(Decrypt::isAes128CbcSupported());
}
}
Run tests:
composer test
# or
./vendor/bin/phpunit
Algorithm Details
- Algorithm: AES-128-CBC
- Key: MD5(uuid + "-" + password).substring(0, 16)
- IV: Fixed 16 bytes of zeros
- Padding: PKCS7 (manually removed)
- Encoding: Base64
Performance
- Decryption time: ~2-3ms for typical CookieCloud data
- Memory usage: ~5-8MB
- No external dependencies (uses built-in OpenSSL)
Security Considerations
- Input Validation: Always validate and sanitize input parameters
- Error Handling: Don't expose detailed error messages to end users
- Rate Limiting: Implement rate limiting for API endpoints
- HTTPS: Always use HTTPS in production
- Memory: Clear sensitive data from memory after use
// Example secure wrapper
function secureDecrypt($uuid, $encrypted, $password) {
// Input validation
if (!is_string($uuid) || !is_string($encrypted) || !is_string($password)) {
throw new InvalidArgumentException('Invalid input types');
}
if (strlen($uuid) > 100 || strlen($password) > 100) {
throw new InvalidArgumentException('Input too long');
}
try {
return Decrypt::decrypt($uuid, $encrypted, $password);
} finally {
// Clear sensitive variables
$uuid = null;
$password = null;
$encrypted = null;
}
}
Deployment
Apache
Create .htaccess:
RewriteEngine On
RewriteRule ^api/decrypt$ decrypt.php [L]
# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Nginx
location /api/decrypt {
try_files $uri /decrypt.php;
# Security headers
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
}
Docker
Create Dockerfile:
FROM php:8.1-apache
# Install extensions
RUN docker-php-ext-install json
# Copy source code
COPY . /var/www/html/
# Set permissions
RUN chown -R www-data:www-data /var/www/html
# Expose port
EXPOSE 80
CMD ["apache2-foreground"]
Build and run:
docker build -t cookiecloud-decrypt-php .
docker run -p 8080:80 cookiecloud-decrypt-php