@happyvertical/encryption 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +478 -0
- package/dist/adapters/nacl.d.ts +75 -0
- package/dist/adapters/nacl.d.ts.map +1 -0
- package/dist/adapters/node.d.ts +96 -0
- package/dist/adapters/node.d.ts.map +1 -0
- package/dist/adapters/pgp.d.ts +79 -0
- package/dist/adapters/pgp.d.ts.map +1 -0
- package/dist/chunks/nacl-CoiIhzki.js +454 -0
- package/dist/chunks/nacl-CoiIhzki.js.map +1 -0
- package/dist/chunks/node-nfBpcQQH.js +551 -0
- package/dist/chunks/node-nfBpcQQH.js.map +1 -0
- package/dist/chunks/pgp-BIhtvrNo.js +916 -0
- package/dist/chunks/pgp-BIhtvrNo.js.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +356 -0
- package/dist/index.js.map +1 -0
- package/dist/shared/base.d.ts +61 -0
- package/dist/shared/base.d.ts.map +1 -0
- package/dist/shared/errors.d.ts +79 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/factory.d.ts +42 -0
- package/dist/shared/factory.d.ts.map +1 -0
- package/dist/shared/types.d.ts +310 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/metadata.json +34 -0
- package/package.json +67 -0
package/AGENT.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @happyvertical/encryption
|
|
2
|
+
|
|
3
|
+
<!-- BEGIN AGENT:GENERATED -->
|
|
4
|
+
## Purpose
|
|
5
|
+
Unified encryption and cryptography operations with adapter-based architecture
|
|
6
|
+
|
|
7
|
+
## Package Map
|
|
8
|
+
- Package: `@happyvertical/encryption`
|
|
9
|
+
- Hierarchy path: `@happyvertical/sdk > packages > encryption`
|
|
10
|
+
- Workspace position: `10 of 30` local packages
|
|
11
|
+
- Internal dependencies: `@happyvertical/logger`, `@happyvertical/utils`
|
|
12
|
+
- Internal dependents: none
|
|
13
|
+
- Knowledge graph files: `AGENT.md`, `metadata.json`, `ecosystem-manifest.json`
|
|
14
|
+
|
|
15
|
+
## Build & Test
|
|
16
|
+
```bash
|
|
17
|
+
pnpm --filter @happyvertical/encryption build
|
|
18
|
+
pnpm --filter @happyvertical/encryption test
|
|
19
|
+
pnpm --filter @happyvertical/encryption typecheck
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Agent Correction Loops
|
|
23
|
+
- If module resolution or export errors mention a workspace dependency, build the dependency first (`pnpm --filter @happyvertical/logger build`, `pnpm --filter @happyvertical/utils build`) and then rerun `pnpm --filter @happyvertical/encryption build`.
|
|
24
|
+
- If you hit type-only regressions, run `pnpm --filter @happyvertical/encryption typecheck` before rerunning the package build or tests to isolate the failing surface.
|
|
25
|
+
- If failures span multiple packages or Turborepo ordering looks wrong, run `pnpm build` and `pnpm typecheck` from the repo root before retrying package-scoped commands.
|
|
26
|
+
|
|
27
|
+
## Ecosystem Relationships
|
|
28
|
+
- Provides: Unified encryption and cryptography operations with adapter-based architecture
|
|
29
|
+
- Implements: none
|
|
30
|
+
- Requires: @happyvertical/logger, @happyvertical/utils, @openpgp/web-stream-tools, openpgp, tweetnacl, tweetnacl-util
|
|
31
|
+
- Stability: stable (Primary package surface is described as implemented and production-oriented.)
|
|
32
|
+
<!-- END AGENT:GENERATED -->
|
|
33
|
+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright <2025> <Happy Vertical Corporation>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
# @happyvertical/encryption
|
|
2
|
+
|
|
3
|
+
> Unified encryption and cryptography operations with adapter-based architecture supporting PGP, NaCl, and Node.js crypto.
|
|
4
|
+
|
|
5
|
+
[](./test)
|
|
6
|
+
[](../../LICENSE)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **🔐 Multiple Encryption Methods**: PGP/OpenPGP, NaCl/libsodium, Node.js crypto
|
|
12
|
+
- **📝 Text, Files & Buffers**: Encrypt any data format with a unified API
|
|
13
|
+
- **📧 Email Integration**: Specialized PGP/MIME email encryption
|
|
14
|
+
- **🔑 Key Management**: Generate, import, export, and manage encryption keys
|
|
15
|
+
- **✍️ Digital Signatures**: Sign and verify data with RSA, ECDSA, and EdDSA
|
|
16
|
+
- **🎯 Type-Safe**: Full TypeScript support with comprehensive type definitions
|
|
17
|
+
- **⚡ High Performance**: Fast NaCl encryption, efficient streaming for large files
|
|
18
|
+
- **🧪 Well-Tested**: 209 tests covering all adapters and use cases
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @happyvertical/encryption
|
|
24
|
+
# or
|
|
25
|
+
pnpm add @happyvertical/encryption
|
|
26
|
+
# or
|
|
27
|
+
yarn add @happyvertical/encryption
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Claude Code Context
|
|
31
|
+
|
|
32
|
+
Install Claude Code context files for AI-assisted development:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx have-encryption-context
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This copies the package's `AGENT.md` documentation and `metadata.json` metadata to your project's `.claude/` directory, enabling Claude to provide better assistance when working with this package.
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### PGP Encryption
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
46
|
+
|
|
47
|
+
// Create PGP encryption instance
|
|
48
|
+
const pgp = await getEncryption({ type: 'pgp' });
|
|
49
|
+
|
|
50
|
+
// Generate keypair
|
|
51
|
+
const keypair = await pgp.generateKeyPair({
|
|
52
|
+
name: 'Alice',
|
|
53
|
+
email: 'alice@example.com',
|
|
54
|
+
passphrase: 'secure-passphrase',
|
|
55
|
+
type: 'rsa',
|
|
56
|
+
keySize: 4096
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Initialize with keys
|
|
60
|
+
const encryption = await getEncryption({
|
|
61
|
+
type: 'pgp',
|
|
62
|
+
publicKey: keypair.publicKey,
|
|
63
|
+
privateKey: keypair.privateKey,
|
|
64
|
+
passphrase: 'secure-passphrase'
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Encrypt and decrypt text
|
|
68
|
+
const encrypted = await encryption.encryptText('Secret message');
|
|
69
|
+
const decrypted = await encryption.decryptText(encrypted);
|
|
70
|
+
|
|
71
|
+
// Encrypt and decrypt files
|
|
72
|
+
await encryption.encryptFile('document.pdf', 'document.pdf.pgp');
|
|
73
|
+
await encryption.decryptFile('document.pdf.pgp', 'document.pdf');
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### NaCl Encryption (Fast & Modern)
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
80
|
+
|
|
81
|
+
// Generate keypair
|
|
82
|
+
const nacl = await getEncryption({ type: 'nacl' });
|
|
83
|
+
const keypair = await nacl.generateKeyPair();
|
|
84
|
+
|
|
85
|
+
// Symmetric encryption (secretbox)
|
|
86
|
+
const encryption = await getEncryption({
|
|
87
|
+
type: 'nacl',
|
|
88
|
+
secretKey: keypair.secretKey
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const encrypted = await encryption.encryptText('Secret message');
|
|
92
|
+
const decrypted = await encryption.decryptText(encrypted);
|
|
93
|
+
|
|
94
|
+
// Encrypt files (very fast!)
|
|
95
|
+
await encryption.encryptFile('data.json', 'data.json.enc');
|
|
96
|
+
await encryption.decryptFile('data.json.enc', 'data.json');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Node.js Crypto (AES & RSA)
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
103
|
+
|
|
104
|
+
// AES-256-GCM encryption
|
|
105
|
+
const aes = await getEncryption({
|
|
106
|
+
type: 'node',
|
|
107
|
+
algorithm: 'aes-256-gcm',
|
|
108
|
+
keyDerivation: {
|
|
109
|
+
password: 'user-password',
|
|
110
|
+
salt: 'unique-salt',
|
|
111
|
+
iterations: 100000
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const encrypted = await aes.encryptText('Secret message');
|
|
116
|
+
const decrypted = await aes.decryptText(encrypted);
|
|
117
|
+
|
|
118
|
+
// RSA encryption
|
|
119
|
+
const rsa = await getEncryption({
|
|
120
|
+
type: 'node',
|
|
121
|
+
algorithm: 'rsa-oaep'
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const keypair = await rsa.generateKeyPair({
|
|
125
|
+
type: 'rsa',
|
|
126
|
+
keySize: 2048
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const rsaEncryption = await getEncryption({
|
|
130
|
+
type: 'node',
|
|
131
|
+
algorithm: 'rsa-oaep',
|
|
132
|
+
publicKey: keypair.publicKey,
|
|
133
|
+
privateKey: keypair.privateKey
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const encrypted = await rsaEncryption.encryptText('Small message');
|
|
137
|
+
const decrypted = await rsaEncryption.decryptText(encrypted);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Common Use Cases
|
|
141
|
+
|
|
142
|
+
### Email Encryption (PGP/MIME)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
146
|
+
|
|
147
|
+
const pgp = await getEncryption({
|
|
148
|
+
type: 'pgp',
|
|
149
|
+
publicKey: recipientPublicKey,
|
|
150
|
+
privateKey: myPrivateKey,
|
|
151
|
+
passphrase: 'my-passphrase'
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Encrypt email message
|
|
155
|
+
const encryptedEmail = await pgp.encryptEmail({
|
|
156
|
+
from: { address: 'sender@example.com' },
|
|
157
|
+
to: [{ address: 'recipient@example.com' }],
|
|
158
|
+
subject: 'Confidential Information',
|
|
159
|
+
text: 'Secret message content',
|
|
160
|
+
attachments: [
|
|
161
|
+
{ filename: 'document.pdf', content: pdfBuffer }
|
|
162
|
+
]
|
|
163
|
+
}, {
|
|
164
|
+
sign: true,
|
|
165
|
+
armor: true
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Send with your email provider
|
|
169
|
+
// await mailbox.send(encryptedEmail);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Database Field Encryption
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
176
|
+
|
|
177
|
+
const encryption = await getEncryption({
|
|
178
|
+
type: 'node',
|
|
179
|
+
algorithm: 'aes-256-gcm',
|
|
180
|
+
keyDerivation: {
|
|
181
|
+
password: process.env.DB_ENCRYPTION_PASSWORD,
|
|
182
|
+
salt: 'db-encryption-salt',
|
|
183
|
+
iterations: 100000
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Encrypt sensitive fields
|
|
188
|
+
async function saveUser(user) {
|
|
189
|
+
const encryptedSSN = await encryption.encryptText(user.ssn);
|
|
190
|
+
const encryptedCreditCard = await encryption.encryptText(user.creditCard);
|
|
191
|
+
|
|
192
|
+
await db.insert('users', {
|
|
193
|
+
id: user.id,
|
|
194
|
+
name: user.name, // Plain text
|
|
195
|
+
ssn: encryptedSSN,
|
|
196
|
+
credit_card: encryptedCreditCard
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Decrypt when retrieving
|
|
201
|
+
async function getUser(id) {
|
|
202
|
+
const row = await db.selectOne('users', { where: { id } });
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
id: row.id,
|
|
206
|
+
name: row.name,
|
|
207
|
+
ssn: await encryption.decryptText(row.ssn),
|
|
208
|
+
creditCard: await encryption.decryptText(row.credit_card)
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### File Backup Encryption
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
217
|
+
|
|
218
|
+
const encryption = await getEncryption({
|
|
219
|
+
type: 'nacl',
|
|
220
|
+
secretKey: backupSecretKey
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Encrypt backup files
|
|
224
|
+
await encryption.encryptFile(
|
|
225
|
+
'/data/backup-2024-01.tar.gz',
|
|
226
|
+
'/encrypted-backups/backup-2024-01.tar.gz.enc'
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Decrypt when needed
|
|
230
|
+
await encryption.decryptFile(
|
|
231
|
+
'/encrypted-backups/backup-2024-01.tar.gz.enc',
|
|
232
|
+
'/restored/backup-2024-01.tar.gz'
|
|
233
|
+
);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Digital Signatures
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { getEncryption } from '@happyvertical/encryption';
|
|
240
|
+
|
|
241
|
+
const pgp = await getEncryption({
|
|
242
|
+
type: 'pgp',
|
|
243
|
+
privateKey: myPrivateKey,
|
|
244
|
+
passphrase: 'my-passphrase'
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Sign message
|
|
248
|
+
const message = 'Important announcement';
|
|
249
|
+
const signature = await pgp.sign(message, {
|
|
250
|
+
detached: true,
|
|
251
|
+
armor: true
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Verify signature
|
|
255
|
+
const valid = await pgp.verify(message, signature, {
|
|
256
|
+
publicKey: signerPublicKey
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (valid) {
|
|
260
|
+
console.log('✓ Signature verified - message is authentic');
|
|
261
|
+
} else {
|
|
262
|
+
console.log('✗ Invalid signature - message may be tampered');
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## API Overview
|
|
267
|
+
|
|
268
|
+
### Factory Function
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
function getEncryption(options: GetEncryptionOptions): Promise<Encryption>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Encryption Interface
|
|
275
|
+
|
|
276
|
+
All adapters implement this unified interface:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
interface Encryption {
|
|
280
|
+
// Text operations
|
|
281
|
+
encryptText(text: string, options?: EncryptOptions): Promise<string>;
|
|
282
|
+
decryptText(encrypted: string, options?: DecryptOptions): Promise<string>;
|
|
283
|
+
|
|
284
|
+
// File operations
|
|
285
|
+
encryptFile(inputPath: string, outputPath: string, options?: EncryptOptions): Promise<void>;
|
|
286
|
+
decryptFile(inputPath: string, outputPath: string, options?: DecryptOptions): Promise<void>;
|
|
287
|
+
|
|
288
|
+
// Buffer operations
|
|
289
|
+
encryptBuffer(buffer: Buffer, options?: EncryptOptions): Promise<Buffer>;
|
|
290
|
+
decryptBuffer(buffer: Buffer, options?: DecryptOptions): Promise<Buffer>;
|
|
291
|
+
|
|
292
|
+
// Key management
|
|
293
|
+
generateKeyPair(options?: KeyPairOptions): Promise<KeyPair>;
|
|
294
|
+
importKey(key: string | Buffer, options?: ImportKeyOptions): Promise<Key>;
|
|
295
|
+
exportKey(key: Key, options?: ExportKeyOptions): Promise<string | Buffer>;
|
|
296
|
+
|
|
297
|
+
// Signing (optional)
|
|
298
|
+
sign?(data: string | Buffer, options?: SignOptions): Promise<string | Buffer>;
|
|
299
|
+
verify?(data: string | Buffer, signature: string | Buffer, options?: VerifyOptions): Promise<boolean>;
|
|
300
|
+
|
|
301
|
+
// Email operations (PGP only)
|
|
302
|
+
encryptEmail?(message: EmailMessage, options?: EncryptEmailOptions): Promise<EmailMessage>;
|
|
303
|
+
decryptEmail?(message: EmailMessage, options?: DecryptEmailOptions): Promise<DecryptedEmail>;
|
|
304
|
+
|
|
305
|
+
// Adapter info
|
|
306
|
+
getCapabilities(): Promise<EncryptionCapabilities>;
|
|
307
|
+
getAdapter(): AdapterType;
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Adapter Comparison
|
|
312
|
+
|
|
313
|
+
| Feature | PGP | NaCl | Node Crypto |
|
|
314
|
+
|---------|-----|------|-------------|
|
|
315
|
+
| **Text Encryption** | ✅ | ✅ | ✅ |
|
|
316
|
+
| **File Encryption** | ✅ | ✅ | ✅ |
|
|
317
|
+
| **Email Encryption** | ✅ | ❌ | ❌ |
|
|
318
|
+
| **Digital Signatures** | ✅ | ✅ | ✅ |
|
|
319
|
+
| **Multiple Recipients** | ✅ | ❌ | ❌ |
|
|
320
|
+
| **Symmetric** | ❌ | ✅ | ✅ |
|
|
321
|
+
| **Asymmetric** | ✅ | ✅ | ✅ |
|
|
322
|
+
| **Speed** | Medium | Fast | Fast |
|
|
323
|
+
| **Key Size** | Large | Small | Medium |
|
|
324
|
+
| **Best For** | Email, compatibility | Performance, modern apps | Standard algorithms, built-in |
|
|
325
|
+
|
|
326
|
+
### When to Use Each Adapter
|
|
327
|
+
|
|
328
|
+
**PGP/OpenPGP** - Best for:
|
|
329
|
+
- Email encryption (PGP/MIME standard)
|
|
330
|
+
- Multi-recipient scenarios
|
|
331
|
+
- Compatibility with existing PGP infrastructure
|
|
332
|
+
- Long-term archival
|
|
333
|
+
|
|
334
|
+
**NaCl/libsodium** - Best for:
|
|
335
|
+
- High-performance applications
|
|
336
|
+
- Modern cryptography
|
|
337
|
+
- File encryption
|
|
338
|
+
- API token encryption
|
|
339
|
+
- Real-time data encryption
|
|
340
|
+
|
|
341
|
+
**Node.js Crypto** - Best for:
|
|
342
|
+
- Standard algorithms (AES, RSA)
|
|
343
|
+
- No external dependencies needed
|
|
344
|
+
- Password-based encryption (PBKDF2)
|
|
345
|
+
- Enterprise requirements (FIPS compliance)
|
|
346
|
+
|
|
347
|
+
## Security Considerations
|
|
348
|
+
|
|
349
|
+
### Key Storage
|
|
350
|
+
|
|
351
|
+
**❌ DO NOT:**
|
|
352
|
+
- Store private keys in plain text
|
|
353
|
+
- Commit keys to version control
|
|
354
|
+
- Log keys or passphrases
|
|
355
|
+
- Transmit keys over insecure channels
|
|
356
|
+
|
|
357
|
+
**✅ DO:**
|
|
358
|
+
- Use environment variables for keys
|
|
359
|
+
- Encrypt private keys with strong passphrases
|
|
360
|
+
- Use hardware security modules (HSMs) for production
|
|
361
|
+
- Implement key rotation policies
|
|
362
|
+
- Use key derivation for password-based encryption
|
|
363
|
+
|
|
364
|
+
### Best Practices
|
|
365
|
+
|
|
366
|
+
1. **Key Length**:
|
|
367
|
+
- RSA: Minimum 2048 bits (4096 recommended)
|
|
368
|
+
- AES: 256 bits
|
|
369
|
+
- ECC: curve25519 or P-384
|
|
370
|
+
|
|
371
|
+
2. **Algorithms**:
|
|
372
|
+
- ✅ Prefer: AES-256-GCM, RSA-OAEP, ECDH, NaCl
|
|
373
|
+
- ❌ Avoid: DES, 3DES, MD5, SHA1
|
|
374
|
+
|
|
375
|
+
3. **Key Derivation**:
|
|
376
|
+
- PBKDF2: Minimum 100,000 iterations
|
|
377
|
+
- Use unique salts per encryption
|
|
378
|
+
- Consider Argon2 for new applications
|
|
379
|
+
|
|
380
|
+
4. **Encrypted Data Integrity**:
|
|
381
|
+
- Use authenticated encryption (GCM, Poly1305)
|
|
382
|
+
- Always verify signatures before trusting data
|
|
383
|
+
- Implement replay protection
|
|
384
|
+
|
|
385
|
+
## Testing
|
|
386
|
+
|
|
387
|
+
Run the test suite:
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
npm test
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Run tests for a specific adapter:
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
npm test -- test/unit/pgp.test.ts
|
|
397
|
+
npm test -- test/unit/nacl.test.ts
|
|
398
|
+
npm test -- test/unit/node.test.ts
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Run file operations tests:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
npm test -- test/unit/file-operations.test.ts
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Performance Benchmarks
|
|
408
|
+
|
|
409
|
+
Approximate performance for 100KB data:
|
|
410
|
+
|
|
411
|
+
| Adapter | Encryption | Decryption | Key Generation |
|
|
412
|
+
|---------|------------|------------|----------------|
|
|
413
|
+
| **PGP (RSA 4096)** | ~200ms | ~100ms | ~3000ms |
|
|
414
|
+
| **NaCl (secretbox)** | ~2ms | ~2ms | ~1ms |
|
|
415
|
+
| **AES-256-GCM** | ~5ms | ~5ms | N/A |
|
|
416
|
+
| **RSA-OAEP 2048** | ~50ms | ~100ms | ~500ms |
|
|
417
|
+
|
|
418
|
+
*Benchmarks run on M1 MacBook Pro. Your results may vary.*
|
|
419
|
+
|
|
420
|
+
## Documentation
|
|
421
|
+
|
|
422
|
+
- **[AGENT.md](./AGENT.md)** - Comprehensive developer guide with detailed API reference, architecture, and implementation phases
|
|
423
|
+
- **[API Types](./src/shared/types.ts)** - TypeScript type definitions
|
|
424
|
+
- **[Error Handling](./src/shared/errors.ts)** - Custom error classes
|
|
425
|
+
|
|
426
|
+
## Examples
|
|
427
|
+
|
|
428
|
+
See the [test directory](./test) for comprehensive examples:
|
|
429
|
+
|
|
430
|
+
- **[PGP Tests](./test/unit/pgp.test.ts)** - Text, file, signature examples
|
|
431
|
+
- **[PGP Email Tests](./test/unit/pgp-email.test.ts)** - Email encryption examples
|
|
432
|
+
- **[NaCl Tests](./test/unit/nacl.test.ts)** - Symmetric and asymmetric examples
|
|
433
|
+
- **[Node Crypto Tests](./test/unit/node.test.ts)** - AES, RSA, ECDSA examples
|
|
434
|
+
- **[File Operations Tests](./test/unit/file-operations.test.ts)** - File encryption for all adapters
|
|
435
|
+
|
|
436
|
+
## Related Packages
|
|
437
|
+
|
|
438
|
+
- **[@happyvertical/email](../email/)** - Email operations with encryption support
|
|
439
|
+
- **[@happyvertical/files](../files/)** - File operations
|
|
440
|
+
- **[@happyvertical/sql](../sql/)** - Database operations (can encrypt fields)
|
|
441
|
+
|
|
442
|
+
## Contributing
|
|
443
|
+
|
|
444
|
+
Contributions are welcome! Please see the root [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.
|
|
445
|
+
|
|
446
|
+
### Development
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
# Install dependencies
|
|
450
|
+
pnpm install
|
|
451
|
+
|
|
452
|
+
# Run tests
|
|
453
|
+
npm test
|
|
454
|
+
|
|
455
|
+
# Run tests in watch mode
|
|
456
|
+
npm test -- --watch
|
|
457
|
+
|
|
458
|
+
# Build package
|
|
459
|
+
npm run build
|
|
460
|
+
|
|
461
|
+
# Lint and format
|
|
462
|
+
npm run lint
|
|
463
|
+
npm run format
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## License
|
|
467
|
+
|
|
468
|
+
MIT License - see [LICENSE](../../LICENSE) for details.
|
|
469
|
+
|
|
470
|
+
## Support
|
|
471
|
+
|
|
472
|
+
- **Issues**: [GitHub Issues](https://github.com/happyvertical/sdk/issues)
|
|
473
|
+
- **Documentation**: [AGENT.md](./AGENT.md)
|
|
474
|
+
- **Examples**: [test/unit/](./test/unit/)
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
**Built with ❤️ by HappyVertical**
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { BaseEncryption } from '../shared/base.js';
|
|
2
|
+
import { DecryptOptions, EncryptionCapabilities, EncryptOptions, ExportKeyOptions, ImportKeyOptions, Key, KeyPair, KeyPairOptions, NaClOptions, SignOptions, VerifyOptions } from '../shared/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* NaCl/TweetNaCl encryption adapter
|
|
5
|
+
*
|
|
6
|
+
* Provides fast, modern cryptography using the NaCl library.
|
|
7
|
+
* Supports both symmetric (secretbox) and asymmetric (box) encryption.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Symmetric encryption
|
|
12
|
+
* const nacl = new NaClEncryption({
|
|
13
|
+
* type: 'nacl',
|
|
14
|
+
* secretKey: secretKey
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* const encrypted = await nacl.encryptText('Secret message');
|
|
18
|
+
* const decrypted = await nacl.decryptText(encrypted);
|
|
19
|
+
*
|
|
20
|
+
* // Asymmetric encryption
|
|
21
|
+
* const nacl = new NaClEncryption({
|
|
22
|
+
* type: 'nacl',
|
|
23
|
+
* publicKey: theirPublicKey,
|
|
24
|
+
* secretKey: mySecretKey
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const encrypted = await nacl.encryptText('Secret message', {
|
|
28
|
+
* recipientPublicKey: theirPublicKey
|
|
29
|
+
* });
|
|
30
|
+
* const decrypted = await nacl.decryptText(encrypted);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class NaClEncryption extends BaseEncryption {
|
|
34
|
+
private options;
|
|
35
|
+
private secretKey?;
|
|
36
|
+
private publicKey?;
|
|
37
|
+
constructor(options: NaClOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Initialize keys from options
|
|
40
|
+
*/
|
|
41
|
+
private initializeKeys;
|
|
42
|
+
/**
|
|
43
|
+
* Parse key from various formats
|
|
44
|
+
*/
|
|
45
|
+
private parseKey;
|
|
46
|
+
/**
|
|
47
|
+
* Format key for output
|
|
48
|
+
*/
|
|
49
|
+
private formatKey;
|
|
50
|
+
encryptText(text: string, options?: EncryptOptions): Promise<string>;
|
|
51
|
+
decryptText(encrypted: string, options?: DecryptOptions): Promise<string>;
|
|
52
|
+
encryptBuffer(buffer: Buffer, options?: EncryptOptions): Promise<Buffer>;
|
|
53
|
+
decryptBuffer(buffer: Buffer, options?: DecryptOptions): Promise<Buffer>;
|
|
54
|
+
/**
|
|
55
|
+
* Symmetric encryption using secretbox
|
|
56
|
+
*/
|
|
57
|
+
private encryptSymmetric;
|
|
58
|
+
/**
|
|
59
|
+
* Asymmetric encryption using box
|
|
60
|
+
*/
|
|
61
|
+
private encryptAsymmetric;
|
|
62
|
+
generateKeyPair(options?: KeyPairOptions): Promise<KeyPair>;
|
|
63
|
+
importKey(key: string | Buffer, options?: ImportKeyOptions): Promise<Key>;
|
|
64
|
+
exportKey(key: Key, options?: ExportKeyOptions): Promise<string | Buffer>;
|
|
65
|
+
/**
|
|
66
|
+
* Sign data with signing key
|
|
67
|
+
*/
|
|
68
|
+
sign(data: string | Buffer, options?: SignOptions): Promise<string | Buffer>;
|
|
69
|
+
/**
|
|
70
|
+
* Verify signature
|
|
71
|
+
*/
|
|
72
|
+
verify(data: string | Buffer, signature: string | Buffer, options?: VerifyOptions): Promise<boolean>;
|
|
73
|
+
getCapabilities(): Promise<EncryptionCapabilities>;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=nacl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nacl.d.ts","sourceRoot":"","sources":["../../src/adapters/nacl.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,GAAG,EACH,OAAO,EACP,cAAc,EACd,WAAW,EACX,WAAW,EACX,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,cAAe,SAAQ,cAAc;IAChD,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,SAAS,CAAC,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAa;gBAEnB,OAAO,EAAE,WAAW;IAMhC;;OAEG;IACH,OAAO,CAAC,cAAc;IA0BtB;;OAEG;IACH,OAAO,CAAC,QAAQ;IA2BhB;;OAEG;IACH,OAAO,CAAC,SAAS;IAgBX,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBpE,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA6DZ,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IAyBZ,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA4DlB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAmDnB,eAAe,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IA2C3D,SAAS,CACb,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,CAAC;IA6CT,SAAS,CACb,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IA0C3B;;OAEG;IACG,IAAI,CACR,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAiD3B;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,OAAO,CAAC;IAgEb,eAAe,IAAI,OAAO,CAAC,sBAAsB,CAAC;CAgBzD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { BaseEncryption } from '../shared/base.js';
|
|
2
|
+
import { DecryptOptions, EncryptionCapabilities, EncryptOptions, ExportKeyOptions, ImportKeyOptions, Key, KeyPair, KeyPairOptions, NodeCryptoOptions, SignOptions, VerifyOptions } from '../shared/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Node.js crypto adapter
|
|
5
|
+
*
|
|
6
|
+
* Uses Node.js built-in crypto module for standard encryption algorithms
|
|
7
|
+
* (AES, RSA, ECDH, ECDSA, etc.).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const crypto = new NodeCryptoEncryption({
|
|
12
|
+
* type: 'node',
|
|
13
|
+
* algorithm: 'aes-256-gcm',
|
|
14
|
+
* key: encryptionKey
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* const encrypted = await crypto.encryptText('Secret message');
|
|
18
|
+
* const decrypted = await crypto.decryptText(encrypted);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare class NodeCryptoEncryption extends BaseEncryption {
|
|
22
|
+
private options;
|
|
23
|
+
private key?;
|
|
24
|
+
private publicKey?;
|
|
25
|
+
private privateKey?;
|
|
26
|
+
constructor(options: NodeCryptoOptions);
|
|
27
|
+
/**
|
|
28
|
+
* Initialize keys from options
|
|
29
|
+
*/
|
|
30
|
+
private initializeKeys;
|
|
31
|
+
/**
|
|
32
|
+
* Derive key from password using PBKDF2
|
|
33
|
+
*/
|
|
34
|
+
private deriveKey;
|
|
35
|
+
/**
|
|
36
|
+
* Get key length for current algorithm
|
|
37
|
+
*/
|
|
38
|
+
private getKeyLength;
|
|
39
|
+
/**
|
|
40
|
+
* Parse buffer from string or Buffer
|
|
41
|
+
*/
|
|
42
|
+
private parseBuffer;
|
|
43
|
+
/**
|
|
44
|
+
* Import public key from PEM/DER
|
|
45
|
+
*/
|
|
46
|
+
private importPublicKeyObject;
|
|
47
|
+
/**
|
|
48
|
+
* Import private key from PEM/DER
|
|
49
|
+
*/
|
|
50
|
+
private importPrivateKeyObject;
|
|
51
|
+
/**
|
|
52
|
+
* Check if algorithm is symmetric (AES)
|
|
53
|
+
*/
|
|
54
|
+
private isSymmetric;
|
|
55
|
+
/**
|
|
56
|
+
* Check if algorithm is RSA
|
|
57
|
+
*/
|
|
58
|
+
private isRSA;
|
|
59
|
+
encryptText(text: string, options?: EncryptOptions): Promise<string>;
|
|
60
|
+
decryptText(encrypted: string, options?: DecryptOptions): Promise<string>;
|
|
61
|
+
encryptBuffer(buffer: Buffer, options?: EncryptOptions): Promise<Buffer>;
|
|
62
|
+
decryptBuffer(buffer: Buffer, options?: DecryptOptions): Promise<Buffer>;
|
|
63
|
+
/**
|
|
64
|
+
* Symmetric encryption (AES)
|
|
65
|
+
*/
|
|
66
|
+
private encryptSymmetric;
|
|
67
|
+
/**
|
|
68
|
+
* Symmetric decryption (AES)
|
|
69
|
+
*/
|
|
70
|
+
private decryptSymmetric;
|
|
71
|
+
/**
|
|
72
|
+
* Asymmetric encryption (RSA)
|
|
73
|
+
*/
|
|
74
|
+
private encryptAsymmetric;
|
|
75
|
+
/**
|
|
76
|
+
* Asymmetric decryption (RSA)
|
|
77
|
+
*/
|
|
78
|
+
private decryptAsymmetric;
|
|
79
|
+
/**
|
|
80
|
+
* Get RSA padding mode
|
|
81
|
+
*/
|
|
82
|
+
private getRSAPadding;
|
|
83
|
+
generateKeyPair(options?: KeyPairOptions): Promise<KeyPair>;
|
|
84
|
+
importKey(key: string | Buffer, options?: ImportKeyOptions): Promise<Key>;
|
|
85
|
+
exportKey(key: Key, options?: ExportKeyOptions): Promise<string | Buffer>;
|
|
86
|
+
/**
|
|
87
|
+
* Sign data
|
|
88
|
+
*/
|
|
89
|
+
sign(data: string | Buffer, options?: SignOptions): Promise<string | Buffer>;
|
|
90
|
+
/**
|
|
91
|
+
* Verify signature
|
|
92
|
+
*/
|
|
93
|
+
verify(data: string | Buffer, signature: string | Buffer, options?: VerifyOptions): Promise<boolean>;
|
|
94
|
+
getCapabilities(): Promise<EncryptionCapabilities>;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,GAAG,EACH,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAqB,SAAQ,cAAc;IACtD,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,GAAG,CAAC,CAAS;IACrB,OAAO,CAAC,SAAS,CAAC,CAAmB;IACrC,OAAO,CAAC,UAAU,CAAC,CAAmB;gBAE1B,OAAO,EAAE,iBAAiB;IAMtC;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;OAEG;IACH,OAAO,CAAC,SAAS;IAmBjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAY7B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACH,OAAO,CAAC,KAAK;IAKP,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BpE,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA4BZ,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA4BZ,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA4BlB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAwCxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA4CxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAWf,eAAe,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAwF3D,SAAS,CACb,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,CAAC;IAoDT,SAAS,CACb,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IA2B3B;;OAEG;IACG,IAAI,CACR,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAuC3B;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,OAAO,CAAC;IA8Bb,eAAe,IAAI,OAAO,CAAC,sBAAsB,CAAC;CAsCzD"}
|