Skip to content

Public API (non-internal, non-plugin implementations)#

api, public

// Structure of documents
└── src/
    └── Encryption/
        ├── EncryptedValue.php
        ├── EncryptionException.php
        ├── EncryptionKeyId.php
        ├── EncryptorInterface.php
    └── KeyManagement/
        ├── KeyActivatorException.php
        ├── KeyActivatorInterface.php
        ├── KeyGeneratorException.php
        ├── KeyGeneratorInterface.php
        ├── KeyPrunePlan.php
        ├── KeyPruneResult.php
        ├── KeyPrunerException.php
        ├── KeyPrunerInterface.php
        ├── KeyRotationException.php
        ├── KeyRotationOptions.php
        ├── KeyRotationPlan.php
        ├── KeyRotationResult.php
        ├── KeyRotatorInterface.php
        ├── KeyUsageTrackerInterface.php
        ├── Observers/
           ├── KeyActivatedObserverInterface.php
           ├── KeyDeletedObserverInterface.php
        ├── Port/
           └── KeyRegistryException.php
           └── KeyRegistryInterface.php
           └── KeyUsageMapping.php
           └── KeyUsageProviderInterface.php
           └── MutableKeyRegistryInterface.php
    └── KeyTransfer/
        ├── KeyTransferException.php
        ├── KeyTransferInterface.php
        ├── Port/
           └── KeyPackageCodecException.php
           └── KeyPackageCodecInterface.php
           └── KeyTransferPayloadHandlerException.php
           └── KeyTransferPayloadHandlerInterface.php
    └── Sodium/
        └── Exception/
            ├── SodiumKeyPairException.php
            ├── SodiumKeyPairNotFoundException.php
            ├── SodiumKeyPairOperationException.php
        └── SodiumKeyPairReadRepositoryInterface.php
        └── SodiumKeyPairWriteRepositoryInterface.php

Path: /src/Encryption/EncryptedValue.php#

namespace Drupal\easy_encryption\Encryption;

/**
 * Immutable value object representing encrypted data with key metadata.
 *
 * The ciphertext is stored internally as raw binary data. Use
 * getCiphertextHex() for storage in configuration, databases, or files that
 * expect string data.
 *
 * @immutable
 */
final class EncryptedValue
{
    public function __construct(
        private readonly string $ciphertext,
        public readonly EncryptionKeyId $keyId,
    ) {
        /* ... */
    }


    /**
     * Returns the raw binary ciphertext.
     *
     * @return string
     *   The binary ciphertext.
     */
    public function getCiphertext(): string
    {
        /* ... */
    }


    /**
     * Returns hex-encoded ciphertext for storage.
     *
     * Use this method when persisting encrypted data to configuration, databases,
     * or files. To reconstruct the object from stored hex, use
     * EncryptedValue::fromHex().
     *
     * @return string
     *   The hex-encoded ciphertext.
     */
    public function getCiphertextHex(): string
    {
        /* ... */
    }


    /**
     * Creates an EncryptedValue from hex-encoded ciphertext.
     *
     * Use this factory method when reading encrypted data from storage that was
     * previously encoded with getCiphertextHex().
     *
     * @param string $hex
     *   The hex-encoded ciphertext.
     * @param string $keyId
     *   The key pair identifier.
     *
     * @return static
     *   A new EncryptedValue instance.
     *
     * @throws \InvalidArgumentException
     *   If the ciphertext is empty or invalid, or the key ID is empty.
     */
    public static function fromHex(string $hex, string $keyId): self
    {
        /* ... */
    }
}

Path: /src/Encryption/EncryptionException.php#

namespace Drupal\easy_encryption\Encryption;

/**
 * Thrown when an encryption or decryption operation fails.
 */
class EncryptionException extends \RuntimeException
{
}

Path: /src/Encryption/EncryptionKeyId.php#

namespace Drupal\easy_encryption\Encryption;

/**
 * Value object representing an Encryption key identifier.
 *
 * Instances are immutable and always contain a safe, normalized identifier
 * consisting only of lowercase letters, digits, and underscores.
 *
 * This is a shared domain concept used by both key management (generation,
 * rotation, transfer) and encryption (encryptors/ciphertexts). It is not the
 * same as a Key module Key entity ID.
 */
final class EncryptionKeyId implements \Stringable
{
    private const NORMALIZED_PATTERN = '/^[a-z0-9_]+$/';

    /**
     * Creates a EncryptionKeyId from arbitrary input by normalizing it.
     *
     * Normalization rules:
     * - lowercases
     * - replaces any run of characters not in [a-z0-9_] with a single underscore
     * - trims leading/trailing underscores.
     */
    public static function fromUserInput(string $keyId): self
    {
        /* ... */
    }


    /**
     * Creates a EncryptionKeyId from an already-normalized value.
     */
    public static function fromNormalized(string $keyId): self
    {
        /* ... */
    }


    /**
     * {@inheritdoc}
     */
    public function __toString(): string
    {
        /* ... */
    }
}

Path: /src/Encryption/EncryptorInterface.php#

namespace Drupal\easy_encryption\Encryption;

/**
 * Defines an interface for encrypting and decrypting sensitive data.
 */
interface EncryptorInterface
{
    /**
     * Encrypts a value.
     *
     * @param string $value
     *   The plaintext value to encrypt.
     *
     * @return \Drupal\easy_encryption\Encryption\EncryptedValue
     *   The encrypted value with metadata.
     *
     * @throws \InvalidArgumentException
     *   If the value is empty.
     * @throws \Drupal\easy_encryption\Encryption\EncryptionException
     *   If encryption fails.
     */
    public function encrypt(
        #[\SensitiveParameter]
        string $value,
    ): EncryptedValue;


    /**
     * Decrypts a value.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptedValue $value
     *   The encrypted value to decrypt.
     *
     * @return string
     *   The decrypted plaintext.
     *
     * @throws \Drupal\easy_encryption\Encryption\EncryptionException
     *   If decryption fails.
     */
    public function decrypt(EncryptedValue $value): string;


    /**
     * Validates that encryption and decryption work correctly.
     *
     * Implementations may skip this test silently if the environment does not
     * support decryption (for example, when only a public key is available).
     *
     * @throws \Drupal\easy_encryption\Encryption\EncryptionException
     *   If the self-test fails.
     */
    public function selfTest(): void;
}

Path: /src/KeyManagement/KeyActivatorException.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Thrown when key activation fails.
 *
 * This exception is intended to be thrown by the KeyActivator application
 * service, so callers do not need to depend on the underlying repository
 * exception hierarchy.
 */
final class KeyActivatorException extends \RuntimeException
{
    /**
     * Creates an exception for a failed encryption key activation.
     *
     * @param string $keyId
     *   The key identifier that could not be activated.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception that caused activation to fail.
     *
     * @return self
     *   The exception instance.
     */
    public static function activationFailed(string $keyId, ?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyActivatorInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Application service for activating an encryption key.
 *
 * Activation sets which encryption key ID is considered active for new
 * encryption operations on the site.
 */
interface KeyActivatorInterface
{
    /**
     * Activates an existing encryption key by ID.
     *
     * Activation MUST be allowed when private key is missing, as long as a public
     * key exists (encrypt-only environments).
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   The encryption key identifier.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyActivatorException
     *   Thrown when activation fails.
     */
    public function activate(EncryptionKeyId $keyId): void;
}

Path: /src/KeyManagement/KeyGeneratorException.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Thrown when key generation or activation fails.
 */
final class KeyGeneratorException extends \RuntimeException
{
    /**
     * Creates an exception for a failed encryption key generation.
     *
     * @param string|null $keyId
     *   The key identifier, if one was known at the time of failure.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception that caused generation to fail.
     *
     * @return self
     *   The exception instance.
     */
    public static function generationFailed(?string $keyId = null, ?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyGeneratorInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Application service for generating and activating encryption keys.
 *
 * This service returns key identifiers, not key material, to keep the
 * application layer decoupled from the underlying cryptographic library.
 */
interface KeyGeneratorInterface
{
    /**
     * Generates and persists an encryption key.
     *
     * If no ID is provided, the generator MUST create a new identifier.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $keyId
     *   (optional) The encryption key identifier to use.
     *
     * @return \Drupal\easy_encryption\Encryption\EncryptionKeyId
     *   The encryption key identifier that was generated.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyGeneratorException
     *   Thrown when the encryption key generation fails.
     */
    public function generate(?EncryptionKeyId $keyId = null): EncryptionKeyId;
}

Path: /src/KeyManagement/KeyPrunePlan.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Describes what would be pruned without performing changes.
 *
 * @immutable
 */
final class KeyPrunePlan
{
    /**
     * Construct a KeyPrunePlan.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $activeKeyId
     *   The active encryption key ID, if any.
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $toDelete
     *   Encryption key IDs that would be deleted.
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $referenced
     *   Encryption key IDs referenced, in use.
     */
    public function __construct(
        public readonly ?EncryptionKeyId $activeKeyId,
        public readonly array $toDelete = [],
        public readonly array $referenced = [],
    ) {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyPruneResult.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Result of pruning unused encryption keys.
 *
 * @immutable
 */
final class KeyPruneResult
{
    /**
     * Construct a KeyPruneResult.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $deleted
     *   Deleted encryption key IDs.
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId[] $failed
     *   Encryption key IDs that failed deletion.
     */
    public function __construct(
        public readonly array $deleted = [],
        public readonly array $failed = [],
    ) {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyPrunerException.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Thrown when pruning unused encryption keys cannot be planned or started.
 */
final class KeyPrunerException extends \RuntimeException
{
    /**
     * Creates an exception for failures while building a prune plan.
     *
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function planFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures that prevent pruning from running at all.
     *
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function pruneFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyPrunerInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Application service for pruning unused encryption keys.
 */
interface KeyPrunerInterface
{
    /**
     * Builds a non-mutating plan describing what would be pruned.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyPrunerException
     *   Thrown when the plan cannot be computed.
     */
    public function planPruning(): KeyPrunePlan;


    /**
     * Deletes unused encryption keys.
     *
     * This operation returns partial results: failures are reported in the result
     * object rather than aborting the whole run.
     *
     * @return \Drupal\easy_encryption\KeyManagement\KeyPruneResult
     *   The prune result.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyPrunerException
     *   Thrown when the prune operation cannot start
     *   (for example, planning fails).
     */
    public function pruneUnused(): KeyPruneResult;
}

Path: /src/KeyManagement/KeyRotationException.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Exception is thrown by key rotation workflows.
 */
final class KeyRotationException extends \RuntimeException
{
    /**
     * Creates an exception for failures while building a rotation plan.
     *
     * Planning is a non-mutating operation (used for dry-run previews). This
     * exception indicates that the system could not compute a plan, typically due
     * to storage access errors or unexpected runtime issues.
     *
     * @param \Throwable|null $previous
     *   (optional) The underlying exception that caused planning to fail.
     *
     * @return self
     *   The exception instance.
     */
    public static function planFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures while rotating the active enc. keys.
     *
     * This exception indicates that generating or activating a new encryption key
     * failed.
     *
     * @param \Throwable|null $previous
     *   (optional) The underlying exception that caused rotation to fail.
     *
     * @return self
     *   The exception instance.
     */
    public static function rotateFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when re-encryption cannot be performed.
     *
     * This is used when the operation is not possible in the current environment,
     * for example because the private key is not available and existing encrypted
     * values therefore cannot be decrypted for re-encryption.
     *
     * @param string $reason
     *   A human-readable explanation of why re-encryption cannot be performed.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception, if any.
     *
     * @return self
     *   The exception instance.
     */
    public static function reencryptNotPossible(string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when one or more credentials fail to re-encrypt.
     *
     * @param int $failedCount
     *   The number of credentials that failed to re-encrypt.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception, if any.
     *
     * @return self
     *   The exception instance.
     */
    public static function reencryptFailed(int $failedCount, ?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyRotationOptions.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Options for the rotation operation.
 */
final class KeyRotationOptions
{
    public function __construct(
        public readonly bool $reencryptKeys = false,
        public readonly bool $failOnReencryptErrors = true,
    ) {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyRotationPlan.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Describes what would be re-encrypted without performing changes.
 *
 * @immutable
 */
final class KeyRotationPlan
{
    public function __construct(
        public readonly ?EncryptionKeyId $activeKeyId,
        public readonly int $total = 0,
        public readonly int $toUpdate = 0,
        public readonly int $toSkip = 0,
    ) {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyRotationResult.php#

namespace Drupal\easy_encryption\KeyManagement;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Result of rotating the active encryption key and optionally re-encrypting.
 *
 * @immutable
 */
final class KeyRotationResult
{
    public function __construct(
        public readonly ?EncryptionKeyId $oldActiveKeyId,
        public readonly EncryptionKeyId $newActiveKeyId,
        public readonly int $updated = 0,
        public readonly int $skipped = 0,
        public readonly int $failed = 0,
    ) {
        /* ... */
    }
}

Path: /src/KeyManagement/KeyRotatorInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Application service for planning and performing encryption key rotation.
 */
interface KeyRotatorInterface
{
    /**
     * Builds a non-mutating plan describing what would change.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyRotationException
     *   If the plan cannot be computed.
     */
    public function plan(bool $includeReencryptCounts = true): KeyRotationPlan;


    /**
     * Rotates the active encryption key and optionally re-encrypts credentials.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\KeyRotationException
     *   If rotation fails, or re-encryption fails and failOnReencryptErrors
     *   is TRUE.
     */
    public function rotate(KeyRotationOptions $options): KeyRotationResult;
}

Path: /src/KeyManagement/KeyUsageTrackerInterface.php#

namespace Drupal\easy_encryption\KeyManagement;

/**
 * Public API for tracking encryption key usage across the entire system.
 */
interface KeyUsageTrackerInterface
{
    /**
     * Returns the aggregated mapping of all consumers and their encryption keys.
     *
     * @return array{result: array<string, \Drupal\easy_encryption\KeyManagement\Port\KeyUsageMapping>, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   The 'result' is keyed by consumer ID.
     *   'cacheability' applies to the entire set.
     */
    public function getKeyUsageMapping(): array;
}

Path: /src/KeyManagement/Observers/KeyActivatedObserverInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Observers;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Contract for encryption key activation observers.
 */
interface KeyActivatedObserverInterface
{
    /**
     * Act when an encryption key gets activated.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $activeKeyId
     *   The ID of the activated encryption key.
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId|null $previousKeyId
     *   The ID of the previously active key if there was any.
     */
    public function onKeyActivation(EncryptionKeyId $activeKeyId, ?EncryptionKeyId $previousKeyId): void;
}

Path: /src/KeyManagement/Observers/KeyDeletedObserverInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Observers;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Contract for encryption key deletion observers.
 */
interface KeyDeletedObserverInterface
{
    /**
     * Act when an encryption key gets deleted.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   The ID of the activated encryption key.
     */
    public function onKeyDeletion(EncryptionKeyId $keyId): void;
}

Path: /src/KeyManagement/Port/KeyRegistryException.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

/**
 * Thrown when the encryption key registry cannot be read or written.
 *
 * This exception is intended to be thrown by KeyRegistryInterface
 * implementations, so callers do not need to depend on underlying storage
 * exceptions (config, database, etc.).
 */
final class KeyRegistryException extends \RuntimeException
{
    /**
     * Creates an exception for failures while reading registry data.
     *
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function readFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures while registering a key id.
     *
     * @param string $keyId
     *   The encryption key identifier that could not be registered.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function registerFailed(string $keyId, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures while unregistering a key id.
     *
     * @param string $keyId
     *   The encryption key identifier that could not be registered.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function unregisterFailed(string $keyId, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures while setting the active key id.
     *
     * @param string $keyId
     *   The encryption key identifier that could not be activated.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function setActiveFailed(string $keyId, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when attempting to set an active key that is unknown.
     *
     * @param string $keyId
     *   The encryption key identifier.
     */
    public static function unknownKey(string $keyId): self
    {
        /* ... */
    }
}

Path: /src/KeyManagement/Port/KeyRegistryInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Read-only registry of known encryption keys and the active key.
 */
interface KeyRegistryInterface
{
    /**
     * Lists encryption key IDs known to this site.
     *
     * @return array{result: \Drupal\easy_encryption\Encryption\EncryptionKeyId[], cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   Known key ids plus cacheability metadata.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When registry storage cannot be read.
     */
    public function listKnownKeyIds(): array;


    /**
     * Returns the active encryption key id, if any.
     *
     * @return array{result: \Drupal\easy_encryption\Encryption\EncryptionKeyId|null, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   Active key id plus cacheability metadata.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When registry storage cannot be read.
     */
    public function getActiveKeyId(): array;


    /**
     * Checks whether a key id is known to the registry.
     *
     * @return array{result: bool, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   TRUE if known plus cacheability metadata.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When registry storage cannot be read.
     */
    public function isKnown(EncryptionKeyId $key_id): array;
}

Path: /src/KeyManagement/Port/KeyUsageMapping.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

use Drupal\Core\Cache\CacheBackendInterface as CacheBackendInterface;
use Drupal\Core\Cache\CacheableDependencyInterface as CacheableDependencyInterface;
use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Represents an encryption key used by a specific consumer with cacheability.
 */
final class KeyUsageMapping implements CacheableDependencyInterface
{
    /**
     * Constructs a new object.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   The encryption key being used.
     * @param \Drupal\Core\Cache\CacheableDependencyInterface|null $cacheability
     *   Optional cacheability metadata for this specific mapping.
     */
    public function __construct(
        public readonly EncryptionKeyId $keyId,
        private readonly ?CacheableDependencyInterface $cacheability = null,
    ) {
        /* ... */
    }


    /**
     * {@inheritdoc}
     */
    public function getCacheContexts(): array
    {
        /* ... */
    }


    /**
     * {@inheritdoc}
     */
    public function getCacheTags(): array
    {
        /* ... */
    }


    /**
     * {@inheritdoc}
     */
    public function getCacheMaxAge(): int
    {
        /* ... */
    }
}

Path: /src/KeyManagement/Port/KeyUsageProviderInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

/**
 * Interface for reporters that identify encryption key dependencies.
 */
interface KeyUsageProviderInterface
{
    /**
     * Returns a mapping of consumers.
     *
     * @return array{result: array<string, \Drupal\easy_encryption\KeyManagement\Port\KeyUsageMapping>, cacheability: \Drupal\Core\Cache\CacheableDependencyInterface}
     *   The 'result' is keyed by consumer ID. 'cacheability' applies to the
     *   entire set.
     */
    public function getKeyUsageMapping(): array;
}

Path: /src/KeyManagement/Port/MutableKeyRegistryInterface.php#

namespace Drupal\easy_encryption\KeyManagement\Port;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Mutable registry of known encryption keys and the active key.
 */
interface MutableKeyRegistryInterface
{
    /**
     * Registers a key id as known.
     *
     * Implementations must be idempotent.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When the registry cannot be written.
     */
    public function register(EncryptionKeyId $key_id): void;


    /**
     * Unregisters a key id from the known list.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When the registry cannot be written.
     */
    public function unregister(EncryptionKeyId $key_id): void;


    /**
     * Sets the active encryption key id.
     *
     * Implementations should either:
     * - implicitly register the key id if missing, or
     * - throw unknownKey() if the key id is not registered.
     *
     * Pick one policy and keep it consistent. For export/import and for
     * predictable behavior, I recommend: throw if unknown.
     *
     * @throws \Drupal\easy_encryption\KeyManagement\Port\KeyRegistryException
     *   When the registry cannot be written or the key is unknown.
     */
    public function setActive(EncryptionKeyId $key_id): void;
}

Path: /src/KeyTransfer/KeyTransferException.php#

namespace Drupal\easy_encryption\KeyTransfer;

/**
 * Thrown when key transfer operations fail at the application layer.
 */
final class KeyTransferException extends \RuntimeException
{
    /**
     * Creates an exception for an invalid package.
     *
     * @param string $reason
     *   Human-readable validation error.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function invalidPackage(string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when no payload handler supports the package payload.
     *
     * @param string $reason
     *   Human-readable explanation, for example "Unsupported format foo".
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function unsupportedPayload(string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for export failures.
     *
     * @param string $keyId
     *   The key id that was being exported.
     * @param string $reason
     *   Human-readable explanation of the failure.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function exportFailed(string $keyId, string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for import failures.
     *
     * @param string $reason
     *   Human-readable explanation of the failure.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function importFailed(string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures while activating a key after import.
     *
     * @param string $keyId
     *   The imported key id that could not be activated.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function activationFailed(string $keyId, ?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyTransfer/KeyTransferInterface.php#

namespace Drupal\easy_encryption\KeyTransfer;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Application service for importing/exporting keys as portable packages.
 */
interface KeyTransferInterface
{
    /**
     * Exports a known key as a portable package string.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\KeyTransferException
     *   When export fails or cannot be performed.
     */
    public function exportKey(EncryptionKeyId $keyId): string;


    /**
     * Imports a portable package string & optionally activates the imported key.
     *
     * @return array{key_id: \Drupal\easy_encryption\Encryption\EncryptionKeyId, activated: bool}
     *   The imported key id and whether activation was requested/performed.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\KeyTransferException
     *   When import fails or the package is invalid/unsupported.
     */
    public function importKey(string $package, bool $activate = false): array;
}

Path: /src/KeyTransfer/Port/KeyPackageCodecException.php#

namespace Drupal\easy_encryption\KeyTransfer\Port;

/**
 * Thrown when a key package cannot be encoded or decoded.
 */
final class KeyPackageCodecException extends \RuntimeException
{
    /**
     * Creates an exception for failures while encoding a key package.
     *
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function encodeFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for failures while decoding a key package.
     *
     * @param string $reason
     *   Human-readable error describing what part of decoding failed.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function decodeFailed(string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyTransfer/Port/KeyPackageCodecInterface.php#

namespace Drupal\easy_encryption\KeyTransfer\Port;

/**
 * Encodes/decodes key transfer packages (envelope only).
 *
 * The codec is format-agnostic: algorithm-specific data is carried in the
 * payload structure and interpreted by payload handlers.
 */
interface KeyPackageCodecInterface
{
    /**
     * Encodes the package structure into a portable string.
     *
     * @param array<string,mixed> $data
     *   Package data, typically with keys like 'key_id' and 'payload'.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyPackageCodecException
     *   When the package cannot be encoded.
     */
    public function encode(array $data): string;


    /**
     * Decodes a portable string into the package structure.
     *
     * @return array<string,mixed>
     *   Package data.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyPackageCodecException
     *   When the package cannot be decoded.
     */
    public function decode(string $text): array;
}

Path: /src/KeyTransfer/Port/KeyTransferPayloadHandlerException.php#

namespace Drupal\easy_encryption\KeyTransfer\Port;

/**
 * Thrown when a key transfer payload handler cannot import or export a payload.
 */
final class KeyTransferPayloadHandlerException extends \RuntimeException
{
    /**
     * Creates an exception for invalid payload content.
     *
     * @param string $reason
     *   Human-readable validation error.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function invalidPayload(string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when exporting a key is not possible.
     *
     * @param string $keyId
     *   The key id that could not be exported.
     * @param string $reason
     *   Human-readable explanation.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function exportNotPossible(string $keyId, string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when importing a key is not possible.
     *
     * @param string $keyId
     *   The key id that could not be imported.
     * @param string $reason
     *   Human-readable explanation.
     * @param \Throwable|null $previous
     *   (optional) The underlying exception.
     */
    public static function importNotPossible(string $keyId, string $reason, ?\Throwable $previous = null): self
    {
        /* ... */
    }
}

Path: /src/KeyTransfer/Port/KeyTransferPayloadHandlerInterface.php#

namespace Drupal\easy_encryption\KeyTransfer\Port;

use Drupal\easy_encryption\Encryption\EncryptionKeyId as EncryptionKeyId;

/**
 * Port for handling algorithm-specific key transfer payloads.
 *
 * Implementations are discovered via tagged services.
 *
 * @template TPayload of array
 */
interface KeyTransferPayloadHandlerInterface
{
    /**
     * Returns TRUE if this handler supports importing the given payload.
     *
     * This method must be defensive: it can receive any decoded payload data.
     *
     * @param array $payload
     *   Payload data.
     *
     * @phpstan-assert-if-true TPayload $payload
     */
    public function applies(array $payload): bool;


    /**
     * Exports key material as payload data.
     *
     * @return TPayload
     *   Payload data for this handler.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyTransferPayloadHandlerException
     *   When export cannot be performed.
     */
    public function exportPayload(EncryptionKeyId $keyId): array;


    /**
     * Imports key material from payload data for the provided key id.
     *
     * This method must not activate the key. Activation is application logic.
     *
     * @param \Drupal\easy_encryption\Encryption\EncryptionKeyId $keyId
     *   Key identifier from the package envelope.
     * @param TPayload $payload
     *   Payload data for this handler.
     *
     * @throws \Drupal\easy_encryption\KeyTransfer\Port\KeyTransferPayloadHandlerException
     *   When import cannot be performed.
     */
    public function importPayload(EncryptionKeyId $keyId, array $payload): void;
}

Path: /src/Sodium/Exception/SodiumKeyPairException.php#

namespace Drupal\easy_encryption\Sodium\Exception;

/**
 * Base exception for sodium key pair repository failures.
 *
 * All exceptions thrown by Sodium repositories
 * implementations SHOULD extend this class so that callers can
 * catch and handle repository errors in a generic way.
 */
class SodiumKeyPairException extends \RuntimeException
{
    /**
     * Creates an exception for a key pair that was not found.
     *
     * @param string $id
     *   The key pair identifier.
     *
     * @return self
     *   The exception instance.
     */
    public static function notFound(string $id): self
    {
        /* ... */
    }
}

Path: /src/Sodium/Exception/SodiumKeyPairNotFoundException.php#

namespace Drupal\easy_encryption\Sodium\Exception;

/**
 * Thrown when a requested key pair cannot be found.
 */
final class SodiumKeyPairNotFoundException extends SodiumKeyPairException
{
    /**
     * Creates an exception for a missing key pair identifier.
     *
     * @param string $id
     *   The missing key pair identifier.
     * @param \Throwable|null $previous
     *   (optional) The previous throwable.
     *
     * @return static
     *   The exception instance.
     */
    public static function forId(string $id, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for a missing active key pair.
     *
     * @return self
     *   The exception instance.
     */
    public static function forActive(): self
    {
        /* ... */
    }
}

Path: /src/Sodium/Exception/SodiumKeyPairOperationException.php#

namespace Drupal\easy_encryption\Sodium\Exception;

/**
 * Thrown when a key pair operation fails.
 *
 * This exception covers failures related to key pair generation, storage,
 * retrieval, deletion, and cryptographic operations that depend on key
 * availability or validity.
 */
final class SodiumKeyPairOperationException extends SodiumKeyPairException
{
    /**
     * Creates an exception for a failed generation or activation.
     *
     * @param \Throwable|null $previous
     *   (optional) The previous throwable.
     *
     * @return self
     *   The exception instance.
     */
    public static function generationFailed(?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for a failed load of an existing key pair.
     *
     * @param string $id
     *   The key pair identifier.
     * @param \Throwable|null $previous
     *   (optional) The previous throwable.
     *
     * @return self
     *   The exception instance.
     */
    public static function loadFailed(string $id, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for an attempt to delete the active key pair.
     *
     * @param string $id
     *   The key pair identifier.
     *
     * @return self
     *   The exception instance.
     */
    public static function cannotDeleteActive(string $id): self
    {
        /* ... */
    }


    /**
     * Creates an exception for a failed deletion operation.
     *
     * @param string $id
     *   The key pair identifier.
     * @param \Throwable|null $previous
     *   (optional) The previous throwable.
     *
     * @return self
     *   The exception instance.
     */
    public static function deleteFailed(string $id, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception for a failed decryption operation.
     *
     * @param string $keyId
     *   The key pair identifier.
     * @param \Throwable|null $previous
     *   (optional) The previous throwable.
     *
     * @return self
     *   The exception instance.
     */
    public static function decryptionFailed(string $keyId, ?\Throwable $previous = null): self
    {
        /* ... */
    }


    /**
     * Creates an exception when the private key is not available.
     *
     * This typically occurs in encrypt-only environments where the private key
     * has been intentionally excluded for security reasons.
     *
     * @param string $keyId
     *   The key pair identifier.
     *
     * @return self
     *   The exception instance.
     */
    public static function privateKeyNotAvailable(string $keyId): self
    {
        /* ... */
    }


    /**
     * Creates an exception when the public key is not available.
     *
     * @param string $keyId
     *   The key pair identifier.
     *
     * @return self
     *   The exception instance.
     */
    public static function publicKeyNotAvailable(string $keyId): self
    {
        /* ... */
    }


    /**
     * Creates an exception when keypair construction fails.
     *
     * This occurs when sodium_crypto_box_keypair_from_secretkey_and_publickey()
     * throws an exception, typically indicating key corruption or mismatch.
     *
     * @param string $keyId
     *   The key pair identifier.
     * @param \Throwable $previous
     *   The previous throwable from the Sodium operation.
     *
     * @return self
     *   The exception instance.
     */
    public static function keypairConstructionFailed(string $keyId, \Throwable $previous): self
    {
        /* ... */
    }
}

Path: /src/Sodium/SodiumKeyPairReadRepositoryInterface.php#

namespace Drupal\easy_encryption\Sodium;

/**
 * Read-only repository for sodium key pairs.
 */
interface SodiumKeyPairReadRepositoryInterface
{
    /**
     * Returns a key pair by its identifier.
     *
     * Implementations MAY omit the private key when the current environment is
     * not allowed to perform decryption.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairNotFoundException
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     */
    public function getKeyPairById(string $id): SodiumKeyPair;


    /**
     * Returns identifiers for all stored key pairs.
     *
     * Implementations MUST return identifiers for all key pairs known to
     * the repository, regardless of whether the corresponding private
     * keys are available in the current environment.
     *
     * @return string[]
     *   An array of key pair identifiers.
     */
    public function listKeyPairIds(): array;
}

Path: /src/Sodium/SodiumKeyPairWriteRepositoryInterface.php#

namespace Drupal\easy_encryption\Sodium;

/**
 * Write repository for sodium key pairs.
 */
interface SodiumKeyPairWriteRepositoryInterface
{
    /**
     * Generates and persists a new key pair with the given id.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If generation or persistence fails.
     */
    public function generateKeyPair(string $id): void;


    /**
     * Deletes persisted key material for the given id.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If deletion fails.
     */
    public function deleteKeyPair(string $id): void;


    /**
     * Writes/updates public key material.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If persistence fails.
     */
    public function upsertPublicKey(string $id, string $publicKeyBin): void;


    /**
     * Writes/updates private key material.
     *
     * @throws \Drupal\easy_encryption\Sodium\Exception\SodiumKeyPairOperationException
     *   If persistence fails.
     */
    public function upsertPrivateKey(string $id, string $privateKeyBin): void;
}

File Statistics - Size: 40.72 KB - Lines: 1672 File: core/api.md