README.md

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

  1. Input Validation: Always validate and sanitize input parameters
  2. Error Handling: Don't expose detailed error messages to end users
  3. Rate Limiting: Implement rate limiting for API endpoints
  4. HTTPS: Always use HTTPS in production
  5. 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