@growy/strapi-plugin-encrypted-field 2.4.1 → 2.4.3

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +65 -52
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
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
+
10
+ ## [2.4.2] - 2026-02-26
11
+
12
+ ### Changed
13
+ - Improved Key Rotation documentation with a detailed step-by-step foolproof guide to prevent data loss.
14
+
5
15
  ## [2.4.1] - 2026-02-26
6
16
 
7
17
  ### 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
- - ✅ **Native Strapi v5 UI** with visibility controls, resizable inputs and copy to clipboard
16
- - ✅ **Values hidden** by default with show/hide toggle
17
- - ✅ **Copy notifications** confirmation when copying values
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
- Edit `config/plugins.js`:
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('ENCRYPTION_KEY'),
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 will generate a 64-character hexadecimal key (32 bytes).
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
- - **In the panel**: Type text normally
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**: Automatically encrypted
137
- - **On read**: Automatically decrypted
138
- - **In the DB**: Stored encrypted with format `iv:authTag:encrypted`
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
- **In the DB:**
174
+ **What gets stored in the DB:**
173
175
  ```
174
176
  apiKey: "a1b2c3d4e5f6....:f9e8d7c6b5a4....:9f8e7d6c5b4a3..."
175
177
  ```
176
178
 
177
- **In the panel and API:**
179
+ **What the admin panel and API show:**
178
180
  ```
179
181
  apiKey: "sk-1234567890abcdef"
180
182
  ```
@@ -194,35 +196,46 @@ 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
208
210
  5. **Private fields**: Mark sensitive fields as "private" to exclude them from the public API
209
211
 
210
- ### Key Rotation
212
+ ### Key Rotation (Preventing Data Loss)
211
213
 
212
- If you need to change your encryption key, use the included rotation script to re-encrypt existing data:
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
- ```bash
215
- node scripts/rotate-key.js --old=<CURRENT_64_CHAR_KEY> --new=<NEW_64_CHAR_KEY>
216
- ```
216
+ Follow this safe process to rotate your key:
217
217
 
218
- The script reads encrypted values from stdin, decrypts with the old key, and re-encrypts with the new key. See the script output for database-specific integration examples (PostgreSQL, etc.).
218
+ 1. **Keep your OLD key** do not remove it yet.
219
+ 2. **Generate a NEW key** (64-character hexadecimal).
220
+ 3. **Export the encrypted values** from your database.
221
+ 4. **Run the rotation script** included in this plugin:
222
+ ```bash
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>
227
+ ```
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.
231
+ 7. **Restart Strapi**.
219
232
 
220
233
  ## Use Cases
221
234
 
222
235
  - 🔑 Third-party API Keys
223
236
  - 🔐 Access tokens
224
237
  - 🔒 Webhook secrets
225
- - 💳 Sensitive information
238
+ - 💳 Payment or sensitive information
226
239
  - 📧 SMTP credentials
227
240
  - 🔑 Application passwords
228
241
 
@@ -231,7 +244,7 @@ The script reads encrypted values from stdin, decrypts with the old key, and re-
231
244
  - ❌ **Search**: Cannot search by encrypted fields (data is encrypted in DB)
232
245
  - ❌ **Sorting**: Cannot sort by encrypted fields
233
246
  - ❌ **Filters**: Cannot apply direct filters on encrypted fields
234
- - ❌ **Unique constraint**: Strapi's unique validation will not work correctly on encrypted fields because each encryption produces a different ciphertext (random IV)
247
+ - ❌ **Unique constraint**: Strapi's unique validation will not work correctly on encrypted fields because each encryption produces different ciphertext (random IV)
235
248
  - ⚠️ **Performance**: Encryption/decryption adds minimal overhead (~1-2ms per operation)
236
249
  - ⚠️ **Key synchronization**: All environments sharing the same DB must use the same key
237
250
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growy/strapi-plugin-encrypted-field",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "Custom encrypted text field plugin for Strapi using AES-256-GCM",
5
5
  "strapi": {
6
6
  "name": "encrypted-field",