@ubay182/sveltekit-hpke-wrapper 1.0.2 โ†’ 1.0.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 (2) hide show
  1. package/README.md +180 -154
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4,12 +4,12 @@ HPKE (Hybrid Public Key Encryption) wrapper for SvelteKit applications with end-
4
4
 
5
5
  ## ๐Ÿš€ Features
6
6
 
7
- - โœ… **Complete HPKE Implementation** - RFC 9180 compliant
8
- - โœ… **End-to-End Encryption** - Client โ†” Server encryption
9
- - โœ… **SvelteKit Integration** - Ready-to-use API endpoint creators
10
- - โœ… **TypeScript Support** - Full type definitions
11
- - โœ… **X25519 Key Exchange** - Elliptic curve Diffie-Hellman
12
- - โœ… **AES-128-GCM & ChaCha20** - Authenticated encryption
7
+ - โœ… **Complete HPKE Implementation** โ€” RFC 9180 compliant
8
+ - โœ… **End-to-End Encryption** โ€” Client โ†” Server encryption
9
+ - โœ… **SvelteKit Integration** โ€” Ready-to-use API endpoint creators
10
+ - โœ… **TypeScript Support** โ€” Full type definitions
11
+ - โœ… **X25519 Key Exchange** โ€” Elliptic curve Diffie-Hellman
12
+ - โœ… **AES-128-GCM & ChaCha20-Poly1305** โ€” Authenticated encryption
13
13
 
14
14
  ## ๐Ÿ“ฆ Installation
15
15
 
@@ -17,76 +17,128 @@ HPKE (Hybrid Public Key Encryption) wrapper for SvelteKit applications with end-
17
17
  npm install @ubay182/sveltekit-hpke-wrapper
18
18
  # or
19
19
  pnpm add @ubay182/sveltekit-hpke-wrapper
20
- # or
21
- yarn add @ubay182/sveltekit-hpke-wrapper
22
20
  ```
23
21
 
24
22
  ## ๐ŸŽฏ Quick Start
25
23
 
26
- ### 1. Basic Usage (Client-Side)
24
+ ### 1. Client-Side (Svelte Component)
25
+
26
+ ```svelte
27
+ <script lang="ts">
28
+ import {
29
+ generateKeyPair,
30
+ hpkeEncrypt,
31
+ hpkeDecrypt,
32
+ uint8ArrayToBase64,
33
+ base64ToUint8Array,
34
+ createHpkeSuite
35
+ } from '@ubay182/sveltekit-hpke-wrapper';
36
+
37
+ let serverPubKey = $state<any>(null);
38
+ let clientPrivKey = $state<any>(null);
39
+ let clientPubKeyB64 = $state('');
40
+ let decryptedText = $state('');
41
+
42
+ // Step 1: Fetch server public key
43
+ async function getServerKey() {
44
+ const res = await fetch('/api/hpke-keys');
45
+ const data = await res.json();
46
+
47
+ const keyBytes = base64ToUint8Array(data.publicKey);
48
+ const suite = createHpkeSuite();
49
+ serverPubKey = await suite.kem.importKey('raw', keyBytes.buffer as ArrayBuffer, true);
50
+ }
27
51
 
28
- ```typescript
29
- import {
30
- generateKeyPair,
31
- hpkeEncrypt,
32
- hpkeDecrypt,
33
- exportKeyToBase64,
34
- importKeyFromBase64
35
- } from '@ubay182/sveltekit-hpke-wrapper';
52
+ // Step 2: Generate client key pair
53
+ async function generateClientKeys() {
54
+ const keys = await generateKeyPair();
55
+ clientPrivKey = keys.privateKey;
56
+ clientPubKeyB64 = uint8ArrayToBase64(keys.publicKeyRaw);
57
+ }
36
58
 
37
- // Generate key pair
38
- const { publicKey, privateKey, publicKeyRaw } = await generateKeyPair();
59
+ // Step 3: Encrypt & send
60
+ async function encryptAndSend(payload: any) {
61
+ const message = JSON.stringify(payload);
62
+ const result = await hpkeEncrypt(message, serverPubKey);
39
63
 
40
- // Export public key for transmission
41
- const publicKeyBase64 = exportKeyToBase64(publicKey);
64
+ const ciphertext = uint8ArrayToBase64(new Uint8Array(result.ciphertext));
65
+ const enc = uint8ArrayToBase64(new Uint8Array(result.enc));
42
66
 
43
- // Import server's public key
44
- const serverPublicKey = await importKeyFromBase64(serverPublicKeyBase64);
67
+ const res = await fetch('/api/hpke-proxy', {
68
+ method: 'POST',
69
+ headers: { 'Content-Type': 'application/json' },
70
+ body: JSON.stringify({ ciphertext, enc, clientPublicKey: clientPubKeyB64 })
71
+ });
45
72
 
46
- // Encrypt message
47
- const { ciphertext, enc } = await hpkeEncrypt('Secret message', serverPublicKey);
73
+ const data = await res.json();
74
+ return data; // { ciphertext, enc }
75
+ }
48
76
 
49
- // Decrypt message
50
- const decrypted = await hpkeDecrypt(ciphertext, enc, privateKey);
51
- ```
77
+ // Step 4: Decrypt server response
78
+ async function decryptResponse(encryptedData: { ciphertext: string; enc: string }) {
79
+ const ct = base64ToUint8Array(encryptedData.ciphertext);
80
+ const enc = base64ToUint8Array(encryptedData.enc);
52
81
 
53
- ### 2. Server-Side with SvelteKit
82
+ decryptedText = await hpkeDecrypt(
83
+ ct.buffer as ArrayBuffer,
84
+ enc.buffer as ArrayBuffer,
85
+ clientPrivKey
86
+ );
87
+ }
88
+ </script>
89
+ ```
54
90
 
55
- ```typescript
56
- // src/routes/api/hpke/+server.ts
57
- import { createHpkeEndpoint } from '@ubay182/sveltekit-hpke-wrapper';
91
+ ### 2. Server-Side (SvelteKit Routes)
58
92
 
59
- const { GET, POST } = createHpkeEndpoint({
60
- onRequest: async (decryptedData, request) => {
61
- // Process the decrypted request
62
- const response = await fetch('https://api.example.com/data', {
63
- method: 'POST',
64
- headers: { 'Content-Type': 'application/json' },
65
- body: JSON.stringify(decryptedData)
66
- });
93
+ Create a shared HPKE server instance so all routes use the same key pair:
67
94
 
68
- return await response.json();
69
- }
70
- });
95
+ ```typescript
96
+ // src/lib/hpke-server-instance.ts
97
+ import { createHpkeServer, type HpkeServerInstance } from '@ubay182/sveltekit-hpke-wrapper';
71
98
 
72
- export { GET, POST };
99
+ export const hpkeServer: HpkeServerInstance = createHpkeServer({ autoGenerateKeys: false });
73
100
  ```
74
101
 
75
- ### 3. Manual Server Setup
102
+ ```typescript
103
+ // src/routes/api/hpke-keys/+server.ts
104
+ import { hpkeServer } from '$lib/hpke-server-instance';
105
+
106
+ export async function GET() {
107
+ const publicKey = await hpkeServer.init();
108
+
109
+ return new Response(
110
+ JSON.stringify({
111
+ publicKey,
112
+ algorithm: 'X25519-HKDF-SHA256',
113
+ aead: 'AES-128-GCM'
114
+ }),
115
+ {
116
+ headers: { 'Content-Type': 'application/json' }
117
+ }
118
+ );
119
+ }
120
+ ```
76
121
 
77
122
  ```typescript
78
- import { createHpkeServer } from '@ubay182/sveltekit-hpke-wrapper';
123
+ // src/routes/api/hpke-proxy/+server.ts
124
+ import { hpkeServer } from '$lib/hpke-server-instance';
125
+
126
+ export async function POST({ request }: { request: Request }) {
127
+ const body = await request.json();
128
+ const { ciphertext, enc, clientPublicKey } = body;
79
129
 
80
- const server = createHpkeServer();
130
+ // Decrypt client message
131
+ const decrypted = await hpkeServer.decrypt(ciphertext, enc, clientPublicKey);
81
132
 
82
- // Get server public key
83
- const publicKey = server.getPublicKeyBase64();
133
+ // ... process decrypted data, call external APIs, etc. ...
84
134
 
85
- // Decrypt client message
86
- const decrypted = await server.decrypt(ciphertext, enc, clientPublicKey);
135
+ // Encrypt response
136
+ const encrypted = await hpkeServer.encrypt(responseData, clientPublicKey);
87
137
 
88
- // Encrypt response
89
- const encrypted = await server.encrypt(responseData, clientPublicKey);
138
+ return new Response(JSON.stringify(encrypted), {
139
+ headers: { 'Content-Type': 'application/json' }
140
+ });
141
+ }
90
142
  ```
91
143
 
92
144
  ## ๐Ÿ“š API Reference
@@ -99,59 +151,76 @@ Generate a new HPKE key pair.
99
151
 
100
152
  ```typescript
101
153
  async function generateKeyPair(): Promise<{
102
- publicKey: any; // XCryptoKey for HPKE operations
103
- privateKey: any; // XCryptoKey for HPKE operations
154
+ publicKey: any; // XCryptoKey
155
+ privateKey: any; // XCryptoKey
104
156
  publicKeyRaw: Uint8Array; // Raw bytes for transmission
105
157
  }>;
106
158
  ```
107
159
 
108
160
  #### `hpkeEncrypt(message, recipientPublicKey)`
109
161
 
110
- Encrypt a message.
162
+ Encrypt a message. Returns `{ ciphertext: ArrayBuffer, enc: ArrayBuffer }`.
111
163
 
112
164
  ```typescript
113
- async function hpkeEncrypt(
114
- message: string,
115
- recipientPublicKey: any
116
- ): Promise<{
117
- ciphertext: ArrayBuffer;
118
- enc: ArrayBuffer;
119
- }>;
165
+ const { ciphertext, enc } = await hpkeEncrypt('Secret message', serverPublicKey);
120
166
  ```
121
167
 
122
168
  #### `hpkeDecrypt(ciphertext, enc, recipientPrivateKey)`
123
169
 
124
- Decrypt a message.
170
+ Decrypt a message. Returns plaintext string.
125
171
 
126
172
  ```typescript
127
- async function hpkeDecrypt(
128
- ciphertext: ArrayBuffer,
129
- enc: Uint8Array | ArrayBuffer,
130
- recipientPrivateKey: any
131
- ): Promise<string>;
173
+ const decrypted = await hpkeDecrypt(ciphertextBuffer, encBuffer, privateKey);
174
+ ```
175
+
176
+ #### `createHpkeSuite()`
177
+
178
+ Create an HPKE suite with AES-128-GCM.
179
+
180
+ ```typescript
181
+ const suite = createHpkeSuite();
182
+ const keyPair = await suite.kem.generateKeyPair();
183
+ const importedKey = await suite.kem.importKey('raw', keyBytes.buffer, true);
184
+ ```
185
+
186
+ #### `createHpkeSuiteChaCha20()`
187
+
188
+ Create an HPKE suite with ChaCha20-Poly1305.
189
+
190
+ ```typescript
191
+ const suite = createHpkeSuiteChaCha20();
132
192
  ```
133
193
 
134
194
  #### `exportKeyToBase64(publicKey)`
135
195
 
136
- Export public key to base64.
196
+ Export public key to base64 string.
137
197
 
138
198
  ```typescript
139
- function exportKeyToBase64(publicKey: any): string;
199
+ const b64 = exportKeyToBase64(publicKey);
140
200
  ```
141
201
 
142
202
  #### `importKeyFromBase64(base64)`
143
203
 
144
- Import public key from base64.
204
+ Import public key from base64 string.
205
+
206
+ ```typescript
207
+ const publicKey = await importKeyFromBase64(b64String);
208
+ ```
209
+
210
+ #### `uint8ArrayToBase64(data)` / `base64ToUint8Array(base64)`
211
+
212
+ Utility functions for encoding/decoding.
145
213
 
146
214
  ```typescript
147
- async function importKeyFromBase64(base64: string): Promise<any>;
215
+ const b64 = uint8ArrayToBase64(bytes);
216
+ const bytes = base64ToUint8Array(b64);
148
217
  ```
149
218
 
150
219
  ### Server Functions
151
220
 
152
221
  #### `createHpkeServer(config?)`
153
222
 
154
- Create HPKE server instance.
223
+ Create an HPKE server instance with key management.
155
224
 
156
225
  ```typescript
157
226
  interface HpkeServerConfig {
@@ -159,15 +228,10 @@ interface HpkeServerConfig {
159
228
  }
160
229
 
161
230
  interface HpkeServerInstance {
231
+ init(): Promise<string>; // Generate keys, return public key as base64
162
232
  getPublicKeyBase64(): string;
163
233
  decrypt(ciphertext: string, enc: string, clientPublicKey: string): Promise<string>;
164
- encrypt(
165
- message: string,
166
- clientPublicKey: string
167
- ): Promise<{
168
- ciphertext: string;
169
- enc: string;
170
- }>;
234
+ encrypt(message: string, clientPublicKey: string): Promise<{ ciphertext: string; enc: string }>;
171
235
  }
172
236
  ```
173
237
 
@@ -175,93 +239,59 @@ interface HpkeServerInstance {
175
239
 
176
240
  #### `createHpkeEndpoint(config?)`
177
241
 
178
- Create complete API endpoints.
179
-
180
- ```typescript
181
- interface HpkeEndpointConfig {
182
- autoGenerateKeys?: boolean;
183
- onRequest?: (decrypted: any, request: Request) => Promise<any>;
184
- onError?: (error: Error, request: Request) => Promise<Response>;
185
- }
186
- ```
187
-
188
- ## ๐Ÿ”ง Advanced Usage
189
-
190
- ### Custom Algorithm (ChaCha20-Poly1305)
191
-
192
- ```typescript
193
- import { createHpkeSuiteChaCha20 } from '@ubay182/sveltekit-hpke-wrapper';
194
-
195
- const suite = createHpkeSuiteChaCha20();
196
- // Use suite for encryption/decryption
197
- ```
198
-
199
- ### Manual Key Management
200
-
201
- ```typescript
202
- import { createHpkeServer } from '@ubay182/sveltekit-hpke-wrapper';
203
-
204
- // Disable auto-generation
205
- const server = createHpkeServer({ autoGenerateKeys: false });
206
-
207
- // Set keys manually later
208
- // (You'll need to extend the server instance with a setKeys method)
209
- ```
210
-
211
- ### Error Handling
242
+ Create complete GET/POST handlers for a SvelteKit route.
212
243
 
213
244
  ```typescript
214
245
  const { GET, POST } = createHpkeEndpoint({
215
- onError: async (error, request) => {
216
- console.error('HPKE Error:', error);
217
-
218
- return new Response(
219
- JSON.stringify({
220
- error: 'Encryption failed',
221
- code: 'HPKE_ERROR'
222
- }),
223
- { status: 500 }
224
- );
246
+ onRequest: async (decryptedData, request) => {
247
+ // Process decrypted request
248
+ return await fetch('https://api.example.com/data', {
249
+ method: 'POST',
250
+ body: JSON.stringify(decryptedData)
251
+ }).then((r) => r.json());
225
252
  }
226
253
  });
227
254
  ```
228
255
 
229
- ## ๐Ÿ” Security Notes
230
-
231
- โš ๏ธ **Important**: This is a wrapper library for convenience. For production:
232
-
233
- 1. **Key Storage**: Use HSM, AWS KMS, or Azure Key Vault
234
- 2. **HTTPS**: Always use HTTPS in production
235
- 3. **Authentication**: Implement proper auth mechanisms
236
- 4. **Rate Limiting**: Add rate limiting to prevent abuse
237
- 5. **Key Rotation**: Implement regular key rotation
238
- 6. **Audit**: Have security audits performed
239
-
240
- ## ๐Ÿ“– How It Works
256
+ ## ๐Ÿ” How It Works
241
257
 
242
258
  ```
243
259
  Client Server
244
260
  โ”‚ โ”‚
245
- โ”œโ”€โ”€โ”€ GET /api/hpke โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚
261
+ โ”œโ”€โ”€โ”€ GET /api/hpke-keys โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚
246
262
  โ”‚ โ”‚
247
263
  โ”‚<โ”€โ”€โ”€โ”€ Public Key (base64) โ”€โ”€โ”€โ”€โ”‚
248
264
  โ”‚ โ”‚
249
- โ”œโ”€โ”€โ”€ Encrypt with Public Key โ”€โ”€โ”‚
265
+ โ”œโ”€โ”€โ”€ generateKeyPair() โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ (client generates its own keys)
266
+ โ”‚ โ”‚
267
+ โ”œโ”€โ”€โ”€ hpkeEncrypt(payload) โ”€โ”€โ”€โ”€โ”‚
250
268
  โ”‚ โ”‚
251
- โ”œโ”€โ”€โ”€ POST Encrypted Data โ”€โ”€โ”€โ”€โ”€>โ”‚
269
+ โ”œโ”€โ”€โ”€ POST { ciphertext, enc, โ”€>โ”‚
270
+ โ”‚ clientPublicKey } โ”‚
252
271
  โ”‚ โ”‚
253
- โ”‚ โ”œโ”€โ”€โ”€ Decrypt โ”€โ”€โ”
254
- โ”‚ โ”‚ โ”‚
255
- โ”‚ โ”‚<โ”€โ”€ Process โ”€โ”€โ”€โ”˜
272
+ โ”‚ โ”œโ”€โ”€โ”€ decrypt() โ”€โ”€โ”
273
+ โ”‚ โ”‚ โ”‚
274
+ โ”‚ โ”‚<โ”€โ”€ Process โ”€โ”€โ”€โ”€โ”€โ”˜
275
+ โ”‚ โ”‚ โ”‚
276
+ โ”‚ โ”‚<โ”€โ”€ encrypt() โ”€โ”€โ”€โ”˜
256
277
  โ”‚ โ”‚
257
- โ”‚ โ”œโ”€โ”€โ”€ Encrypt โ”€โ”€โ”
258
- โ”‚ โ”‚ โ”‚
259
- โ”‚<โ”€โ”€โ”€โ”€ Encrypted Response โ”€โ”€โ”€โ”€โ”€โ”‚<โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
278
+ โ”‚<โ”€โ”€โ”€โ”€ { ciphertext, enc } โ”€โ”€โ”€โ”€โ”‚
260
279
  โ”‚ โ”‚
261
- โ””โ”€โ”€โ”€ Decrypt Response โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
280
+ โ””โ”€โ”€โ”€ hpkeDecrypt(response) โ”€โ”€โ”€โ”€โ”˜
262
281
  ```
263
282
 
264
- ## ๐Ÿงช Testing
283
+ ## ๐Ÿ” Security Notes
284
+
285
+ โš ๏ธ **Important**: This is a convenience wrapper library. For production:
286
+
287
+ 1. **Key Storage** โ€” Use HSM, AWS KMS, or Azure Key Vault
288
+ 2. **HTTPS** โ€” Always use HTTPS in production
289
+ 3. **Authentication** โ€” Implement proper auth mechanisms
290
+ 4. **Rate Limiting** โ€” Add rate limiting to prevent abuse
291
+ 5. **Key Rotation** โ€” Implement regular key rotation
292
+ 6. **Audit** โ€” Have security audits performed
293
+
294
+ ## ๐Ÿงช Development
265
295
 
266
296
  ```bash
267
297
  # Build the package
@@ -270,7 +300,7 @@ npm run build
270
300
  # Type check
271
301
  npm run lint
272
302
 
273
- # Watch mode for development
303
+ # Watch mode
274
304
  npm run dev
275
305
  ```
276
306
 
@@ -278,12 +308,8 @@ npm run dev
278
308
 
279
309
  MIT
280
310
 
281
- ## ๐Ÿค Contributing
282
-
283
- Contributions are welcome! Please feel free to submit a Pull Request.
284
-
285
311
  ## ๐Ÿ“š Resources
286
312
 
287
- - [RFC 9180 - HPKE Specification](https://www.rfc-editor.org/rfc/rfc9180.html)
313
+ - [RFC 9180 โ€” HPKE Specification](https://www.rfc-editor.org/rfc/rfc9180.html)
288
314
  - [hpke-js Library](https://github.com/dajiaji/hpke-js)
289
315
  - [SvelteKit Documentation](https://kit.svelte.dev/docs)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubay182/sveltekit-hpke-wrapper",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "HPKE (Hybrid Public Key Encryption) wrapper for SvelteKit applications with end-to-end encryption support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",