@growy/strapi-plugin-encrypted-field 2.4.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +58 -55
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [2.4.3] - 2026-02-26
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- README full consistency review: Node.js requirement corrected to 23.x, redundant feature bullets consolidated, Option B clarified, rebuild step scoped to first install only, Key Rotation guide expanded with multi-line command for readability.
|
|
9
|
+
|
|
5
10
|
## [2.4.2] - 2026-02-26
|
|
6
11
|
|
|
7
12
|
### Changed
|
package/README.md
CHANGED
|
@@ -12,15 +12,20 @@ Official **Growy AI** plugin for Strapi that provides a custom encrypted text fi
|
|
|
12
12
|
- ✅ **Automatic encryption** AES-256-GCM on save
|
|
13
13
|
- ✅ **Transparent decryption** on read (admin panel and API)
|
|
14
14
|
- ✅ **Backend validation** with regex and length constraint support
|
|
15
|
-
- ✅ **
|
|
16
|
-
- ✅ **
|
|
17
|
-
- ✅ **
|
|
18
|
-
- ✅ **Multi-language support (i18n)**: English and Spanish
|
|
15
|
+
- ✅ **Admin UI** with show/hide toggle, resizable inputs and copy to clipboard
|
|
16
|
+
- ✅ **Copy notifications** with confirmation toast when copying values
|
|
17
|
+
- ✅ **Multi-language support (i18n)**: English and Spanish in the admin panel
|
|
19
18
|
- ✅ **Robust key management** with validation and clear error messages
|
|
20
19
|
- ✅ **Encrypted data** in database with unique IV and Auth Tag per operation
|
|
21
20
|
- ✅ **Reusable** in any collection or component
|
|
22
21
|
- ✅ **Full support** for nested components and complex structures
|
|
23
22
|
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- **Strapi**: v5.0.0 or higher
|
|
26
|
+
- **Node.js**: 18.x - 23.x
|
|
27
|
+
- **npm**: 6.0.0 or higher
|
|
28
|
+
|
|
24
29
|
## Installation
|
|
25
30
|
|
|
26
31
|
```bash
|
|
@@ -55,14 +60,14 @@ ENCRYPTION_KEY=your_64_character_hex_key_here
|
|
|
55
60
|
|
|
56
61
|
#### Option B: Configuration file
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
Use this option if you need to read the key from a different environment variable name or from a secrets provider:
|
|
59
64
|
|
|
60
65
|
```javascript
|
|
61
66
|
module.exports = ({ env }) => ({
|
|
62
67
|
'encrypted-field': {
|
|
63
68
|
enabled: true,
|
|
64
69
|
config: {
|
|
65
|
-
encryptionKey: env('
|
|
70
|
+
encryptionKey: env('MY_CUSTOM_SECRET_KEY'),
|
|
66
71
|
},
|
|
67
72
|
},
|
|
68
73
|
});
|
|
@@ -70,11 +75,13 @@ module.exports = ({ env }) => ({
|
|
|
70
75
|
|
|
71
76
|
#### Generate a secure key
|
|
72
77
|
|
|
78
|
+
Run this command once to generate a valid key:
|
|
79
|
+
|
|
73
80
|
```bash
|
|
74
81
|
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
75
82
|
```
|
|
76
83
|
|
|
77
|
-
This
|
|
84
|
+
This outputs a 64-character hexadecimal key (32 bytes) ready to use.
|
|
78
85
|
|
|
79
86
|
⚠️ **CRITICAL - Key Management**:
|
|
80
87
|
- **Store the key securely** (secrets manager, encrypted environment variables)
|
|
@@ -83,37 +90,15 @@ This will generate a 64-character hexadecimal key (32 bytes).
|
|
|
83
90
|
- **Use the same key** across all environments sharing the same database
|
|
84
91
|
- **For production**, consider services like AWS Secrets Manager, HashiCorp Vault or similar
|
|
85
92
|
|
|
86
|
-
### 3. Rebuild the admin
|
|
93
|
+
### 3. Rebuild the admin panel (first install only)
|
|
94
|
+
|
|
95
|
+
After installing the plugin for the first time, rebuild the admin panel:
|
|
87
96
|
|
|
88
97
|
```bash
|
|
89
98
|
npm run build
|
|
90
99
|
npm run develop
|
|
91
100
|
```
|
|
92
101
|
|
|
93
|
-
## Requirements
|
|
94
|
-
|
|
95
|
-
- **Strapi**: v5.0.0 or higher
|
|
96
|
-
- **Node.js**: 18.x - 22.x
|
|
97
|
-
- **npm**: 6.0.0 or higher
|
|
98
|
-
|
|
99
|
-
## Data Validation
|
|
100
|
-
|
|
101
|
-
The plugin supports validation before encryption:
|
|
102
|
-
|
|
103
|
-
### Configure regex validation
|
|
104
|
-
|
|
105
|
-
1. In Content-Type Builder, select the encrypted field
|
|
106
|
-
2. Go to the **"Advanced Settings"** tab
|
|
107
|
-
3. In **"RegEx pattern"**, enter your regular expression
|
|
108
|
-
4. Save the changes
|
|
109
|
-
|
|
110
|
-
**Example**: To validate API key format:
|
|
111
|
-
```regex
|
|
112
|
-
^sk-[a-zA-Z0-9]{32}$
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
If the value does not match the pattern, an error will be thrown before encryption.
|
|
116
|
-
|
|
117
102
|
## Usage
|
|
118
103
|
|
|
119
104
|
### 1. Add an encrypted field to a collection
|
|
@@ -125,23 +110,24 @@ If the value does not match the pattern, an error will be thrown before encrypti
|
|
|
125
110
|
5. Set the field name
|
|
126
111
|
6. Save and restart Strapi
|
|
127
112
|
|
|
128
|
-
### 2. Using the field
|
|
113
|
+
### 2. Using the field in the admin panel
|
|
129
114
|
|
|
130
115
|
The field works like a regular text field with additional security features:
|
|
131
116
|
|
|
132
|
-
- **
|
|
133
|
-
- **Hidden values**: Values are shown as `***` by default
|
|
117
|
+
- **Values are hidden** by default (shown as `***`)
|
|
134
118
|
- **Eye button**: Toggles between show/hide the value
|
|
135
119
|
- **Copy button**: Copies the value to clipboard with a confirmation notification
|
|
136
|
-
- **On save**:
|
|
137
|
-
- **On read**:
|
|
138
|
-
- **In the DB**: Stored
|
|
120
|
+
- **On save**: Value is automatically encrypted before storing
|
|
121
|
+
- **On read**: Value is automatically decrypted before displaying
|
|
122
|
+
- **In the DB**: Stored as `iv:authTag:encryptedText` (unreadable without the key)
|
|
139
123
|
- **In components**: Works the same in nested components at any depth
|
|
140
124
|
|
|
141
125
|
### 3. API Usage
|
|
142
126
|
|
|
127
|
+
The API always returns **decrypted** values for authorized requests. You write plain text, the plugin handles encryption transparently.
|
|
128
|
+
|
|
143
129
|
```bash
|
|
144
|
-
# Create with an encrypted field
|
|
130
|
+
# Create an entry with an encrypted field
|
|
145
131
|
curl -X POST http://localhost:1337/api/users \
|
|
146
132
|
-H "Content-Type: application/json" \
|
|
147
133
|
-d '{
|
|
@@ -151,11 +137,27 @@ curl -X POST http://localhost:1337/api/users \
|
|
|
151
137
|
}
|
|
152
138
|
}'
|
|
153
139
|
|
|
154
|
-
# Read (returns decrypted)
|
|
140
|
+
# Read (automatically returns decrypted)
|
|
155
141
|
curl -X GET http://localhost:1337/api/users/1
|
|
156
142
|
# Response: { "name": "John", "apiKey": "my-secret-key-123" }
|
|
157
143
|
```
|
|
158
144
|
|
|
145
|
+
## Data Validation
|
|
146
|
+
|
|
147
|
+
The plugin supports validation before encryption. If validation fails, the value is rejected before being encrypted or saved.
|
|
148
|
+
|
|
149
|
+
### Configure regex validation
|
|
150
|
+
|
|
151
|
+
1. In Content-Type Builder, select the encrypted field
|
|
152
|
+
2. Go to the **"Advanced Settings"** tab
|
|
153
|
+
3. In **"RegEx pattern"**, enter your regular expression
|
|
154
|
+
4. Save the changes
|
|
155
|
+
|
|
156
|
+
**Example**: To only accept values that look like an API key:
|
|
157
|
+
```regex
|
|
158
|
+
^sk-[a-zA-Z0-9]{32}$
|
|
159
|
+
```
|
|
160
|
+
|
|
159
161
|
## Usage Example
|
|
160
162
|
|
|
161
163
|
### "User" collection with an encrypted API Key
|
|
@@ -169,12 +171,12 @@ curl -X GET http://localhost:1337/api/users/1
|
|
|
169
171
|
}
|
|
170
172
|
```
|
|
171
173
|
|
|
172
|
-
**
|
|
174
|
+
**What gets stored in the DB:**
|
|
173
175
|
```
|
|
174
176
|
apiKey: "a1b2c3d4e5f6....:f9e8d7c6b5a4....:9f8e7d6c5b4a3..."
|
|
175
177
|
```
|
|
176
178
|
|
|
177
|
-
**
|
|
179
|
+
**What the admin panel and API show:**
|
|
178
180
|
```
|
|
179
181
|
apiKey: "sk-1234567890abcdef"
|
|
180
182
|
```
|
|
@@ -194,14 +196,14 @@ apiKey: "sk-1234567890abcdef"
|
|
|
194
196
|
|
|
195
197
|
- ✅ **Authenticated encryption**: GCM provides both confidentiality and integrity
|
|
196
198
|
- ✅ **Unique IV**: Every encryption operation generates a random IV
|
|
197
|
-
- ✅ **Tamper resistance**: Auth Tag detects any modification
|
|
199
|
+
- ✅ **Tamper resistance**: Auth Tag detects any modification to the ciphertext
|
|
198
200
|
- ✅ **Input validation**: Regex and custom constraints supported
|
|
199
201
|
- ✅ **Safe error handling**: Controlled logs without exposing sensitive data
|
|
200
202
|
- ✅ **Double-layer decryption**: Lifecycle hooks (internal) + middleware (API responses)
|
|
201
203
|
|
|
202
204
|
### Best Practices
|
|
203
205
|
|
|
204
|
-
1. **Key rotation**: Use the included rotation script (see below)
|
|
206
|
+
1. **Key rotation**: Use the included rotation script when changing keys (see below)
|
|
205
207
|
2. **Environment separation**: Use different keys per dev/staging/prod
|
|
206
208
|
3. **Auditing**: Monitor encryption/decryption error logs
|
|
207
209
|
4. **Key backup**: Keep secure copies of keys in multiple locations
|
|
@@ -209,30 +211,31 @@ apiKey: "sk-1234567890abcdef"
|
|
|
209
211
|
|
|
210
212
|
### Key Rotation (Preventing Data Loss)
|
|
211
213
|
|
|
212
|
-
⚠️ **IMPORTANT**: If you change `ENCRYPTION_KEY` in your `.env` without re-encrypting your data first, **all existing data will become unreadable**.
|
|
214
|
+
⚠️ **IMPORTANT**: If you change `ENCRYPTION_KEY` in your `.env` without re-encrypting your data first, **all existing data will become permanently unreadable**.
|
|
213
215
|
|
|
214
|
-
|
|
216
|
+
Follow this safe process to rotate your key:
|
|
215
217
|
|
|
216
|
-
1. **Keep your OLD key**
|
|
218
|
+
1. **Keep your OLD key** — do not remove it yet.
|
|
217
219
|
2. **Generate a NEW key** (64-character hexadecimal).
|
|
218
220
|
3. **Export the encrypted values** from your database.
|
|
219
221
|
4. **Run the rotation script** included in this plugin:
|
|
220
222
|
```bash
|
|
221
|
-
# From your project root
|
|
222
|
-
node node_modules/@growy/strapi-plugin-encrypted-field/scripts/rotate-key.js
|
|
223
|
+
# From your Strapi project root
|
|
224
|
+
node node_modules/@growy/strapi-plugin-encrypted-field/scripts/rotate-key.js \
|
|
225
|
+
--old=<YOUR_CURRENT_64_CHAR_KEY> \
|
|
226
|
+
--new=<YOUR_NEW_64_CHAR_KEY>
|
|
223
227
|
```
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
The script reads encrypted values from stdin, decrypts with the old key, and re-encrypts with the new key, writing the results to stdout.
|
|
229
|
+
5. **Update your database** with the new encrypted values output by the script.
|
|
230
|
+
6. **Update your `.env`** with the `NEW_KEY` and remove the old one.
|
|
226
231
|
7. **Restart Strapi**.
|
|
227
232
|
|
|
228
|
-
The script works as a pipe (stdin to stdout). See the script output or documentation for database-specific integration examples (e.g., PostgreSQL loops).
|
|
229
|
-
|
|
230
233
|
## Use Cases
|
|
231
234
|
|
|
232
235
|
- 🔑 Third-party API Keys
|
|
233
236
|
- 🔐 Access tokens
|
|
234
237
|
- 🔒 Webhook secrets
|
|
235
|
-
- 💳
|
|
238
|
+
- 💳 Payment or sensitive information
|
|
236
239
|
- 📧 SMTP credentials
|
|
237
240
|
- 🔑 Application passwords
|
|
238
241
|
|
|
@@ -241,7 +244,7 @@ The script works as a pipe (stdin to stdout). See the script output or documenta
|
|
|
241
244
|
- ❌ **Search**: Cannot search by encrypted fields (data is encrypted in DB)
|
|
242
245
|
- ❌ **Sorting**: Cannot sort by encrypted fields
|
|
243
246
|
- ❌ **Filters**: Cannot apply direct filters on encrypted fields
|
|
244
|
-
- ❌ **Unique constraint**: Strapi's unique validation will not work correctly on encrypted fields because each encryption produces
|
|
247
|
+
- ❌ **Unique constraint**: Strapi's unique validation will not work correctly on encrypted fields because each encryption produces different ciphertext (random IV)
|
|
245
248
|
- ⚠️ **Performance**: Encryption/decryption adds minimal overhead (~1-2ms per operation)
|
|
246
249
|
- ⚠️ **Key synchronization**: All environments sharing the same DB must use the same key
|
|
247
250
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@growy/strapi-plugin-encrypted-field",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.4",
|
|
4
4
|
"description": "Custom encrypted text field plugin for Strapi using AES-256-GCM",
|
|
5
5
|
"strapi": {
|
|
6
6
|
"name": "encrypted-field",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
}
|
|
36
36
|
],
|
|
37
37
|
"engines": {
|
|
38
|
-
"node": ">=18.0.0 <=
|
|
38
|
+
"node": ">=18.0.0 <=22.x.x",
|
|
39
39
|
"npm": ">=6.0.0"
|
|
40
40
|
},
|
|
41
41
|
"license": "MIT",
|