@lightsparkdev/core 0.2.0 → 0.2.2

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 (58) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/chunk-23X5L5S3.js +604 -0
  3. package/dist/chunk-4OZ5E62P.js +608 -0
  4. package/dist/chunk-5FD46UVI.js +600 -0
  5. package/dist/chunk-BAQMCJ7C.js +630 -0
  6. package/dist/chunk-GFTKZSHK.js +627 -0
  7. package/dist/chunk-I3HKDOEE.js +627 -0
  8. package/dist/chunk-J6LSW6XO.js +601 -0
  9. package/dist/chunk-JUD4MOOQ.js +608 -0
  10. package/dist/chunk-KX6HH6CX.js +629 -0
  11. package/dist/chunk-MZCDWVLH.js +634 -0
  12. package/dist/chunk-NY3BK66J.js +624 -0
  13. package/dist/chunk-Q7UUXZNC.js +26 -0
  14. package/dist/chunk-WT2HYC6Q.js +601 -0
  15. package/dist/chunk-YYVOX4YM.js +600 -0
  16. package/dist/chunk-ZUIUADXH.js +616 -0
  17. package/dist/crypto-rn-2BYOHLMG.js +72 -0
  18. package/dist/crypto-rn-2YV53C3B.js +72 -0
  19. package/dist/crypto-rn-3HFXYG7I.js +75 -0
  20. package/dist/crypto-rn-3HLWLVZS.js +76 -0
  21. package/dist/crypto-rn-3N3JTBLE.js +83 -0
  22. package/dist/crypto-rn-3OEMMMOD.js +74 -0
  23. package/dist/crypto-rn-5EZSRY5Y.js +82 -0
  24. package/dist/crypto-rn-5KM2YVOI.js +82 -0
  25. package/dist/crypto-rn-6335R2CU.js +80 -0
  26. package/dist/crypto-rn-6ZHSL7CX.js +72 -0
  27. package/dist/crypto-rn-7DWXMO2Q.js +75 -0
  28. package/dist/crypto-rn-7GTI374I.js +81 -0
  29. package/dist/crypto-rn-AXDY3LDG.js +124 -0
  30. package/dist/crypto-rn-BZ2KZ2YR.js +68 -0
  31. package/dist/crypto-rn-CAPL7MYC.js +80 -0
  32. package/dist/crypto-rn-CBAKEB7C.js +68 -0
  33. package/dist/crypto-rn-CBWHV2F5.js +82 -0
  34. package/dist/crypto-rn-CS36MQ4X.js +77 -0
  35. package/dist/crypto-rn-E4RZNGIB.js +82 -0
  36. package/dist/crypto-rn-H4NIT5CT.js +70 -0
  37. package/dist/crypto-rn-IAC27WLZ.js +74 -0
  38. package/dist/crypto-rn-LLY6FCWE.js +82 -0
  39. package/dist/crypto-rn-MOWVVG3L.js +78 -0
  40. package/dist/crypto-rn-OAPLHNM5.js +73 -0
  41. package/dist/crypto-rn-PVAG5TVH.js +80 -0
  42. package/dist/crypto-rn-QLVBL5DI.js +75 -0
  43. package/dist/crypto-rn-TBKXR3SR.js +68 -0
  44. package/dist/crypto-rn-TSQJA6A3.js +81 -0
  45. package/dist/crypto-rn-U3XEJXIM.js +77 -0
  46. package/dist/crypto-rn-UHTZEVAR.js +74 -0
  47. package/dist/crypto-rn-V3ZNQSFI.js +79 -0
  48. package/dist/crypto-rn-VGNP6VZW.js +75 -0
  49. package/dist/crypto-rn-XMYCUEGV.js +72 -0
  50. package/dist/crypto-rn-YPOTC5RI.js +73 -0
  51. package/dist/index.cjs +93 -116
  52. package/dist/index.d.ts +31 -17
  53. package/dist/index.js +92 -106
  54. package/package.json +2 -1
  55. package/src/crypto/NodeKeyCache.ts +18 -15
  56. package/src/crypto/crypto.ts +72 -78
  57. package/src/requester/Requester.ts +11 -17
  58. package/src/utils/base64.ts +51 -2
package/dist/index.js CHANGED
@@ -34,14 +34,44 @@ var StubAuthProvider = class {
34
34
  };
35
35
 
36
36
  // src/utils/base64.ts
37
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
38
+ var Base64 = {
39
+ btoa: (input = "") => {
40
+ let str = input;
41
+ let output = "";
42
+ for (let block = 0, charCode, i = 0, map = chars; str.charAt(i | 0) || (map = "=", i % 1); output += map.charAt(63 & block >> 8 - i % 1 * 8)) {
43
+ charCode = str.charCodeAt(i += 3 / 4);
44
+ if (charCode > 255) {
45
+ throw new Error(
46
+ "'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
47
+ );
48
+ }
49
+ block = block << 8 | charCode;
50
+ }
51
+ return output;
52
+ },
53
+ atob: (input = "") => {
54
+ let str = input.replace(/=+$/, "");
55
+ let output = "";
56
+ if (str.length % 4 == 1) {
57
+ throw new Error(
58
+ "'atob' failed: The string to be decoded is not correctly encoded."
59
+ );
60
+ }
61
+ for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++); ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0) {
62
+ buffer = chars.indexOf(buffer);
63
+ }
64
+ return output;
65
+ }
66
+ };
37
67
  var b64decode = (encoded) => {
38
- return Uint8Array.from(atob(encoded), (c) => c.charCodeAt(0));
68
+ return Uint8Array.from(Base64.atob(encoded), (c) => c.charCodeAt(0));
39
69
  };
40
70
  var urlsafe_b64decode = (encoded) => {
41
71
  return b64decode(encoded.replace(/_/g, "/").replace(/-/g, "+"));
42
72
  };
43
73
  var b64encode = (data) => {
44
- return btoa(
74
+ return Base64.btoa(
45
75
  String.fromCharCode.apply(null, Array.from(new Uint8Array(data)))
46
76
  );
47
77
  };
@@ -55,8 +85,7 @@ var LightsparkSigningException = class extends LightsparkException_default {
55
85
  var LightsparkSigningException_default = LightsparkSigningException;
56
86
 
57
87
  // src/crypto/crypto.ts
58
- var ITERATIONS = 5e5;
59
- function getCrypto() {
88
+ var getCrypto = () => {
60
89
  let cryptoImplPromise;
61
90
  if (typeof crypto !== "undefined") {
62
91
  cryptoImplPromise = Promise.resolve(crypto);
@@ -66,34 +95,26 @@ function getCrypto() {
66
95
  });
67
96
  }
68
97
  return cryptoImplPromise;
69
- }
70
- var getRandomValues = async (arr) => {
71
- if (typeof crypto !== "undefined") {
72
- return crypto.getRandomValues(arr);
73
- } else {
74
- const cryptoImpl2 = await getCrypto();
75
- return cryptoImpl2.getRandomValues(arr);
76
- }
77
98
  };
78
99
  var getRandomValues32 = async (arr) => {
79
100
  if (typeof crypto !== "undefined") {
80
101
  return crypto.getRandomValues(arr);
81
102
  } else {
82
- const cryptoImpl2 = await getCrypto();
83
- return cryptoImpl2.getRandomValues(arr);
103
+ const cryptoImpl = await getCrypto();
104
+ return cryptoImpl.getRandomValues(arr);
84
105
  }
85
106
  };
86
107
  var deriveKey = async (password, salt, iterations, algorithm, bit_len) => {
87
108
  const enc = new TextEncoder();
88
- const cryptoImpl2 = await getCrypto();
89
- const password_key = await cryptoImpl2.subtle.importKey(
109
+ const cryptoImpl = await getCrypto();
110
+ const password_key = await cryptoImpl.subtle.importKey(
90
111
  "raw",
91
112
  enc.encode(password),
92
113
  "PBKDF2",
93
114
  false,
94
115
  ["deriveBits", "deriveKey"]
95
116
  );
96
- const derived = await cryptoImpl2.subtle.deriveBits(
117
+ const derived = await cryptoImpl.subtle.deriveBits(
97
118
  {
98
119
  name: "PBKDF2",
99
120
  salt,
@@ -103,7 +124,7 @@ var deriveKey = async (password, salt, iterations, algorithm, bit_len) => {
103
124
  password_key,
104
125
  bit_len
105
126
  );
106
- const key = await cryptoImpl2.subtle.importKey(
127
+ const key = await cryptoImpl.subtle.importKey(
107
128
  "raw",
108
129
  derived.slice(0, 32),
109
130
  { name: algorithm, length: 256 },
@@ -113,25 +134,6 @@ var deriveKey = async (password, salt, iterations, algorithm, bit_len) => {
113
134
  const iv = derived.slice(32);
114
135
  return [key, iv];
115
136
  };
116
- var encrypt = async (plaintext, password, salt) => {
117
- if (!salt) {
118
- salt = new Uint8Array(16);
119
- getRandomValues(salt);
120
- }
121
- const [key, iv] = await deriveKey(password, salt, ITERATIONS, "AES-GCM", 352);
122
- const cryptoImpl2 = await getCrypto();
123
- const encrypted = new Uint8Array(
124
- await cryptoImpl2.subtle.encrypt({ name: "AES-GCM", iv }, key, plaintext)
125
- );
126
- const output = new Uint8Array(salt.byteLength + encrypted.byteLength);
127
- output.set(salt);
128
- output.set(encrypted, salt.byteLength);
129
- const header = {
130
- v: 4,
131
- i: ITERATIONS
132
- };
133
- return [JSON.stringify(header), b64encode(output)];
134
- };
135
137
  var decrypt = async (header_json, ciphertext, password) => {
136
138
  var decoded = b64decode(ciphertext);
137
139
  var header;
@@ -150,7 +152,7 @@ var decrypt = async (header_json, ciphertext, password) => {
150
152
  "Unknown version ".concat(header.v)
151
153
  );
152
154
  }
153
- const cryptoImpl2 = await getCrypto();
155
+ const cryptoImpl = await getCrypto();
154
156
  const algorithm = header.v < 2 ? "AES-CBC" : "AES-GCM";
155
157
  const bit_len = header.v < 4 ? 384 : 352;
156
158
  const salt_len = header.v < 4 ? 8 : 16;
@@ -165,7 +167,7 @@ var decrypt = async (header_json, ciphertext, password) => {
165
167
  algorithm,
166
168
  256
167
169
  );
168
- return await cryptoImpl2.subtle.decrypt(
170
+ return await cryptoImpl.subtle.decrypt(
169
171
  { name: algorithm, iv: nonce.buffer },
170
172
  key,
171
173
  cipherText
@@ -180,7 +182,7 @@ var decrypt = async (header_json, ciphertext, password) => {
180
182
  algorithm,
181
183
  bit_len
182
184
  );
183
- return await cryptoImpl2.subtle.decrypt(
185
+ return await cryptoImpl.subtle.decrypt(
184
186
  { name: algorithm, iv },
185
187
  key,
186
188
  encrypted
@@ -196,13 +198,9 @@ async function decryptSecretWithNodePassword(cipher, encryptedSecret, nodePasswo
196
198
  }
197
199
  return decryptedValue;
198
200
  }
199
- function decode(arrBuff) {
200
- const dec = new TextDecoder();
201
- return dec.decode(arrBuff);
202
- }
203
201
  var generateSigningKeyPair = async () => {
204
- const cryptoImpl2 = await getCrypto();
205
- return await cryptoImpl2.subtle.generateKey(
202
+ const cryptoImpl = await getCrypto();
203
+ return await cryptoImpl.subtle.generateKey(
206
204
  /*algorithm:*/
207
205
  {
208
206
  name: "RSA-PSS",
@@ -217,74 +215,72 @@ var generateSigningKeyPair = async () => {
217
215
  );
218
216
  };
219
217
  var serializeSigningKey = async (key, format) => {
220
- const cryptoImpl2 = await getCrypto();
221
- return await cryptoImpl2.subtle.exportKey(
218
+ const cryptoImpl = await getCrypto();
219
+ return await cryptoImpl.subtle.exportKey(
222
220
  /*format*/
223
221
  format,
224
222
  /*key*/
225
223
  key
226
224
  );
227
225
  };
228
- var encryptWithNodeKey = async (key, data) => {
229
- const enc = new TextEncoder();
230
- const encoded = enc.encode(data);
231
- const encrypted = await cryptoImpl.subtle.encrypt(
232
- /*algorithm:*/
226
+ var getNonce = async () => {
227
+ const cryptoImpl = await getCrypto();
228
+ const nonceSt = await getRandomValues32(new Uint32Array(1));
229
+ return Number(nonceSt);
230
+ };
231
+ var sign = async (key, data) => {
232
+ const cryptoImpl = await getCrypto();
233
+ return await cryptoImpl.subtle.sign(
233
234
  {
234
- name: "RSA-OAEP"
235
+ name: "RSA-PSS",
236
+ saltLength: 32
235
237
  },
236
- /*key*/
237
238
  key,
238
- /*data*/
239
- encoded
239
+ data
240
240
  );
241
- return b64encode(encrypted);
242
241
  };
243
- var loadNodeEncryptionKey = async (rawPublicKey) => {
244
- const encoded = b64decode(rawPublicKey);
245
- const cryptoImpl2 = await getCrypto();
246
- return await cryptoImpl2.subtle.importKey(
242
+ var importPrivateSigningKey = async (keyData, format) => {
243
+ const cryptoImpl = await getCrypto();
244
+ return await cryptoImpl.subtle.importKey(
247
245
  /*format*/
248
- "spki",
246
+ format,
249
247
  /*keyData*/
250
- encoded,
251
- /*algorithm:*/
248
+ keyData,
249
+ /*algorithm*/
252
250
  {
253
- name: "RSA-OAEP",
251
+ name: "RSA-PSS",
254
252
  hash: "SHA-256"
255
253
  },
256
254
  /*extractable*/
257
255
  true,
258
256
  /*keyUsages*/
259
- ["encrypt"]
257
+ ["sign"]
260
258
  );
261
259
  };
262
- var getNonce = async () => {
263
- const nonceSt = await getRandomValues32(new Uint32Array(1));
264
- return Number(nonceSt);
260
+ var DefaultCrypto = {
261
+ decryptSecretWithNodePassword,
262
+ generateSigningKeyPair,
263
+ serializeSigningKey,
264
+ getNonce,
265
+ sign,
266
+ importPrivateSigningKey
265
267
  };
266
268
 
267
269
  // src/crypto/NodeKeyCache.ts
268
270
  import autoBind from "auto-bind";
269
271
  var NodeKeyCache = class {
270
- idToKey;
271
- constructor() {
272
+ constructor(cryptoImpl = DefaultCrypto) {
273
+ this.cryptoImpl = cryptoImpl;
272
274
  this.idToKey = /* @__PURE__ */ new Map();
273
275
  autoBind(this);
274
276
  }
275
- async loadKey(id, rawKey) {
276
- const decoded = b64decode(rawKey);
277
+ idToKey;
278
+ async loadKey(id, rawKey, format = "pkcs8") {
279
+ const decoded = b64decode(this.stripPemTags(rawKey));
277
280
  try {
278
- const cryptoImpl2 = await getCrypto();
279
- const key = await cryptoImpl2.subtle.importKey(
280
- "pkcs8",
281
+ const key = await this.cryptoImpl.importPrivateSigningKey(
281
282
  decoded,
282
- {
283
- name: "RSA-PSS",
284
- hash: "SHA-256"
285
- },
286
- true,
287
- ["sign"]
283
+ format
288
284
  );
289
285
  this.idToKey.set(id, key);
290
286
  return key;
@@ -299,6 +295,9 @@ var NodeKeyCache = class {
299
295
  hasKey(id) {
300
296
  return this.idToKey.has(id);
301
297
  }
298
+ stripPemTags(pem) {
299
+ return pem.replace(/-----BEGIN (.*)-----/, "").replace(/-----END (.*)----/, "");
300
+ }
302
301
  };
303
302
  var NodeKeyCache_default = NodeKeyCache;
304
303
 
@@ -320,11 +319,13 @@ var LIGHTSPARK_BETA_HEADER_KEY = "X-Lightspark-Beta";
320
319
  var LIGHTSPARK_BETA_HEADER_VALUE = "z2h0BBYxTA83cjW7fi8QwWtBPCzkQKiemcuhKY08LOo";
321
320
  dayjs.extend(utc);
322
321
  var Requester = class {
323
- constructor(nodeKeyCache, schemaEndpoint, authProvider = new StubAuthProvider(), baseUrl = DEFAULT_BASE_URL) {
322
+ constructor(nodeKeyCache, schemaEndpoint, sdkUserAgent, authProvider = new StubAuthProvider(), baseUrl = DEFAULT_BASE_URL, cryptoImpl = DefaultCrypto) {
324
323
  this.nodeKeyCache = nodeKeyCache;
325
324
  this.schemaEndpoint = schemaEndpoint;
325
+ this.sdkUserAgent = sdkUserAgent;
326
326
  this.authProvider = authProvider;
327
327
  this.baseUrl = baseUrl;
328
+ this.cryptoImpl = cryptoImpl;
328
329
  let websocketImpl;
329
330
  if (typeof WebSocket === "undefined" && typeof window === "undefined") {
330
331
  websocketImpl = NodeWebSocket;
@@ -441,8 +442,7 @@ var Requester = class {
441
442
  getSdkUserAgent() {
442
443
  const platform = isNode ? "NodeJS" : "Browser";
443
444
  const platformVersion = isNode ? process.version : "";
444
- const sdkVersion = "1.0.4";
445
- return `lightspark-js-sdk/${sdkVersion} ${platform}/${platformVersion}`;
445
+ return `${this.sdkUserAgent} ${platform}/${platformVersion}`;
446
446
  }
447
447
  async addSigningDataIfNeeded(queryPayload, headers, signingNodeId) {
448
448
  if (!signingNodeId) {
@@ -451,7 +451,7 @@ var Requester = class {
451
451
  const query = queryPayload.query;
452
452
  const variables = queryPayload.variables;
453
453
  const operationName = queryPayload.operationName;
454
- const nonce = await getNonce();
454
+ const nonce = await this.cryptoImpl.getNonce();
455
455
  const expiration = dayjs.utc().add(1, "hour").format();
456
456
  const payload = {
457
457
  query,
@@ -466,16 +466,11 @@ var Requester = class {
466
466
  "Missing node of encrypted_signing_private_key"
467
467
  );
468
468
  }
469
+ if (typeof TextEncoder === "undefined") {
470
+ const TextEncoder2 = (await import("text-encoding")).TextEncoder;
471
+ }
469
472
  const encodedPayload = new TextEncoder().encode(JSON.stringify(payload));
470
- const cryptoImpl2 = await getCrypto();
471
- const signedPayload = await cryptoImpl2.subtle.sign(
472
- {
473
- name: "RSA-PSS",
474
- saltLength: 32
475
- },
476
- key,
477
- encodedPayload
478
- );
473
+ const signedPayload = await this.cryptoImpl.sign(key, encodedPayload);
479
474
  const encodedSignedPayload = b64encode(signedPayload);
480
475
  headers["X-Lightspark-Signing"] = JSON.stringify({
481
476
  v: "1",
@@ -574,6 +569,7 @@ var isType = (typename) => (node) => {
574
569
  return node?.__typename === typename;
575
570
  };
576
571
  export {
572
+ DefaultCrypto,
577
573
  LightsparkAuthException_default as LightsparkAuthException,
578
574
  LightsparkException_default as LightsparkException,
579
575
  LightsparkSigningException_default as LightsparkSigningException,
@@ -585,18 +581,8 @@ export {
585
581
  b64decode,
586
582
  b64encode,
587
583
  convertCurrencyAmount,
588
- decode,
589
- decrypt,
590
- decryptSecretWithNodePassword,
591
- encrypt,
592
- encryptWithNodeKey,
593
- generateSigningKeyPair,
594
- getCrypto,
595
- getNonce,
596
584
  isBrowser,
597
585
  isNode,
598
586
  isType,
599
- loadNodeEncryptionKey,
600
- serializeSigningKey,
601
587
  urlsafe_b64decode
602
588
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightsparkdev/core",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Lightspark JS SDK",
5
5
  "author": "Lightspark Inc.",
6
6
  "keywords": [
@@ -52,6 +52,7 @@
52
52
  "dayjs": "^1.11.7",
53
53
  "graphql": "^16.6.0",
54
54
  "graphql-ws": "^5.11.3",
55
+ "text-encoding": "^0.7.0",
55
56
  "ws": "^8.12.1",
56
57
  "zen-observable-ts": "^1.1.0"
57
58
  },
@@ -3,28 +3,25 @@
3
3
  import autoBind from "auto-bind";
4
4
 
5
5
  import { b64decode } from "../utils/base64.js";
6
- import { getCrypto } from "./crypto.js";
6
+ import { CryptoInterface, DefaultCrypto } from "./crypto.js";
7
7
 
8
8
  class NodeKeyCache {
9
- private idToKey: Map<string, CryptoKey>;
10
- constructor() {
9
+ private idToKey: Map<string, CryptoKey | Uint8Array>;
10
+ constructor(private readonly cryptoImpl: CryptoInterface = DefaultCrypto) {
11
11
  this.idToKey = new Map();
12
12
  autoBind(this);
13
13
  }
14
14
 
15
- public async loadKey(id: string, rawKey: string): Promise<CryptoKey | null> {
16
- const decoded = b64decode(rawKey);
15
+ public async loadKey(
16
+ id: string,
17
+ rawKey: string,
18
+ format: "pkcs8" | "spki" = "pkcs8"
19
+ ): Promise<CryptoKey | Uint8Array | null> {
20
+ const decoded = b64decode(this.stripPemTags(rawKey));
17
21
  try {
18
- const cryptoImpl = await getCrypto();
19
- const key = await cryptoImpl.subtle.importKey(
20
- "pkcs8",
22
+ const key = await this.cryptoImpl.importPrivateSigningKey(
21
23
  decoded,
22
- {
23
- name: "RSA-PSS",
24
- hash: "SHA-256",
25
- },
26
- true,
27
- ["sign"]
24
+ format
28
25
  );
29
26
  this.idToKey.set(id, key);
30
27
  return key;
@@ -34,13 +31,19 @@ class NodeKeyCache {
34
31
  return null;
35
32
  }
36
33
 
37
- public getKey(id: string): CryptoKey | undefined {
34
+ public getKey(id: string): CryptoKey | Uint8Array | undefined {
38
35
  return this.idToKey.get(id);
39
36
  }
40
37
 
41
38
  public hasKey(id: string): boolean {
42
39
  return this.idToKey.has(id);
43
40
  }
41
+
42
+ private stripPemTags(pem: string): string {
43
+ return pem
44
+ .replace(/-----BEGIN (.*)-----/, "")
45
+ .replace(/-----END (.*)----/, "");
46
+ }
44
47
  }
45
48
 
46
49
  export default NodeKeyCache;
@@ -1,11 +1,36 @@
1
1
  // Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved
2
2
  import LightsparkException from "../LightsparkException.js";
3
3
 
4
- import { b64decode, b64encode } from "../utils/base64.js";
4
+ import { b64decode } from "../utils/base64.js";
5
5
 
6
- const ITERATIONS = 500000;
6
+ export type CryptoInterface = {
7
+ decryptSecretWithNodePassword: (
8
+ cipher: string,
9
+ encryptedSecret: string,
10
+ nodePassword: string
11
+ ) => Promise<ArrayBuffer | null>;
7
12
 
8
- export function getCrypto() {
13
+ generateSigningKeyPair: () => Promise<{
14
+ publicKey: CryptoKey | string;
15
+ privateKey: CryptoKey | string;
16
+ }>;
17
+
18
+ serializeSigningKey: (
19
+ key: CryptoKey | string,
20
+ format: "pkcs8" | "spki"
21
+ ) => Promise<ArrayBuffer>;
22
+
23
+ getNonce: () => Promise<number>;
24
+
25
+ sign: (key: CryptoKey | Uint8Array, data: Uint8Array) => Promise<ArrayBuffer>;
26
+
27
+ importPrivateSigningKey: (
28
+ keyData: Uint8Array,
29
+ format: "pkcs8" | "spki"
30
+ ) => Promise<CryptoKey | Uint8Array>;
31
+ };
32
+
33
+ const getCrypto = () => {
9
34
  let cryptoImplPromise: Promise<typeof crypto>;
10
35
  if (typeof crypto !== "undefined") {
11
36
  cryptoImplPromise = Promise.resolve(crypto);
@@ -15,15 +40,6 @@ export function getCrypto() {
15
40
  });
16
41
  }
17
42
  return cryptoImplPromise;
18
- }
19
-
20
- const getRandomValues = async (arr: Uint8Array): Promise<Uint8Array> => {
21
- if (typeof crypto !== "undefined") {
22
- return crypto.getRandomValues(arr);
23
- } else {
24
- const cryptoImpl = await getCrypto();
25
- return cryptoImpl.getRandomValues(arr);
26
- }
27
43
  };
28
44
 
29
45
  const getRandomValues32 = async (arr: Uint32Array): Promise<Uint32Array> => {
@@ -77,36 +93,7 @@ const deriveKey = async (
77
93
  return [key, iv];
78
94
  };
79
95
 
80
- export const encrypt = async (
81
- plaintext: ArrayBuffer,
82
- password: string,
83
- salt?: Uint8Array
84
- ): Promise<[string, string]> => {
85
- if (!salt) {
86
- salt = new Uint8Array(16);
87
- getRandomValues(salt);
88
- }
89
-
90
- const [key, iv] = await deriveKey(password, salt, ITERATIONS, "AES-GCM", 352);
91
- const cryptoImpl = await getCrypto();
92
-
93
- const encrypted = new Uint8Array(
94
- await cryptoImpl.subtle.encrypt({ name: "AES-GCM", iv }, key, plaintext)
95
- );
96
-
97
- const output = new Uint8Array(salt.byteLength + encrypted.byteLength);
98
- output.set(salt);
99
- output.set(encrypted, salt.byteLength);
100
-
101
- const header = {
102
- v: 4,
103
- i: ITERATIONS,
104
- };
105
-
106
- return [JSON.stringify(header), b64encode(output)];
107
- };
108
-
109
- export const decrypt = async (
96
+ const decrypt = async (
110
97
  header_json: string,
111
98
  ciphertext: string,
112
99
  password: string
@@ -172,7 +159,7 @@ export const decrypt = async (
172
159
  }
173
160
  };
174
161
 
175
- export async function decryptSecretWithNodePassword(
162
+ async function decryptSecretWithNodePassword(
176
163
  cipher: string,
177
164
  encryptedSecret: string,
178
165
  nodePassword: string
@@ -188,12 +175,9 @@ export async function decryptSecretWithNodePassword(
188
175
  return decryptedValue;
189
176
  }
190
177
 
191
- export function decode(arrBuff: ArrayBuffer): string {
192
- const dec = new TextDecoder();
193
- return dec.decode(arrBuff);
194
- }
195
-
196
- export const generateSigningKeyPair = async (): Promise<CryptoKeyPair> => {
178
+ const generateSigningKeyPair = async (): Promise<
179
+ CryptoKeyPair | { publicKey: string; privateKey: string }
180
+ > => {
197
181
  const cryptoImpl = await getCrypto();
198
182
  return await cryptoImpl.subtle.generateKey(
199
183
  /*algorithm:*/ {
@@ -207,52 +191,62 @@ export const generateSigningKeyPair = async (): Promise<CryptoKeyPair> => {
207
191
  );
208
192
  };
209
193
 
210
- export const serializeSigningKey = async (
211
- key: CryptoKey,
194
+ const serializeSigningKey = async (
195
+ key: CryptoKey | string,
212
196
  format: "pkcs8" | "spki"
213
197
  ): Promise<ArrayBuffer> => {
214
198
  const cryptoImpl = await getCrypto();
215
- return await cryptoImpl.subtle.exportKey(/*format*/ format, /*key*/ key);
199
+ return await cryptoImpl.subtle.exportKey(
200
+ /*format*/ format,
201
+ /*key*/ key as CryptoKey
202
+ );
216
203
  };
217
204
 
218
- export const encryptWithNodeKey = async (
219
- key: CryptoKey,
220
- data: string
221
- ): Promise<string> => {
222
- const enc = new TextEncoder();
223
- const encoded = enc.encode(data);
224
- // @ts-ignore
225
- const encrypted = await cryptoImpl.subtle.encrypt(
226
- /*algorithm:*/ {
227
- name: "RSA-OAEP",
205
+ const getNonce = async () => {
206
+ const cryptoImpl = await getCrypto();
207
+ const nonceSt = await getRandomValues32(new Uint32Array(1));
208
+ return Number(nonceSt);
209
+ };
210
+
211
+ const sign = async (
212
+ key: CryptoKey | Uint8Array,
213
+ data: Uint8Array
214
+ ): Promise<ArrayBuffer> => {
215
+ const cryptoImpl = await getCrypto();
216
+ return await cryptoImpl.subtle.sign(
217
+ {
218
+ name: "RSA-PSS",
219
+ saltLength: 32,
228
220
  },
229
- /*key*/ key,
230
- /*data*/ encoded
221
+ key as CryptoKey,
222
+ data
231
223
  );
232
- // @ts-ignore
233
- return b64encode(encrypted);
234
224
  };
235
225
 
236
- export const loadNodeEncryptionKey = async (
237
- rawPublicKey: string
238
- ): Promise<CryptoKey> => {
239
- const encoded = b64decode(rawPublicKey);
226
+ const importPrivateSigningKey = async (
227
+ keyData: Uint8Array,
228
+ format: "pkcs8" | "spki"
229
+ ): Promise<CryptoKey | Uint8Array> => {
240
230
  const cryptoImpl = await getCrypto();
241
231
  return await cryptoImpl.subtle.importKey(
242
- /*format*/ "spki",
243
- /*keyData*/ encoded,
244
- /*algorithm:*/ {
245
- name: "RSA-OAEP",
232
+ /*format*/ format,
233
+ /*keyData*/ keyData,
234
+ /*algorithm*/ {
235
+ name: "RSA-PSS",
246
236
  hash: "SHA-256",
247
237
  },
248
238
  /*extractable*/ true,
249
- /*keyUsages*/ ["encrypt"]
239
+ /*keyUsages*/ ["sign"]
250
240
  );
251
241
  };
252
242
 
253
- export const getNonce = async () => {
254
- const nonceSt = await getRandomValues32(new Uint32Array(1));
255
- return Number(nonceSt);
243
+ export const DefaultCrypto = {
244
+ decryptSecretWithNodePassword,
245
+ generateSigningKeyPair,
246
+ serializeSigningKey,
247
+ getNonce,
248
+ sign,
249
+ importPrivateSigningKey,
256
250
  };
257
251
 
258
252
  export { default as LightsparkSigningException } from "./LightsparkSigningException.js";