sikkerkey / sdk
SikkerKey PHP SDK — read secrets with Ed25519 machine authentication
Requires
- php: >=8.1
- ext-curl: *
- ext-json: *
- ext-sodium: *
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-24 16:32:53 UTC
README
Use the official SikkerKey PHP SDK to give a PHP application read access to the secrets its machine is authorized to use.
The SDK can:
- Read standard and structured secrets.
- List the secrets available to a machine.
- Export accessible secrets as application-friendly key/value pairs.
- Use persistent machine identities or memory-only ephemeral identities.
- Keep an optional encrypted fallback cache for temporary service or network outages.
After the client is initialized, every secret request is authenticated with the machine's Ed25519 identity. The SDK supports PHP 8.1 or newer and has no third-party Composer package dependencies.
Requirements
- PHP 8.1 or newer.
- The
sodium,curl, andjsonPHP extensions. - A SikkerKey vault and machine identity.
- The
opensslextension when using the optional encrypted cache.
Install the SDK
composer require sikkerkey/sdk
Read your first secret
<?php require_once __DIR__ . '/vendor/autoload.php'; use SikkerKey\SikkerKey; $sikkerKey = SikkerKey::create('vault_abc123'); $apiKey = $sikkerKey->getSecret('sk_stripe_key');
The SDK loads the machine identity from:
~/.sikkerkey/vaults/vault_abc123/identity.json
It signs the request with the machine's Ed25519 private key and returns the secret value as a string. Your application's access remains limited by the machine's configured access.
All SDK calls are synchronous.
Create a client
// Select a registered vault. $byVault = SikkerKey::create('vault_abc123'); // Load a specific identity file. $byPath = SikkerKey::create( '/etc/sikkerkey/vaults/vault_abc123/identity.json' ); // Use SIKKERKEY_IDENTITY or auto-select the only registered vault. $automatically = SikkerKey::create();
When no argument is supplied, the SDK checks SIKKERKEY_IDENTITY first. If that variable is not set, it uses the only registered vault under ~/.sikkerkey/vaults/.
If more than one vault is registered, select one explicitly. Missing identities, unreadable keys, invalid identity files, and ambiguous vault selection produce ConfigurationError.
The vault_ prefix is added when a vault ID is supplied without it.
Use a different identity directory
export SIKKERKEY_HOME=/var/lib/sikkerkey
The SDK will look under:
/var/lib/sikkerkey/vaults/<vault-id>/identity.json
Use an ephemeral identity
SikkerKey::bootstrapInMemory is designed for short-lived or read-only environments where an identity should not be stored on disk.
$sikkerKey = SikkerKey::bootstrapInMemory( getenv('SIKKERKEY_VAULT_ID'), getenv('SIKKERKEY_ENROLLMENT_TOKEN'), ); $databaseUrl = $sikkerKey->getSecret('sk_db_prod');
During bootstrap, the SDK:
- Generates an Ed25519 key pair in memory.
- Uses the enrollment token to register an ephemeral machine.
- Keeps the private key inside the running PHP process.
- Returns a client ready to read the secrets allowed by the token's access policy.
Nothing is written to disk. The private key disappears when the process exits.
The enrollment token registers the machine; it does not read secrets itself. The resulting machine remains subject to the token's permitted scope, use limit, hostname rules, and machine lifetime. Reads produce AuthenticationError after the machine expires.
Set the machine hostname and name
$sikkerKey = SikkerKey::bootstrapInMemory( $vaultId, $enrollmentToken, hostname: 'worker-1', name: 'invoice-runner', );
hostname defaults to the HOSTNAME environment variable and then to serverless. A name pattern configured on the enrollment token takes precedence over name.
For reliable ephemeral deployments:
- Set a machine lifetime long enough for the workload to finish.
- Allow enough token uses for expected cold starts and concurrency.
- Use a unique name pattern such as
worker-{uuid8}. - Ensure the vault's IP allowlist permits the workload's outbound address when an allowlist is enabled.
Each active ephemeral machine uses a machine slot until it expires.
Read secrets
Standard secrets
$apiKey = $sikkerKey->getSecret('sk_stripe_prod');
Structured secrets
$database = $sikkerKey->getFields('sk_db_prod'); $host = $database['host']; $username = $database['username']; $password = $database['password'];
getFields expects a JSON object. Scalar properties become strings; nested values are returned as JSON text. Another structure produces SecretStructureError.
Use getField when the application needs one field:
$password = $sikkerKey->getField( 'sk_db_prod', 'password' );
A missing field produces FieldNotFoundError with the available field names.
Discover accessible secrets
$secrets = $sikkerKey->listSecrets(); foreach ($secrets as $secret) { echo "{$secret->id}: {$secret->name}\n"; }
Limit the result to one project:
$productionSecrets = $sikkerKey->listSecretsByProject( 'proj_production' );
Each SecretListItem contains:
| Property | Type | Meaning |
|---|---|---|
id |
string |
Secret ID used by read methods |
name |
string |
Display name |
fieldNames |
?string |
Optional structured-field metadata |
projectId |
?string |
Owning project, when present |
Listing returns metadata, not secret values.
Export secrets for application configuration
$configuration = $sikkerKey->export();
Limit the export to a project:
$productionConfiguration = $sikkerKey->export('proj_production');
The returned array<string,string> uses uppercase environment-style names. Structured secrets are expanded into one entry per field:
API_KEY
DB_CREDENTIALS_HOST
DB_CREDENTIALS_USERNAME
DB_CREDENTIALS_PASSWORD
You can apply the result to the current process:
foreach ($configuration as $name => $value) { putenv("{$name}={$value}"); }
Continue reads during temporary outages
The fallback cache is disabled by default:
$sikkerKey = SikkerKey::create('vault_abc123') ->enableCache();
After it is enabled, successful getSecret reads are stored under:
~/.sikkerkey/vaults/<vault-id>/cache/
getFields and getField use getSecret, so their successful reads are cached too. Cache writes are best-effort and cannot turn a successful live read into a failure.
The SDK can return a cached value after a network failure, request timeout, or HTTP 502, 503, 504, 520 through 527, or 530.
Authentication failures, revoked access, missing secrets, rate limits, and other authoritative responses are never replaced by cached values.
Entries use AES-256-GCM with a key derived from the machine's Ed25519 identity and vault ID. Tampered entries and entries belonging to another identity are rejected. The .skc format is compatible with other SikkerKey SDKs and the SikkerKey CLI.
Limit cache age and observe fallback use
$sikkerKey = SikkerKey::create('vault_abc123') ->enableCache( maxAge: 3600, onFallback: static function ( string $secretId, int $cachedAt ): void { error_log( "Using cached value for {$secretId} from epoch {$cachedAt}" ); }, );
maxAge is measured in seconds. Passing null means no automatic expiry. The callback is optional; fallback is otherwise silent.
The cache is intended for a host with a persistent, protected identity directory, not a memory-only identity that disappears with the process.
Work with more than one vault
$production = SikkerKey::create('vault_production'); $staging = SikkerKey::create('vault_staging'); $productionKey = $production->getSecret('sk_api_key'); $stagingKey = $staging->getSecret('sk_api_key');
List locally registered vault IDs:
$vaultIds = SikkerKey::listVaults();
The returned list is sorted alphabetically.
Inspect the active machine
The identity values are available as read-only properties:
echo $sikkerKey->machineId; echo $sikkerKey->machineName; echo $sikkerKey->vaultId; echo $sikkerKey->apiUrl;
They are also available through methods:
echo $sikkerKey->machineId(); echo $sikkerKey->machineName(); echo $sikkerKey->vaultId(); echo $sikkerKey->apiUrl();
| Value | Meaning |
|---|---|
machineId |
Machine UUID assigned by SikkerKey |
machineName |
Machine name assigned during provisioning or enrollment |
vaultId |
Vault associated with the identity |
apiUrl |
Service endpoint stored in the identity |
Handle errors
use SikkerKey\AccessDeniedError; use SikkerKey\ApiError; use SikkerKey\AuthenticationError; use SikkerKey\ConfigurationError; use SikkerKey\NotFoundError; use SikkerKey\RateLimitedError; try { $value = $sikkerKey->getSecret('sk_example'); } catch (NotFoundError $error) { error_log('Secret not found'); } catch (AccessDeniedError $error) { error_log('Access denied'); } catch (AuthenticationError $error) { error_log('Authentication failed'); } catch (RateLimitedError $error) { error_log('Request remained rate-limited'); } catch (ApiError $error) { error_log( "SikkerKey returned HTTP {$error->httpStatus}" ); } catch (ConfigurationError $error) { error_log('Machine identity could not be loaded'); }
Exception reference
| Exception | When it is used |
|---|---|
ConfigurationError |
Identity, key, vault-selection, or bootstrap configuration is invalid |
AuthenticationError |
HTTP 401 |
AccessDeniedError |
HTTP 403 |
NotFoundError |
HTTP 404 |
ConflictError |
HTTP 409 |
RateLimitedError |
HTTP 429 |
ServerSealedError |
HTTP 503 |
ApiError |
Another HTTP or network error; inspect httpStatus |
SecretStructureError |
getFields or getField received a non-object value |
FieldNotFoundError |
The requested structured field does not exist |
Network failures and request timeouts use ApiError with httpStatus === 0.
Retries and timeout
Authenticated secret requests retry network failures and HTTP 429 or 503 responses up to three times. Retries wait 1, 2, and 4 seconds, and every attempt receives a fresh timestamp and nonce.
Connection and total request timeouts are each configured for 15 seconds. Other HTTP responses are returned immediately as their matching exception.
Feature-to-API reference
| What you want to do | SDK API | Result |
|---|---|---|
| Create a client from disk | SikkerKey::create(vaultOrPath?) |
SikkerKey |
| Create an ephemeral client | SikkerKey::bootstrapInMemory(vaultId, token, hostname?, name?) |
SikkerKey |
| List locally registered vaults | SikkerKey::listVaults() |
string[] |
| Enable outage fallback | enableCache(maxAge?, onFallback?) |
The same SikkerKey client |
| Read a standard secret | getSecret(secretId) |
string |
| Read every structured field | getFields(secretId) |
array<string,string> |
| Read one structured field | getField(secretId, field) |
string |
| List accessible secrets | listSecrets() |
SecretListItem[] |
| List accessible secrets in a project | listSecretsByProject(projectId) |
SecretListItem[] |
| Export accessible values | export(projectId?) |
array<string,string> |
The PHP SDK does not run a background watcher. Applications that need change notifications can refresh values on their own schedule.
Runtime footprint
The SDK uses:
ext-sodiumfor Ed25519 key generation and signing.ext-curlfor HTTPS requests.ext-jsonfor serialization.ext-opensslfor the optional AES-GCM cache.
It has no third-party Composer package dependencies.
Documentation
License
The SikkerKey PHP SDK is available under the MIT License.