@djangocfg/crypto 2.1.111
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/README.md +161 -0
- package/dist/index.cjs +267 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +297 -0
- package/dist/index.d.ts +297 -0
- package/dist/index.mjs +246 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.cjs +300 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +234 -0
- package/dist/react.d.ts +234 -0
- package/dist/react.mjs +279 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +79 -0
- package/src/decryption.ts +271 -0
- package/src/index.ts +66 -0
- package/src/key-derivation.ts +168 -0
- package/src/react/hooks.ts +236 -0
- package/src/react/index.ts +21 -0
- package/src/types.ts +159 -0
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for Django-CFG encryption.
|
|
3
|
+
*
|
|
4
|
+
* These types match the encrypted response format from Django-CFG backend.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Encrypted field envelope returned by Django-CFG API.
|
|
8
|
+
*
|
|
9
|
+
* When a serializer field is encrypted, it returns this structure
|
|
10
|
+
* instead of the plain value.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```json
|
|
14
|
+
* {
|
|
15
|
+
* "encrypted": true,
|
|
16
|
+
* "field": "price",
|
|
17
|
+
* "algorithm": "AES-256-GCM",
|
|
18
|
+
* "iv": "base64...",
|
|
19
|
+
* "data": "base64...",
|
|
20
|
+
* "auth_tag": "base64..."
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
interface EncryptedField {
|
|
25
|
+
/** Always true for encrypted fields */
|
|
26
|
+
encrypted: true;
|
|
27
|
+
/** Field name that was encrypted */
|
|
28
|
+
field?: string;
|
|
29
|
+
/** Encryption algorithm used */
|
|
30
|
+
algorithm: 'AES-256-GCM' | 'AES-256-CBC';
|
|
31
|
+
/** Base64-encoded initialization vector */
|
|
32
|
+
iv: string;
|
|
33
|
+
/** Base64-encoded ciphertext */
|
|
34
|
+
data: string;
|
|
35
|
+
/** Base64-encoded authentication tag (GCM only) */
|
|
36
|
+
auth_tag: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Full encrypted response envelope.
|
|
40
|
+
*
|
|
41
|
+
* When response-level encryption is enabled, the entire response
|
|
42
|
+
* body is wrapped in this structure.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```json
|
|
46
|
+
* {
|
|
47
|
+
* "encrypted": true,
|
|
48
|
+
* "algorithm": "AES-256-GCM",
|
|
49
|
+
* "salt": "base64...",
|
|
50
|
+
* "iv": "base64...",
|
|
51
|
+
* "data": "base64...",
|
|
52
|
+
* "auth_tag": "base64..."
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
interface EncryptedResponse {
|
|
57
|
+
/** Always true for encrypted responses */
|
|
58
|
+
encrypted: true;
|
|
59
|
+
/** Encryption algorithm used */
|
|
60
|
+
algorithm: 'AES-256-GCM' | 'AES-256-CBC';
|
|
61
|
+
/** Base64-encoded salt for key derivation */
|
|
62
|
+
salt: string;
|
|
63
|
+
/** Base64-encoded initialization vector */
|
|
64
|
+
iv: string;
|
|
65
|
+
/** Base64-encoded ciphertext */
|
|
66
|
+
data: string;
|
|
67
|
+
/** Base64-encoded authentication tag (GCM only) */
|
|
68
|
+
auth_tag: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Configuration for the decryption client.
|
|
72
|
+
*/
|
|
73
|
+
interface DecryptionConfig {
|
|
74
|
+
/**
|
|
75
|
+
* Secret key for key derivation.
|
|
76
|
+
* Should match the Django SECRET_KEY or a derived key.
|
|
77
|
+
*/
|
|
78
|
+
secretKey: string;
|
|
79
|
+
/**
|
|
80
|
+
* User ID for per-user key derivation (optional).
|
|
81
|
+
* When provided, keys are derived per-user for isolation.
|
|
82
|
+
*/
|
|
83
|
+
userId?: string | number;
|
|
84
|
+
/**
|
|
85
|
+
* Session ID for per-session key derivation (optional).
|
|
86
|
+
* Takes precedence over userId if both provided.
|
|
87
|
+
*/
|
|
88
|
+
sessionId?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Number of PBKDF2 iterations (default: 100000).
|
|
91
|
+
* Must match backend configuration.
|
|
92
|
+
*/
|
|
93
|
+
iterations?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Key prefix for derivation (default: "djangocfg_encryption").
|
|
96
|
+
* Must match backend configuration.
|
|
97
|
+
*/
|
|
98
|
+
keyPrefix?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Result of a decryption operation.
|
|
102
|
+
*/
|
|
103
|
+
interface DecryptionResult<T = unknown> {
|
|
104
|
+
/** Decrypted data */
|
|
105
|
+
data: T;
|
|
106
|
+
/** Whether decryption was successful */
|
|
107
|
+
success: true;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Error from a decryption operation.
|
|
111
|
+
*/
|
|
112
|
+
interface DecryptionError {
|
|
113
|
+
/** Error message */
|
|
114
|
+
message: string;
|
|
115
|
+
/** Error code */
|
|
116
|
+
code: 'INVALID_FORMAT' | 'DECRYPTION_FAILED' | 'AUTH_FAILED' | 'KEY_ERROR';
|
|
117
|
+
/** Whether decryption was successful */
|
|
118
|
+
success: false;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Type guard to check if a value is an encrypted field.
|
|
122
|
+
*/
|
|
123
|
+
declare function isEncryptedField(value: unknown): value is EncryptedField;
|
|
124
|
+
/**
|
|
125
|
+
* Type guard to check if a value is an encrypted response.
|
|
126
|
+
*/
|
|
127
|
+
declare function isEncryptedResponse(value: unknown): value is EncryptedResponse;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Hook state for decryption operations.
|
|
131
|
+
*/
|
|
132
|
+
interface UseDecryptState<T> {
|
|
133
|
+
/** Decrypted data */
|
|
134
|
+
data: T | undefined;
|
|
135
|
+
/** Loading state */
|
|
136
|
+
isLoading: boolean;
|
|
137
|
+
/** Error if decryption failed */
|
|
138
|
+
error: Error | undefined;
|
|
139
|
+
/** Whether data has been decrypted */
|
|
140
|
+
isDecrypted: boolean;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Hook to decrypt data on mount or when dependencies change.
|
|
144
|
+
*
|
|
145
|
+
* @param encryptedData - Data potentially containing encrypted fields
|
|
146
|
+
* @param config - Decryption configuration
|
|
147
|
+
* @returns Decrypted data state
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* function ProductPrice({ product }: { product: Product }) {
|
|
152
|
+
* const { data, isLoading, error } = useDecrypt(product, {
|
|
153
|
+
* secretKey: process.env.NEXT_PUBLIC_DECRYPT_KEY!,
|
|
154
|
+
* userId: user.id
|
|
155
|
+
* });
|
|
156
|
+
*
|
|
157
|
+
* if (isLoading) return <Skeleton />;
|
|
158
|
+
* if (error) return <ErrorMessage error={error} />;
|
|
159
|
+
* return <span>{data.price}</span>;
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
declare function useDecrypt<T>(encryptedData: unknown, config: DecryptionConfig): UseDecryptState<T>;
|
|
164
|
+
/**
|
|
165
|
+
* Hook to create a memoized decryption client.
|
|
166
|
+
*
|
|
167
|
+
* @param config - Decryption configuration
|
|
168
|
+
* @returns Decryption client or undefined while loading
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* function App() {
|
|
173
|
+
* const crypto = useDecryptionClient({
|
|
174
|
+
* secretKey: process.env.NEXT_PUBLIC_DECRYPT_KEY!
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* const handleFetch = async () => {
|
|
178
|
+
* const response = await fetch('/api/products/?encrypt=true');
|
|
179
|
+
* const data = await response.json();
|
|
180
|
+
* const decrypted = await crypto?.decryptObject(data);
|
|
181
|
+
* };
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function useDecryptionClient(config: DecryptionConfig): {
|
|
186
|
+
decryptField: <T = unknown>(field: EncryptedField) => Promise<T>;
|
|
187
|
+
decryptObject: <T>(data: unknown) => Promise<T>;
|
|
188
|
+
isEncryptedField: typeof isEncryptedField;
|
|
189
|
+
isEncryptedResponse: typeof isEncryptedResponse;
|
|
190
|
+
} | null;
|
|
191
|
+
/**
|
|
192
|
+
* Hook for lazy decryption with manual trigger.
|
|
193
|
+
*
|
|
194
|
+
* @param config - Decryption configuration
|
|
195
|
+
* @returns Decrypt function and state
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* function LazyProduct({ product }: { product: Product }) {
|
|
200
|
+
* const { decrypt, data, isLoading } = useLazyDecrypt({
|
|
201
|
+
* secretKey: process.env.NEXT_PUBLIC_DECRYPT_KEY!
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* return (
|
|
205
|
+
* <div>
|
|
206
|
+
* <button onClick={() => decrypt(product)}>Show Price</button>
|
|
207
|
+
* {isLoading && <Spinner />}
|
|
208
|
+
* {data && <span>{data.price}</span>}
|
|
209
|
+
* </div>
|
|
210
|
+
* );
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
declare function useLazyDecrypt<T>(config: DecryptionConfig): {
|
|
215
|
+
decrypt: (encryptedData: unknown) => Promise<T | undefined>;
|
|
216
|
+
reset: () => void;
|
|
217
|
+
/** Decrypted data */
|
|
218
|
+
data: T | undefined;
|
|
219
|
+
/** Loading state */
|
|
220
|
+
isLoading: boolean;
|
|
221
|
+
/** Error if decryption failed */
|
|
222
|
+
error: Error | undefined;
|
|
223
|
+
/** Whether data has been decrypted */
|
|
224
|
+
isDecrypted: boolean;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Hook to check if a value needs decryption.
|
|
228
|
+
*
|
|
229
|
+
* @param value - Value to check
|
|
230
|
+
* @returns Whether the value is encrypted
|
|
231
|
+
*/
|
|
232
|
+
declare function useIsEncrypted(value: unknown): boolean;
|
|
233
|
+
|
|
234
|
+
export { type DecryptionConfig, type DecryptionError, type DecryptionResult, type EncryptedField, type EncryptedResponse, useDecrypt, useDecryptionClient, useIsEncrypted, useLazyDecrypt };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for Django-CFG encryption.
|
|
3
|
+
*
|
|
4
|
+
* These types match the encrypted response format from Django-CFG backend.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Encrypted field envelope returned by Django-CFG API.
|
|
8
|
+
*
|
|
9
|
+
* When a serializer field is encrypted, it returns this structure
|
|
10
|
+
* instead of the plain value.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```json
|
|
14
|
+
* {
|
|
15
|
+
* "encrypted": true,
|
|
16
|
+
* "field": "price",
|
|
17
|
+
* "algorithm": "AES-256-GCM",
|
|
18
|
+
* "iv": "base64...",
|
|
19
|
+
* "data": "base64...",
|
|
20
|
+
* "auth_tag": "base64..."
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
interface EncryptedField {
|
|
25
|
+
/** Always true for encrypted fields */
|
|
26
|
+
encrypted: true;
|
|
27
|
+
/** Field name that was encrypted */
|
|
28
|
+
field?: string;
|
|
29
|
+
/** Encryption algorithm used */
|
|
30
|
+
algorithm: 'AES-256-GCM' | 'AES-256-CBC';
|
|
31
|
+
/** Base64-encoded initialization vector */
|
|
32
|
+
iv: string;
|
|
33
|
+
/** Base64-encoded ciphertext */
|
|
34
|
+
data: string;
|
|
35
|
+
/** Base64-encoded authentication tag (GCM only) */
|
|
36
|
+
auth_tag: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Full encrypted response envelope.
|
|
40
|
+
*
|
|
41
|
+
* When response-level encryption is enabled, the entire response
|
|
42
|
+
* body is wrapped in this structure.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```json
|
|
46
|
+
* {
|
|
47
|
+
* "encrypted": true,
|
|
48
|
+
* "algorithm": "AES-256-GCM",
|
|
49
|
+
* "salt": "base64...",
|
|
50
|
+
* "iv": "base64...",
|
|
51
|
+
* "data": "base64...",
|
|
52
|
+
* "auth_tag": "base64..."
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
interface EncryptedResponse {
|
|
57
|
+
/** Always true for encrypted responses */
|
|
58
|
+
encrypted: true;
|
|
59
|
+
/** Encryption algorithm used */
|
|
60
|
+
algorithm: 'AES-256-GCM' | 'AES-256-CBC';
|
|
61
|
+
/** Base64-encoded salt for key derivation */
|
|
62
|
+
salt: string;
|
|
63
|
+
/** Base64-encoded initialization vector */
|
|
64
|
+
iv: string;
|
|
65
|
+
/** Base64-encoded ciphertext */
|
|
66
|
+
data: string;
|
|
67
|
+
/** Base64-encoded authentication tag (GCM only) */
|
|
68
|
+
auth_tag: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Configuration for the decryption client.
|
|
72
|
+
*/
|
|
73
|
+
interface DecryptionConfig {
|
|
74
|
+
/**
|
|
75
|
+
* Secret key for key derivation.
|
|
76
|
+
* Should match the Django SECRET_KEY or a derived key.
|
|
77
|
+
*/
|
|
78
|
+
secretKey: string;
|
|
79
|
+
/**
|
|
80
|
+
* User ID for per-user key derivation (optional).
|
|
81
|
+
* When provided, keys are derived per-user for isolation.
|
|
82
|
+
*/
|
|
83
|
+
userId?: string | number;
|
|
84
|
+
/**
|
|
85
|
+
* Session ID for per-session key derivation (optional).
|
|
86
|
+
* Takes precedence over userId if both provided.
|
|
87
|
+
*/
|
|
88
|
+
sessionId?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Number of PBKDF2 iterations (default: 100000).
|
|
91
|
+
* Must match backend configuration.
|
|
92
|
+
*/
|
|
93
|
+
iterations?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Key prefix for derivation (default: "djangocfg_encryption").
|
|
96
|
+
* Must match backend configuration.
|
|
97
|
+
*/
|
|
98
|
+
keyPrefix?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Result of a decryption operation.
|
|
102
|
+
*/
|
|
103
|
+
interface DecryptionResult<T = unknown> {
|
|
104
|
+
/** Decrypted data */
|
|
105
|
+
data: T;
|
|
106
|
+
/** Whether decryption was successful */
|
|
107
|
+
success: true;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Error from a decryption operation.
|
|
111
|
+
*/
|
|
112
|
+
interface DecryptionError {
|
|
113
|
+
/** Error message */
|
|
114
|
+
message: string;
|
|
115
|
+
/** Error code */
|
|
116
|
+
code: 'INVALID_FORMAT' | 'DECRYPTION_FAILED' | 'AUTH_FAILED' | 'KEY_ERROR';
|
|
117
|
+
/** Whether decryption was successful */
|
|
118
|
+
success: false;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Type guard to check if a value is an encrypted field.
|
|
122
|
+
*/
|
|
123
|
+
declare function isEncryptedField(value: unknown): value is EncryptedField;
|
|
124
|
+
/**
|
|
125
|
+
* Type guard to check if a value is an encrypted response.
|
|
126
|
+
*/
|
|
127
|
+
declare function isEncryptedResponse(value: unknown): value is EncryptedResponse;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Hook state for decryption operations.
|
|
131
|
+
*/
|
|
132
|
+
interface UseDecryptState<T> {
|
|
133
|
+
/** Decrypted data */
|
|
134
|
+
data: T | undefined;
|
|
135
|
+
/** Loading state */
|
|
136
|
+
isLoading: boolean;
|
|
137
|
+
/** Error if decryption failed */
|
|
138
|
+
error: Error | undefined;
|
|
139
|
+
/** Whether data has been decrypted */
|
|
140
|
+
isDecrypted: boolean;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Hook to decrypt data on mount or when dependencies change.
|
|
144
|
+
*
|
|
145
|
+
* @param encryptedData - Data potentially containing encrypted fields
|
|
146
|
+
* @param config - Decryption configuration
|
|
147
|
+
* @returns Decrypted data state
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* function ProductPrice({ product }: { product: Product }) {
|
|
152
|
+
* const { data, isLoading, error } = useDecrypt(product, {
|
|
153
|
+
* secretKey: process.env.NEXT_PUBLIC_DECRYPT_KEY!,
|
|
154
|
+
* userId: user.id
|
|
155
|
+
* });
|
|
156
|
+
*
|
|
157
|
+
* if (isLoading) return <Skeleton />;
|
|
158
|
+
* if (error) return <ErrorMessage error={error} />;
|
|
159
|
+
* return <span>{data.price}</span>;
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
declare function useDecrypt<T>(encryptedData: unknown, config: DecryptionConfig): UseDecryptState<T>;
|
|
164
|
+
/**
|
|
165
|
+
* Hook to create a memoized decryption client.
|
|
166
|
+
*
|
|
167
|
+
* @param config - Decryption configuration
|
|
168
|
+
* @returns Decryption client or undefined while loading
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* function App() {
|
|
173
|
+
* const crypto = useDecryptionClient({
|
|
174
|
+
* secretKey: process.env.NEXT_PUBLIC_DECRYPT_KEY!
|
|
175
|
+
* });
|
|
176
|
+
*
|
|
177
|
+
* const handleFetch = async () => {
|
|
178
|
+
* const response = await fetch('/api/products/?encrypt=true');
|
|
179
|
+
* const data = await response.json();
|
|
180
|
+
* const decrypted = await crypto?.decryptObject(data);
|
|
181
|
+
* };
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
declare function useDecryptionClient(config: DecryptionConfig): {
|
|
186
|
+
decryptField: <T = unknown>(field: EncryptedField) => Promise<T>;
|
|
187
|
+
decryptObject: <T>(data: unknown) => Promise<T>;
|
|
188
|
+
isEncryptedField: typeof isEncryptedField;
|
|
189
|
+
isEncryptedResponse: typeof isEncryptedResponse;
|
|
190
|
+
} | null;
|
|
191
|
+
/**
|
|
192
|
+
* Hook for lazy decryption with manual trigger.
|
|
193
|
+
*
|
|
194
|
+
* @param config - Decryption configuration
|
|
195
|
+
* @returns Decrypt function and state
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* function LazyProduct({ product }: { product: Product }) {
|
|
200
|
+
* const { decrypt, data, isLoading } = useLazyDecrypt({
|
|
201
|
+
* secretKey: process.env.NEXT_PUBLIC_DECRYPT_KEY!
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* return (
|
|
205
|
+
* <div>
|
|
206
|
+
* <button onClick={() => decrypt(product)}>Show Price</button>
|
|
207
|
+
* {isLoading && <Spinner />}
|
|
208
|
+
* {data && <span>{data.price}</span>}
|
|
209
|
+
* </div>
|
|
210
|
+
* );
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
declare function useLazyDecrypt<T>(config: DecryptionConfig): {
|
|
215
|
+
decrypt: (encryptedData: unknown) => Promise<T | undefined>;
|
|
216
|
+
reset: () => void;
|
|
217
|
+
/** Decrypted data */
|
|
218
|
+
data: T | undefined;
|
|
219
|
+
/** Loading state */
|
|
220
|
+
isLoading: boolean;
|
|
221
|
+
/** Error if decryption failed */
|
|
222
|
+
error: Error | undefined;
|
|
223
|
+
/** Whether data has been decrypted */
|
|
224
|
+
isDecrypted: boolean;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Hook to check if a value needs decryption.
|
|
228
|
+
*
|
|
229
|
+
* @param value - Value to check
|
|
230
|
+
* @returns Whether the value is encrypted
|
|
231
|
+
*/
|
|
232
|
+
declare function useIsEncrypted(value: unknown): boolean;
|
|
233
|
+
|
|
234
|
+
export { type DecryptionConfig, type DecryptionError, type DecryptionResult, type EncryptedField, type EncryptedResponse, useDecrypt, useDecryptionClient, useIsEncrypted, useLazyDecrypt };
|