@byearlybird/crypto 0.1.0 → 0.2.0

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 CHANGED
@@ -10,208 +10,263 @@ npm install @byearlybird/crypto
10
10
 
11
11
  ## Quick Start
12
12
 
13
- ### Registration
13
+ ### Encrypt & Decrypt Data
14
14
 
15
15
  ```typescript
16
- import { generateKeys, encryptData } from '@byearlybird/crypto';
16
+ import { generateEncryptionKey, encrypt, decrypt } from '@byearlybird/crypto';
17
17
 
18
- // Generate all keys at once
19
- const { vaultKey, masterKey, encryptedMasterKey } = await generateKeys();
18
+ const key = await generateEncryptionKey();
20
19
 
21
- // Show vault key to user (they must save it!)
22
- console.log('Save this vault key:', vaultKey);
23
-
24
- // Encrypt user data
25
- const encrypted = await encryptData(JSON.stringify({ secret: 'data' }), masterKey);
26
-
27
- // Store on server: encryptedMasterKey + encrypted data
28
- await saveToServer({ encryptedMasterKey, data: encrypted });
20
+ const ciphertext = await encrypt('secret data', key);
21
+ const plaintext = await decrypt(ciphertext, key);
29
22
  ```
30
23
 
31
- ### Login
24
+ ### Sign & Verify Messages
32
25
 
33
26
  ```typescript
34
- import { decryptMasterKey, decryptData } from '@byearlybird/crypto';
27
+ import { generateSigningKeyPair, sign, verify, exportPublicKey } from '@byearlybird/crypto';
35
28
 
36
- // User provides their vault key
37
- const vaultKey = getUserInput();
29
+ const { publicKey, privateKey } = await generateSigningKeyPair(true);
38
30
 
39
- // Fetch from server
40
- const { encryptedMasterKey, data } = await fetchFromServer();
31
+ const signature = await sign('hello', privateKey);
32
+ const valid = await verify('hello', signature, publicKey);
33
+ ```
41
34
 
42
- // Decrypt master key, then decrypt data
43
- const masterKey = await decryptMasterKey(encryptedMasterKey, vaultKey);
44
- const decrypted = await decryptData(data, masterKey);
35
+ ### Signature-Based Auth (eba1)
36
+
37
+ ```typescript
38
+ import {
39
+ generateSigningKeyPair,
40
+ exportPublicKey,
41
+ deriveVaultId,
42
+ createAuthHeader,
43
+ verifyAuthHeader,
44
+ } from '@byearlybird/crypto';
45
+
46
+ const { publicKey, privateKey } = await generateSigningKeyPair(true);
47
+ const pubB64 = await exportPublicKey(publicKey);
48
+ const vaultId = await deriveVaultId(pubB64);
49
+
50
+ // Client: create a signed auth header
51
+ const header = await createAuthHeader({
52
+ vaultId,
53
+ method: 'POST',
54
+ pathWithQuery: '/api/data?page=1',
55
+ serializedBody: JSON.stringify({ hello: 'world' }),
56
+ privateKey,
57
+ });
58
+ // header: "eba1 vid=...;n=...;m=POST;p=/api/data?page=1;t=...;sig=...;bh=..."
59
+
60
+ // Server: verify the header
61
+ const valid = await verifyAuthHeader(header, publicKey);
45
62
  ```
46
63
 
47
64
  ## API Reference
48
65
 
49
- ### `generateKeys()`
66
+ ### Encryption Keys
67
+
68
+ #### `generateEncryptionKey(extractable?)`
50
69
  ```typescript
51
- function generateKeys(): Promise<{
52
- vaultKey: string;
53
- masterKey: CryptoKey;
54
- encryptedMasterKey: string;
55
- }>
70
+ function generateEncryptionKey(extractable?: boolean): Promise<CryptoKey>
56
71
  ```
72
+ Generates a random AES-256-GCM encryption key. `extractable` defaults to `false`.
57
73
 
58
- Generates vault key, master key, and encrypted master key in one call. Convenience method for new users.
74
+ ---
75
+
76
+ #### `exportEncryptionKey(key)`
77
+ ```typescript
78
+ function exportEncryptionKey(key: CryptoKey): Promise<string>
79
+ ```
80
+ Exports an encryption key to a base64 string (raw format).
59
81
 
60
82
  ---
61
83
 
62
- ### `generateVaultKey()`
84
+ #### `importEncryptionKey(base64, extractable?)`
63
85
  ```typescript
64
- function generateVaultKey(): string
86
+ function importEncryptionKey(base64: string, extractable?: boolean): Promise<CryptoKey>
65
87
  ```
88
+ Imports a base64-encoded encryption key. `extractable` defaults to `false`.
89
+
90
+ ---
66
91
 
67
- Generates a random 256-bit vault key (64-char hex string). User must save this.
92
+ #### `encrypt(plaintext, key)`
93
+ ```typescript
94
+ function encrypt(plaintext: string, key: CryptoKey): Promise<string>
95
+ ```
96
+ Encrypts a string with AES-256-GCM. Returns base64 payload (12-byte IV + ciphertext). Fresh random IV per call.
68
97
 
69
98
  ---
70
99
 
71
- ### `generateMasterKey()`
100
+ #### `decrypt(encoded, key)`
72
101
  ```typescript
73
- function generateMasterKey(): Promise<CryptoKey>
102
+ function decrypt(encoded: string, key: CryptoKey): Promise<string>
74
103
  ```
104
+ Decrypts an AES-256-GCM encrypted payload. Throws if the key is wrong or data is tampered with.
105
+
106
+ ---
75
107
 
76
- Generates a random AES-256-GCM master key for encrypting data.
108
+ ### Signing Keys
109
+
110
+ #### `generateSigningKeyPair(extractable?)`
111
+ ```typescript
112
+ function generateSigningKeyPair(extractable?: boolean): Promise<CryptoKeyPair>
113
+ ```
114
+ Generates an Ed25519 signing key pair. `extractable` defaults to `false`.
77
115
 
78
116
  ---
79
117
 
80
- ### `encryptMasterKey(masterKey, vaultKey)`
118
+ #### `exportPublicKey(key)`
81
119
  ```typescript
82
- function encryptMasterKey(
83
- masterKey: CryptoKey,
84
- vaultKey: string
85
- ): Promise<string>
120
+ function exportPublicKey(key: CryptoKey): Promise<string>
86
121
  ```
122
+ Exports a public key to base64 (SPKI format).
123
+
124
+ ---
87
125
 
88
- Encrypts master key with vault key using PBKDF2 (600k iterations). Returns base64 payload (salt + IV + ciphertext).
126
+ #### `importPublicKey(spkiB64, extractable?)`
127
+ ```typescript
128
+ function importPublicKey(spkiB64: string, extractable?: boolean): Promise<CryptoKey>
129
+ ```
130
+ Imports a base64-encoded SPKI public key. `extractable` defaults to `false`.
89
131
 
90
132
  ---
91
133
 
92
- ### `decryptMasterKey(encryptedMasterKey, vaultKey)`
134
+ #### `exportPrivateKey(key)`
93
135
  ```typescript
94
- function decryptMasterKey(
95
- encryptedMasterKey: string,
96
- vaultKey: string
97
- ): Promise<CryptoKey>
136
+ function exportPrivateKey(key: CryptoKey): Promise<string>
98
137
  ```
138
+ Exports a private key to base64 (PKCS8 format).
139
+
140
+ ---
99
141
 
100
- Decrypts encrypted master key. Throws if vault key is wrong or data is corrupted.
142
+ #### `importPrivateKey(pkcs8B64, extractable?)`
143
+ ```typescript
144
+ function importPrivateKey(pkcs8B64: string, extractable?: boolean): Promise<CryptoKey>
145
+ ```
146
+ Imports a base64-encoded PKCS8 private key. `extractable` defaults to `false`.
101
147
 
102
148
  ---
103
149
 
104
- ### `encryptData(data, masterKey)`
150
+ #### `sign(message, privateKey)`
105
151
  ```typescript
106
- function encryptData(
107
- data: string,
108
- masterKey: CryptoKey
109
- ): Promise<string>
152
+ function sign(message: string, privateKey: CryptoKey): Promise<string>
110
153
  ```
154
+ Signs a message using Ed25519. Returns a base64-encoded signature.
155
+
156
+ ---
111
157
 
112
- Encrypts data with master key. Returns base64 payload (IV + ciphertext). Fresh random IV per call.
158
+ #### `verify(message, signatureB64, publicKey)`
159
+ ```typescript
160
+ function verify(message: string, signatureB64: string, publicKey: CryptoKey): Promise<boolean>
161
+ ```
162
+ Verifies an Ed25519 signature. Returns `true` if valid, `false` otherwise.
113
163
 
114
164
  ---
115
165
 
116
- ### `decryptData(encryptedData, masterKey)`
166
+ ### Authentication (eba1)
167
+
168
+ #### `AuthPayload`
117
169
  ```typescript
118
- function decryptData(
119
- encryptedData: string,
120
- masterKey: CryptoKey
121
- ): Promise<string>
170
+ type AuthPayload = {
171
+ scheme: string;
172
+ nonce: string;
173
+ vaultId: string;
174
+ method: string;
175
+ pathWithQuery: string;
176
+ timestamp: number;
177
+ bodyHash?: string;
178
+ }
122
179
  ```
123
180
 
124
- Decrypts data. Throws if key is wrong or data is tampered with (GCM authentication).
181
+ ---
182
+
183
+ #### `deriveVaultId(publicKeyB64)`
184
+ ```typescript
185
+ function deriveVaultId(publicKeyB64: string): Promise<string>
186
+ ```
187
+ Derives a 32-character hex vault ID from a base64-encoded public key (SHA-256 of SPKI bytes, truncated).
125
188
 
126
189
  ---
127
190
 
128
- ### `deriveEncryptionKey(vaultKey, salt?)`
191
+ #### `parseAuthHeader(header)`
129
192
  ```typescript
130
- function deriveEncryptionKey(
131
- vaultKey: string,
132
- salt?: Uint8Array
133
- ): Promise<{ key: CryptoKey; salt: Uint8Array }>
193
+ function parseAuthHeader(header: string): AuthPayload & { signature: string }
134
194
  ```
195
+ Parses an eba1 auth header string back into its components. Throws on malformed or unsupported headers.
135
196
 
136
- Low-level PBKDF2 key derivation. Used internally by `encryptMasterKey`/`decryptMasterKey`.
197
+ ---
198
+
199
+ #### `createAuthHeader(args)`
200
+ ```typescript
201
+ function createAuthHeader(args: {
202
+ vaultId: string;
203
+ method: 'GET' | 'PUT' | 'POST' | 'PATCH' | 'DELETE';
204
+ pathWithQuery: string;
205
+ serializedBody?: string;
206
+ privateKey: CryptoKey;
207
+ }): Promise<string>
208
+ ```
209
+ Creates a complete signed auth header. Generates a nonce/timestamp, hashes the body if provided, signs the canonical string, and returns the formatted header.
137
210
 
138
211
  ---
139
212
 
140
- ### `hash(data)`
213
+ #### `verifyAuthHeader(header, publicKey)`
141
214
  ```typescript
142
- function hash(data: string): Promise<string>
215
+ function verifyAuthHeader(header: string, publicKey: CryptoKey): Promise<boolean>
143
216
  ```
217
+ Verifies an eba1 auth header against a public key. Parses the header, reconstructs the canonical string, and verifies the signature. Returns `true` if valid.
144
218
 
145
- Computes SHA-256 hash of a string. Returns hex-encoded digest (64 chars).
219
+ ---
220
+
221
+ ### Utilities
222
+
223
+ #### `bytesToBase64(bytes)`
224
+ ```typescript
225
+ function bytesToBase64(bytes: Uint8Array): string
226
+ ```
227
+ Converts a byte array to a base64 string.
146
228
 
147
229
  ---
148
230
 
149
- ### `hashObject(obj)`
231
+ #### `base64ToBytes(base64)`
150
232
  ```typescript
151
- function hashObject(obj: unknown): Promise<string>
233
+ function base64ToBytes(base64: string): Uint8Array
152
234
  ```
235
+ Converts a base64 string to a byte array.
153
236
 
154
- Computes SHA-256 hash of a JSON-serializable object. Returns hex-encoded digest (64 chars). Objects must be JSON serializable. Property order is normalized for consistent hashing.
237
+ ---
238
+
239
+ #### `hashString(value)`
240
+ ```typescript
241
+ function hashString(value: string): Promise<string>
242
+ ```
243
+ Computes SHA-256 hash of a string. Returns hex-encoded digest (64 chars).
155
244
 
156
245
  ## Security
157
246
 
158
247
  **Cryptographic primitives:**
159
248
  - AES-256-GCM (authenticated encryption)
160
- - PBKDF2-SHA256 (600k iterations, OWASP 2023)
249
+ - Ed25519 (digital signatures)
161
250
  - SHA-256 (content hashing)
162
- - 128-bit salts, 96-bit IVs
251
+ - 96-bit IVs
163
252
  - `crypto.getRandomValues()` for all randomness
164
253
 
165
254
  **E2EE model:**
166
255
  - All encryption happens client-side
167
256
  - Server only sees ciphertext
168
- - Vault key never leaves client
169
257
  - Fresh IV per encryption (no reuse)
170
- - Self-contained ciphertexts (IVs and salts embedded)
171
-
172
- **Important:**
173
- - Users must save vault keys securely (no recovery if lost)
174
- - Use HTTPS to prevent code injection
258
+ - Self-contained ciphertexts (IVs embedded)
175
259
  - GCM authentication detects tampering
176
- - Vault keys are case-insensitive (normalized to lowercase)
177
-
178
- ## Examples
179
-
180
- ### Password Change
181
-
182
- ```typescript
183
- // Re-encrypt master key with new vault key
184
- const masterKey = await decryptMasterKey(encrypted, oldVaultKey);
185
- const newEncrypted = await encryptMasterKey(masterKey, newVaultKey);
186
- // Update on server (user data doesn't need re-encryption)
187
- ```
188
-
189
- ### Multiple Items
190
260
 
191
- ```typescript
192
- const masterKey = await generateMasterKey();
193
- const items = ['item1', 'item2', 'item3'];
194
- const encrypted = await Promise.all(
195
- items.map(item => encryptData(item, masterKey))
196
- );
197
- // Each has different ciphertext (fresh IV)
198
- ```
199
-
200
- ### Hashing
201
-
202
- ```typescript
203
- import { hash, hashObject } from '@byearlybird/crypto';
204
-
205
- // Hash a string
206
- const digest = await hash('hello world');
207
-
208
- // Hash an object (must be JSON serializable)
209
- const objHash = await hashObject({ user: 'alice', id: 123 });
210
- ```
261
+ **Signature-based auth:**
262
+ - Ed25519 key pairs for request signing
263
+ - Nonce + timestamp prevent replay attacks
264
+ - Optional body hash ensures payload integrity
265
+ - Canonical string format for deterministic signing
211
266
 
212
267
  ## Browser Compatibility
213
268
 
214
- Requires Web Crypto API (Chrome 37+, Firefox 34+, Safari 11+, all modern mobile browsers).
269
+ Requires Web Crypto API and Ed25519 support (Chrome 113+, Firefox 130+, Safari 17+).
215
270
 
216
271
  ## License
217
272
 
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as crypto0 from "crypto";
2
2
 
3
- //#region src/eb-auth.d.ts
3
+ //#region src/auth.d.ts
4
4
  type AuthPayload = {
5
5
  scheme: string;
6
6
  nonce: string;
@@ -11,26 +11,26 @@ type AuthPayload = {
11
11
  bodyHash?: string;
12
12
  };
13
13
  declare function deriveVaultId(publicKeyB64: string): Promise<string>;
14
- declare function generateAuthPayload(args: {
14
+ declare function createAuthHeader(args: {
15
15
  vaultId: string;
16
16
  method: "GET" | "PUT" | "POST" | "PATCH" | "DELETE";
17
17
  pathWithQuery: string;
18
18
  serializedBody?: string;
19
- }): Promise<AuthPayload>;
20
- declare function makeCanonicalString(payload: AuthPayload): string;
21
- declare function makeAuthHeader(payload: AuthPayload, signature: string): string;
19
+ privateKey: CryptoKey;
20
+ }): Promise<string>;
22
21
  declare function parseAuthHeader(header: string): AuthPayload & {
23
22
  signature: string;
24
23
  };
24
+ declare function verifyAuthHeader(header: string, publicKey: CryptoKey): Promise<boolean>;
25
25
  //#endregion
26
- //#region src/encryption-keys.d.ts
26
+ //#region src/encryption.d.ts
27
27
  declare function generateEncryptionKey(extractable?: boolean): Promise<crypto0.webcrypto.CryptoKey>;
28
28
  declare function exportEncryptionKey(key: CryptoKey): Promise<string>;
29
29
  declare function importEncryptionKey(base64: string, extractable?: boolean): Promise<crypto0.webcrypto.CryptoKey>;
30
30
  declare function encrypt(plaintext: string, key: CryptoKey): Promise<string>;
31
31
  declare function decrypt(encoded: string, key: CryptoKey): Promise<string>;
32
32
  //#endregion
33
- //#region src/signing-keys.d.ts
33
+ //#region src/signing.d.ts
34
34
  declare function generateSigningKeyPair(extractable?: boolean): Promise<CryptoKeyPair>;
35
35
  declare function exportPublicKey(key: CryptoKey): Promise<string>;
36
36
  declare function importPublicKey(spkiB64: string, extractable?: boolean): Promise<CryptoKey>;
@@ -44,4 +44,4 @@ declare function bytesToBase64(bytes: Uint8Array): string;
44
44
  declare function base64ToBytes(base64: string): Uint8Array;
45
45
  declare function hashString(value: string): Promise<string>;
46
46
  //#endregion
47
- export { AuthPayload, base64ToBytes, bytesToBase64, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateAuthPayload, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, makeAuthHeader, makeCanonicalString, parseAuthHeader, sign, verify };
47
+ export { AuthPayload, base64ToBytes, bytesToBase64, createAuthHeader, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, parseAuthHeader, sign, verify, verifyAuthHeader };
package/dist/index.mjs CHANGED
@@ -1,3 +1,34 @@
1
+ //#region src/signing.ts
2
+ async function generateSigningKeyPair(extractable = false) {
3
+ return crypto.subtle.generateKey("Ed25519", extractable, ["sign", "verify"]);
4
+ }
5
+ async function exportPublicKey(key) {
6
+ const spki = await crypto.subtle.exportKey("spki", key);
7
+ return Buffer.from(spki).toString("base64");
8
+ }
9
+ async function importPublicKey(spkiB64, extractable = false) {
10
+ const spkiDer = Buffer.from(spkiB64, "base64");
11
+ return await crypto.subtle.importKey("spki", spkiDer, "Ed25519", extractable, ["verify"]);
12
+ }
13
+ async function exportPrivateKey(key) {
14
+ const pkcs8 = await crypto.subtle.exportKey("pkcs8", key);
15
+ return Buffer.from(pkcs8).toString("base64");
16
+ }
17
+ async function importPrivateKey(pkcs8B64, extractable = false) {
18
+ return await crypto.subtle.importKey("pkcs8", Buffer.from(pkcs8B64, "base64"), "Ed25519", extractable, ["sign"]);
19
+ }
20
+ async function sign(message, privateKey) {
21
+ const data = new TextEncoder().encode(message);
22
+ const signature = await crypto.subtle.sign("Ed25519", privateKey, data);
23
+ return Buffer.from(signature).toString("base64");
24
+ }
25
+ async function verify(message, signatureB64, publicKey) {
26
+ const data = new TextEncoder().encode(message);
27
+ const signature = Buffer.from(signatureB64, "base64");
28
+ return crypto.subtle.verify("Ed25519", publicKey, signature, data);
29
+ }
30
+
31
+ //#endregion
1
32
  //#region src/utils.ts
2
33
  function bytesToBase64(bytes) {
3
34
  return Buffer.from(bytes).toString("base64");
@@ -11,13 +42,56 @@ async function hashString(value) {
11
42
  }
12
43
 
13
44
  //#endregion
14
- //#region src/eb-auth.ts
15
- const CURRENT_SCHEME = "eb1";
45
+ //#region src/auth.ts
46
+ const CURRENT_SCHEME = "eba1";
16
47
  async function deriveVaultId(publicKeyB64) {
17
48
  const spkiBytes = Buffer.from(publicKeyB64, "base64");
18
49
  const hash = await crypto.subtle.digest("SHA-256", spkiBytes);
19
50
  return Buffer.from(hash).toString("hex").slice(0, 32);
20
51
  }
52
+ async function createAuthHeader(args) {
53
+ const { privateKey,...payloadArgs } = args;
54
+ const payload = await generateAuthPayload(payloadArgs);
55
+ return makeAuthHeader(payload, await sign(makeCanonicalString(payload), privateKey));
56
+ }
57
+ function parseAuthHeader(header) {
58
+ const spaceIdx = header.indexOf(" ");
59
+ if (spaceIdx === -1) throw new Error("Malformed auth header: missing scheme separator");
60
+ const scheme = header.slice(0, spaceIdx);
61
+ if (scheme !== CURRENT_SCHEME) throw new Error(`Unsupported auth scheme: ${scheme}`);
62
+ const paramStr = header.slice(spaceIdx + 1);
63
+ const params = /* @__PURE__ */ new Map();
64
+ for (const part of paramStr.split(";")) {
65
+ const eqIdx = part.indexOf("=");
66
+ if (eqIdx === -1) throw new Error(`Malformed auth header param: ${part}`);
67
+ params.set(part.slice(0, eqIdx), part.slice(eqIdx + 1));
68
+ }
69
+ const vid = params.get("vid");
70
+ const n = params.get("n");
71
+ const m = params.get("m");
72
+ const p = params.get("p");
73
+ const t = params.get("t");
74
+ const sig = params.get("sig");
75
+ if (!vid || !n || !m || !p || !t || !sig) throw new Error("Malformed auth header: missing required params");
76
+ const timestamp = Number(t);
77
+ if (Number.isNaN(timestamp)) throw new Error("Malformed auth header: timestamp is not a number");
78
+ const result = {
79
+ scheme,
80
+ vaultId: vid,
81
+ nonce: n,
82
+ method: m,
83
+ pathWithQuery: p,
84
+ timestamp,
85
+ signature: sig
86
+ };
87
+ const bh = params.get("bh");
88
+ if (bh) result.bodyHash = bh;
89
+ return result;
90
+ }
91
+ async function verifyAuthHeader(header, publicKey) {
92
+ const { signature,...payload } = parseAuthHeader(header);
93
+ return verify(makeCanonicalString(payload), signature, publicKey);
94
+ }
21
95
  async function generateAuthPayload(args) {
22
96
  const { serializedBody,...rest } = args;
23
97
  const nonce = crypto.randomUUID();
@@ -55,43 +129,9 @@ function makeAuthHeader(payload, signature) {
55
129
  if (payload.bodyHash) params.push(`bh=${payload.bodyHash}`);
56
130
  return `${payload.scheme} ${params.join(";")}`;
57
131
  }
58
- function parseAuthHeader(header) {
59
- const spaceIdx = header.indexOf(" ");
60
- if (spaceIdx === -1) throw new Error("Malformed auth header: missing scheme separator");
61
- const scheme = header.slice(0, spaceIdx);
62
- if (scheme !== CURRENT_SCHEME) throw new Error(`Unsupported auth scheme: ${scheme}`);
63
- const paramStr = header.slice(spaceIdx + 1);
64
- const params = /* @__PURE__ */ new Map();
65
- for (const part of paramStr.split(";")) {
66
- const eqIdx = part.indexOf("=");
67
- if (eqIdx === -1) throw new Error(`Malformed auth header param: ${part}`);
68
- params.set(part.slice(0, eqIdx), part.slice(eqIdx + 1));
69
- }
70
- const vid = params.get("vid");
71
- const n = params.get("n");
72
- const m = params.get("m");
73
- const p = params.get("p");
74
- const t = params.get("t");
75
- const sig = params.get("sig");
76
- if (!vid || !n || !m || !p || !t || !sig) throw new Error("Malformed auth header: missing required params");
77
- const timestamp = Number(t);
78
- if (Number.isNaN(timestamp)) throw new Error("Malformed auth header: timestamp is not a number");
79
- const result = {
80
- scheme,
81
- vaultId: vid,
82
- nonce: n,
83
- method: m,
84
- pathWithQuery: p,
85
- timestamp,
86
- signature: sig
87
- };
88
- const bh = params.get("bh");
89
- if (bh) result.bodyHash = bh;
90
- return result;
91
- }
92
132
 
93
133
  //#endregion
94
- //#region src/encryption-keys.ts
134
+ //#region src/encryption.ts
95
135
  async function generateEncryptionKey(extractable = false) {
96
136
  return crypto.subtle.generateKey({
97
137
  name: "AES-GCM",
@@ -128,35 +168,4 @@ async function decrypt(encoded, key) {
128
168
  }
129
169
 
130
170
  //#endregion
131
- //#region src/signing-keys.ts
132
- async function generateSigningKeyPair(extractable = false) {
133
- return crypto.subtle.generateKey("Ed25519", extractable, ["sign", "verify"]);
134
- }
135
- async function exportPublicKey(key) {
136
- const spki = await crypto.subtle.exportKey("spki", key);
137
- return Buffer.from(spki).toString("base64");
138
- }
139
- async function importPublicKey(spkiB64, extractable = false) {
140
- const spkiDer = Buffer.from(spkiB64, "base64");
141
- return await crypto.subtle.importKey("spki", spkiDer, "Ed25519", extractable, ["verify"]);
142
- }
143
- async function exportPrivateKey(key) {
144
- const pkcs8 = await crypto.subtle.exportKey("pkcs8", key);
145
- return Buffer.from(pkcs8).toString("base64");
146
- }
147
- async function importPrivateKey(pkcs8B64, extractable = false) {
148
- return await crypto.subtle.importKey("pkcs8", Buffer.from(pkcs8B64, "base64"), "Ed25519", extractable, ["sign"]);
149
- }
150
- async function sign(message, privateKey) {
151
- const data = new TextEncoder().encode(message);
152
- const signature = await crypto.subtle.sign("Ed25519", privateKey, data);
153
- return Buffer.from(signature).toString("base64");
154
- }
155
- async function verify(message, signatureB64, publicKey) {
156
- const data = new TextEncoder().encode(message);
157
- const signature = Buffer.from(signatureB64, "base64");
158
- return crypto.subtle.verify("Ed25519", publicKey, signature, data);
159
- }
160
-
161
- //#endregion
162
- export { base64ToBytes, bytesToBase64, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateAuthPayload, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, makeAuthHeader, makeCanonicalString, parseAuthHeader, sign, verify };
171
+ export { base64ToBytes, bytesToBase64, createAuthHeader, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, parseAuthHeader, sign, verify, verifyAuthHeader };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byearlybird/crypto",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Lightweight E2EE toolkit for web apps - zero dependencies + vault key security",
5
5
  "type": "module",
6
6
  "license": "MIT",