@byearlybird/crypto 0.2.0 → 0.4.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/dist/index.d.mts CHANGED
@@ -10,6 +10,25 @@ type AuthPayload = {
10
10
  timestamp: number;
11
11
  bodyHash?: string;
12
12
  };
13
+ type ParseSuccess = {
14
+ ok: true;
15
+ data: AuthPayload;
16
+ signature: string;
17
+ };
18
+ type ParseFailure = {
19
+ ok: false;
20
+ message: string;
21
+ };
22
+ type ParseResult = ParseSuccess | ParseFailure;
23
+ type ValidateSuccess = {
24
+ ok: true;
25
+ data: AuthPayload;
26
+ };
27
+ type ValidateFailure = {
28
+ ok: false;
29
+ message: string;
30
+ };
31
+ type ValidateResult = ValidateSuccess | ValidateFailure;
13
32
  declare function deriveVaultId(publicKeyB64: string): Promise<string>;
14
33
  declare function createAuthHeader(args: {
15
34
  vaultId: string;
@@ -18,10 +37,14 @@ declare function createAuthHeader(args: {
18
37
  serializedBody?: string;
19
38
  privateKey: CryptoKey;
20
39
  }): Promise<string>;
21
- declare function parseAuthHeader(header: string): AuthPayload & {
22
- signature: string;
23
- };
24
- declare function verifyAuthHeader(header: string, publicKey: CryptoKey): Promise<boolean>;
40
+ declare function parseAuthHeader(header: string): ParseResult;
41
+ declare function validateAuthPayload(payload: AuthPayload, options: {
42
+ vaultId: string;
43
+ method: string;
44
+ path: string;
45
+ ttl: number;
46
+ body?: string;
47
+ }): Promise<ValidateResult>;
25
48
  //#endregion
26
49
  //#region src/encryption.d.ts
27
50
  declare function generateEncryptionKey(extractable?: boolean): Promise<crypto0.webcrypto.CryptoKey>;
@@ -44,4 +67,4 @@ declare function bytesToBase64(bytes: Uint8Array): string;
44
67
  declare function base64ToBytes(base64: string): Uint8Array;
45
68
  declare function hashString(value: string): Promise<string>;
46
69
  //#endregion
47
- export { AuthPayload, base64ToBytes, bytesToBase64, createAuthHeader, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, parseAuthHeader, sign, verify, verifyAuthHeader };
70
+ export { AuthPayload, ParseFailure, ParseResult, ParseSuccess, ValidateFailure, ValidateResult, ValidateSuccess, base64ToBytes, bytesToBase64, createAuthHeader, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, parseAuthHeader, sign, validateAuthPayload, verify };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/signing.ts
2
2
  async function generateSigningKeyPair(extractable = false) {
3
- return crypto.subtle.generateKey("Ed25519", extractable, ["sign", "verify"]);
3
+ return await crypto.subtle.generateKey("Ed25519", extractable, ["sign", "verify"]);
4
4
  }
5
5
  async function exportPublicKey(key) {
6
6
  const spki = await crypto.subtle.exportKey("spki", key);
@@ -55,6 +55,49 @@ async function createAuthHeader(args) {
55
55
  return makeAuthHeader(payload, await sign(makeCanonicalString(payload), privateKey));
56
56
  }
57
57
  function parseAuthHeader(header) {
58
+ try {
59
+ return parseAuthHeaderInternal(header);
60
+ } catch {
61
+ return {
62
+ ok: false,
63
+ message: "Malformed auth header"
64
+ };
65
+ }
66
+ }
67
+ async function validateAuthPayload(payload, options) {
68
+ if (payload.vaultId !== options.vaultId) return {
69
+ ok: false,
70
+ message: "Vault id mismatch"
71
+ };
72
+ if (payload.method !== options.method) return {
73
+ ok: false,
74
+ message: "Method mismatch"
75
+ };
76
+ if (payload.pathWithQuery !== options.path) return {
77
+ ok: false,
78
+ message: "Path mismatch"
79
+ };
80
+ if (Math.abs(Date.now() - payload.timestamp) > options.ttl) return {
81
+ ok: false,
82
+ message: "Expired"
83
+ };
84
+ if (payload.bodyHash) {
85
+ if (!options.body) return {
86
+ ok: false,
87
+ message: "Body hash mismatch"
88
+ };
89
+ const serverHash = await hashString(options.body);
90
+ if (payload.bodyHash !== serverHash) return {
91
+ ok: false,
92
+ message: "Body hash mismatch"
93
+ };
94
+ }
95
+ return {
96
+ ok: true,
97
+ data: payload
98
+ };
99
+ }
100
+ function parseAuthHeaderInternal(header) {
58
101
  const spaceIdx = header.indexOf(" ");
59
102
  if (spaceIdx === -1) throw new Error("Malformed auth header: missing scheme separator");
60
103
  const scheme = header.slice(0, spaceIdx);
@@ -75,22 +118,21 @@ function parseAuthHeader(header) {
75
118
  if (!vid || !n || !m || !p || !t || !sig) throw new Error("Malformed auth header: missing required params");
76
119
  const timestamp = Number(t);
77
120
  if (Number.isNaN(timestamp)) throw new Error("Malformed auth header: timestamp is not a number");
78
- const result = {
121
+ const data = {
79
122
  scheme,
80
123
  vaultId: vid,
81
124
  nonce: n,
82
125
  method: m,
83
126
  pathWithQuery: p,
84
- timestamp,
85
- signature: sig
127
+ timestamp
86
128
  };
87
129
  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);
130
+ if (bh) data.bodyHash = bh;
131
+ return {
132
+ ok: true,
133
+ data,
134
+ signature: sig
135
+ };
94
136
  }
95
137
  async function generateAuthPayload(args) {
96
138
  const { serializedBody,...rest } = args;
@@ -168,4 +210,4 @@ async function decrypt(encoded, key) {
168
210
  }
169
211
 
170
212
  //#endregion
171
- export { base64ToBytes, bytesToBase64, createAuthHeader, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, parseAuthHeader, sign, verify, verifyAuthHeader };
213
+ export { base64ToBytes, bytesToBase64, createAuthHeader, decrypt, deriveVaultId, encrypt, exportEncryptionKey, exportPrivateKey, exportPublicKey, generateEncryptionKey, generateSigningKeyPair, hashString, importEncryptionKey, importPrivateKey, importPublicKey, parseAuthHeader, sign, validateAuthPayload, verify };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byearlybird/crypto",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Lightweight E2EE toolkit for web apps - zero dependencies + vault key security",
5
5
  "type": "module",
6
6
  "license": "MIT",