ifabula / sevola-sdk-php
PHP SDK for Sevola encryption service - Format-preserving and AES-GCM encryption
Requires
- php: >=7.3 <9.0
- ext-json: *
- ext-mbstring: *
- ext-openssl: *
- guzzlehttp/guzzle: ^7.7
- phpseclib/phpseclib: ^3.0
Requires (Dev)
- phpunit/phpunit: ^9.6
README
PHP SDK for format-preserving and AES-GCM encryption via Sevola service.
Features
- AES "transit" and "rest" encryption for arbitrary payloads
- FF1 format-preserving encryption for data at rest
- Key retrieval from Sevola API
- PHP 7.3+ compatibility
- Thread-safe operations
- Configurable timeout and base URL
- Comprehensive error handling
Installation
Via Composer
composer require ifabula/sevola-sdk-php
Or add to your composer.json:
{
"require": {
"ifabula/sevola-sdk-php": "^1.0.0"
},
"repositories": [
{
"type": "path",
"url": "./sevola-sdk-php"
}
]
}
Then run:
composer install
Quick Start
1. Basic Usage
<?php
require 'vendor/autoload.php';
use Ifabula\Sevola\EncryptClient;
// Create client with API key
$client = EncryptClient::new('your-api-key');
// Encrypt data at rest
$plaintext = 'Hello, World!';
$encrypted = $client->encryptData($plaintext);
// Decrypt data
$decrypted = $client->decryptData($encrypted);
echo "Original: $plaintext\n";
echo "Encrypted: $encrypted\n";
echo "Decrypted: $decrypted\n";
Compatibility note
Namespace resmi untuk raw SDK adalah:
use Ifabula\Sevola\EncryptClient;
use Ifabula\Sevola\EncryptClientOptions;
Versi ini juga menyediakan alias kompatibilitas untuk contoh awal yang memakai
Ifabula\SevolaInterceptor\EncryptClient. Jadi kode lama seperti ini tetap
akan diarahkan ke client SDK:
use Ifabula\SevolaInterceptor\EncryptClient;
$sdk = new EncryptClient([
'apiKey' => 'your-api-key',
'baseUrl' => 'https://your-sevola-server.com',
'timeout' => 60,
]);
Untuk implementasi baru, tetap gunakan namespace resmi Ifabula\Sevola.
2. Advanced Configuration
<?php
require 'vendor/autoload.php';
use Ifabula\Sevola\EncryptClient;
use Ifabula\Sevola\EncryptClientOptions;
// Create client with custom options
$options = new EncryptClientOptions(
'your-api-key',
'https://your-sevola-server.com',
60
);
$client = EncryptClient::newWithOptions($options);
// Use transit encryption for data in motion
$encrypted = $client->encryptTransit('sensitive data');
$decrypted = $client->decryptTransit($encrypted);
echo "Transit encrypted: $encrypted\n";
echo "Transit decrypted: $decrypted\n";
3. FF1 Format-Preserving Encryption
<?php
require 'vendor/autoload.php';
use Ifabula\Sevola\EncryptClient;
$client = EncryptClient::new('your-api-key');
// Encrypt with FF1
$requests = [
[
'template' => 'numeric',
'data' => '1234-5678-9012'
]
];
$results = $client->encryptDataFF1($requests);
foreach ($results as $result) {
echo "Status: {$result['status']}\n";
echo "Value: {$result['value']}\n";
}
// Decrypt with FF1
$decryptRequests = [
[
'template' => 'numeric',
'value' => $results[0]['value']
]
];
$decryptResults = $client->decryptDataFF1($decryptRequests);
foreach ($decryptResults as $result) {
echo "Status: {$result['status']}\n";
echo "Data: {$result['data']}\n";
}
Interop Test With Python SDK
Run this from the PHP SDK repository to validate FF1 at-rest compatibility with the Python SDK:
cd /Users/anggitsy/Documents/myproject/ENCRYPT/sevola-sdk-php
python3 tests/interop/test_ff1_interop_with_python.py --use-docker
To validate specifically with PHP 7.3, build the local test image first:
docker build -t sevola-php73-test -f docker/php73/Dockerfile .
python3 tests/interop/test_ff1_interop_with_python.py --use-docker --php-docker-image sevola-php73-test
The test validates both directions:
- Python encrypts
numericandalphanumericpayloads, PHP decrypts them. - PHP encrypts the same payloads, Python decrypts them.
If PHP and Composer are installed locally, you can run without Docker after
composer install:
python3 tests/interop/test_ff1_interop_with_python.py
API Reference
Types
EncryptClientOptions
class EncryptClientOptions {
public $apiKey; // Required: API key for authentication
public $baseURL; // Optional: Base URL (default: "http://localhost:8082")
public $timeout; // Optional: Timeout in seconds (default: 30)
public $logger; // Optional: Enable debug logging (default: false)
public $enableCaching; // Optional: Enable key caching for non-dynamic keys (default: false)
public $cacheTTL; // Optional: Cache TTL in seconds for non-dynamic keys (default: 300)
}
Caching behaviour:
- Dynamic keys (used by
encryptTransitDynamic/decryptTransitDynamic) are always cached for 1 minute regardless ofenableCaching. - Regular REST/transit keys are only cached when
enableCaching: true, usingcacheTTL(default 5 minutes). - Call
clearCache()to evict all cached keys, orgetCacheSize()to inspect the cache.
Functions
EncryptClient::new(string $apiKey): EncryptClient
Creates a new client with default settings.
EncryptClient::newWithOptions(EncryptClientOptions $options): EncryptClient
Creates a new client with custom configuration.
Methods
encryptData(string $plaintext): string
Encrypts data using "rest" key type (for data at rest).
decryptData(string $cipherText): string
Decrypts data using "rest" key type.
encryptTransit(string $plaintext): string
Encrypts data using "transit" key type (for data in transit).
decryptTransit(string $cipherText): string
Decrypts data using "transit" key type.
encryptTransitDynamic(string $plaintext): string
Encrypts data using dynamic transit keys.
decryptTransitDynamic(string $cipherText): string
Decrypts data using dynamic transit keys.
encryptDataFF1(array $requests): array
Encrypts data using FF1 format-preserving encryption. Each request should have:
template: "numeric", "alfanum", or "alphanumeric"data: The data to encrypt
Returns an array of results with status and value keys.
decryptDataFF1(array $requests): array
Decrypts data using FF1 format-preserving encryption. Each request should have:
template: "numeric", "alfanum", or "alphanumeric"value: The encrypted value to decrypt
Returns an array of results with status and data keys.
clearCache(): void
Removes all cached encryption keys, forcing the next operation to fetch fresh keys from the server.
getCacheSize(): int
Returns the number of currently cached keys (useful for debugging/monitoring).
Short-String Handling (Magic Markers)
FF1 requires a minimum input length (4 chars for alfanum, 6 digits for numeric). The SDK transparently handles shorter inputs using a magic-marker scheme so callers never need to worry about length constraints.
How it works
Encryption: before passing the cleaned string to FF1, encryptDataFF1 calls escapeAndWrap:
- If the input contains the base marker → append the escape marker (collision prevention).
- If the input is shorter than the minimum → append the padding marker, the original length as a single digit, then random chars to reach the minimum.
- Otherwise the input is passed through unchanged.
Decryption: after FF1 decryption and special-char restoration, decryptDataFF1 calls unwrapAndUnescape:
- If the result ends with the escape marker → strip it.
- If the result contains the padding marker → read the length digit and return the original prefix.
- Otherwise the result is returned unchanged.
Marker reference
| Template | Base marker | Padding marker | Escape marker | Min length |
|---|---|---|---|---|
alfanum | Z9Y | Z9YX | Z9YZ | 4 |
numeric | 9078 | 90780 | 90781 | 6 |
Testing
Run the test suite:
# Run all tests
composer test
# Run tests with coverage
composer test -- --coverage
Building
Build the module:
# Install dependencies
composer install
# Run tests
composer test
Publishing
1. Tag a Release
# Tag the release
git tag v1.0.0
git push origin v1.0.0
2. Composer Package Repository
The package can be installed via Composer once published to a repository:
# Users can install with:
composer require ifabula/sevola-sdk-php
Dependencies
- PHP 7.3+ - Required for the library
- guzzlehttp/guzzle - HTTP client for API requests
- phpseclib/phpseclib - Big integer and AES primitives for FF1
- ext-openssl - OpenSSL extension for cryptographic operations
- ext-json - JSON extension for API responses
- ext-mbstring - Multibyte string handling for FF1 payloads
Examples
See the examples/ directory for more usage examples.
License
MIT © PT Ifabula Digital Kreasi
Support
For issues and questions:
- Create an issue on GitLab
- Email: kasfi.tamiya@ifabula.com