Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions docs/espocrm-extensions/encrypted-fields/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Encrypted Fields Extension

## Overview
Comment on lines +1 to +3
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All other EspoCRM extension docs in this repo appear to start with YAML front-matter (e.g., icon, title, description) that the docs site likely uses for navigation/metadata. This page currently starts directly with a # header, so it may not render consistently or be missing metadata; consider adding the same front-matter block at the top (see e.g. docs/espocrm-extensions/mask-field/index.md lines 1-5).

Copilot uses AI. Check for mistakes.
The **Encrypted Fields** extension adds a new field type `encrypted` to EspoCRM. This allows you to securely store sensitive information (such as API keys, secrets, or personal identification numbers) in the database using reversible encryption.

Unlike the standard `password` field which uses one-way hashing, the `encrypted` field allows the system to decrypt and retrieve the original value when needed (e.g., for integrations or processing), while keeping it secure in the database.

## Features
* **AES-256-CBC Encryption**: Uses industry-standard strong encryption.
* **Automatic Key Management**: Automatically generates a secure 256-bit encryption key (`extendedEncryptionKey`) upon first use if not already present.
* **Unique IV per Value**: Generates a random Initialization Vector (IV) for every record to ensure that identical values produce different encrypted strings.
* **Secure Storage**: The encrypted value and its IV are stored in separate columns in the database.
* **UI Security**: Fields behave like password fields in the user interface (masked input, masked display), preventing casual viewing of sensitive data.

![Encrypted Field](../../_static/images/espocrm-extensions/encrypted-fields/encrypted-field.png)

## Configuration
The extension uses a global encryption key stored in your EspoCRM configuration.

1. **Key Generation**: The first time you save a record with an encrypted field, the extension checks for `extendedEncryptionKey` in your configuration. If missing, it generates a secure 32-byte hex key and saves it to `data/config.php`.
2. **Manual Configuration**: You can optionally define the key manually in `data/config.php`:
```php
'extendedEncryptionKey' => 'YOUR_32_BYTE_HEX_KEY',
Comment thread
eymen-elkum marked this conversation as resolved.
```

> **Warning**: Do not lose this key! If the `extendedEncryptionKey` is lost or changed, all previously encrypted data will become unreadable.

## Usage

### Adding an Encrypted Field
1. Go to **Administration > Entity Manager**.
2. Select the entity where you want to add the field.
3. Click **Fields** and then **Add Field**.
4. Select **Encrypted** from the Type dropdown.
5. Configure the field label and name, then click **Save**.

![Add Encrypted Field](../../_static/images/espocrm-extensions/encrypted-fields/add-field.png)

### Developer Usage
To decrypt values programmatically (e.g., in a custom hook or service), use the `DecryptUtil` class provided by the extension.

```php
use Espo\Modules\EncryptedFields\Utils\DecryptUtil;

// ... inside your class method where $entity and $config are available

$fieldName = 'mySecretField';
$encryptedValue = $entity->get($fieldName);
$iv = $entity->get($fieldName . 'Iv'); // The IV is stored in a field with 'Iv' suffix

// Decrypt the value
$decryptedValue = DecryptUtil::from($encryptedValue, $iv, $config);

if ($decryptedValue !== false) {
// Use the decrypted value
}
```

## Database Structure
For a field named `bank_account_number`, the extension creates:
* `bank_account_number`: Stores the encrypted string (ciphertext).
* `bank_account_number_iv`: Stores the base64-encoded Initialization Vector.
Comment thread
eymen-elkum marked this conversation as resolved.

Both columns are required to decrypt the data.