sliftutils 1.5.3 → 1.5.5

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/index.d.ts CHANGED
@@ -70,7 +70,6 @@ declare module "sliftutils/misc/https/certs" {
70
70
  /// <reference types="node" />
71
71
  /// <reference types="node" />
72
72
  import * as forge from "node-forge";
73
- import { MaybePromise } from "socket-function/src/types";
74
73
  export declare const CA_NOT_FOUND_ERROR = "18aa7318-f88f-4d2d-b41f-3daf4a433827";
75
74
  export declare const identityStorageKey = "machineCA_12";
76
75
  export type IdentityStorageType = {
@@ -121,7 +120,7 @@ declare module "sliftutils/misc/https/certs" {
121
120
  export declare function setIdentityCARaw(domain: string, json: string): Promise<void>;
122
121
  export declare function loadIdentityCA(domain: string): Promise<void>;
123
122
  export declare function getIdentityCA(domain: string): X509KeyPair;
124
- export declare function getIdentityCAPromise(domain: string): MaybePromise<X509KeyPair>;
123
+ export declare function getIdentityCAPromise(domain: string): X509KeyPair;
125
124
  export declare function getOwnMachineId(domain: string): string;
126
125
  export declare function getOwnThreadId(domain: string): string;
127
126
  /** Part of the machineId comes from the publicKey, so we can use it to verify */
@@ -217,10 +216,9 @@ declare module "sliftutils/misc/https/node-forge-ed25519" {
217
216
  }
218
217
 
219
218
  declare module "sliftutils/misc/https/persistentLocalStorage" {
220
- import { MaybePromise } from "socket-function/src/types";
221
219
  export declare function getKeyStore<T>(appName: string, key: string): {
222
- get(): MaybePromise<T | undefined>;
223
- set(value: T | null): MaybePromise<void>;
220
+ get(): T | undefined;
221
+ set(value: T | null): void;
224
222
  };
225
223
 
226
224
  }
@@ -3,7 +3,6 @@
3
3
  /// <reference types="node" />
4
4
  /// <reference types="node" />
5
5
  import * as forge from "node-forge";
6
- import { MaybePromise } from "socket-function/src/types";
7
6
  export declare const CA_NOT_FOUND_ERROR = "18aa7318-f88f-4d2d-b41f-3daf4a433827";
8
7
  export declare const identityStorageKey = "machineCA_12";
9
8
  export type IdentityStorageType = {
@@ -54,7 +53,7 @@ export declare function encodeNodeId(parts: NodeIdParts): string;
54
53
  export declare function setIdentityCARaw(domain: string, json: string): Promise<void>;
55
54
  export declare function loadIdentityCA(domain: string): Promise<void>;
56
55
  export declare function getIdentityCA(domain: string): X509KeyPair;
57
- export declare function getIdentityCAPromise(domain: string): MaybePromise<X509KeyPair>;
56
+ export declare function getIdentityCAPromise(domain: string): X509KeyPair;
58
57
  export declare function getOwnMachineId(domain: string): string;
59
58
  export declare function getOwnThreadId(domain: string): string;
60
59
  /** Part of the machineId comes from the publicKey, so we can use it to verify */
@@ -15,7 +15,6 @@ import crypto from "crypto";
15
15
  import { trustCertificate } from "socket-function/src/certStore";
16
16
  import { measureBlock, measureFnc, measureWrap } from "socket-function/src/profiling/measure";
17
17
  import { getNodeIdDomain, getNodeIdDomainMaybeUndefined, getNodeIdLocation } from "socket-function/src/nodeCache";
18
- import { MaybePromise } from "socket-function/src/types";
19
18
  import { SocketFunction } from "socket-function/SocketFunction";
20
19
  import { resetAllNodeCallFactories } from "socket-function/src/nodeCache";
21
20
  import { getKeyStore } from "./persistentLocalStorage";
@@ -386,6 +385,14 @@ function validateAltNames(certParsed: forge.pki.Certificate, subject: string) {
386
385
  }
387
386
 
388
387
 
388
+ // NOTE: We can't use crypto.subtle (non-extractable CryptoKeys) for our keys, because subtle
389
+ // is asynchronous, and everything here (key generation, cert creation, signing) must be
390
+ // available synchronously. The only real benefit of subtle is that a cross-site scripting
391
+ // attack can't exfiltrate the key. Which, while nice, is of minor benefit, as the cross-site
392
+ // script can already do quite a bit of damage anyway with access. And if that happens, the
393
+ // first thing the user is probably going to do is reset all their credentials, which solves
394
+ // the case of the key being exfiltrated anyway (by telling the server to stop trusting
395
+ // all identities).
389
396
  export function generateKeyPair() {
390
397
  return measureBlock(function generateKeyPair() {
391
398
  // NOTE: We use ED25519 because it can generated keys about 10X faster, WHICH, is still slow
@@ -415,36 +422,32 @@ export function generateTestCA(domain: string) {
415
422
  return createX509({ domain: fullDomain, issuer: "self", keyPair, lifeSpan: timeInDay * 365 * 20 });
416
423
  }
417
424
 
418
- let identityCA = cache((domain: string) => {
419
- let identityCA = lazy((async (): Promise<X509KeyPair> => {
420
- let identityCACached = getIdentityStore(domain);
421
- let caCached = await identityCACached.get();
422
- if (!caCached) {
423
- console.log(`Generating new identity CA`);
424
- const keyPair = generateKeyPair();
425
- let caPublicKeyPart = getDomainPartFromPublicKey(keyPair.publicKey);
426
- let fullDomain = `${caPublicKeyPart}.${domain}`;
425
+ let identityCA = cache((domain: string) => lazy((): X509KeyPair => {
426
+ let identityCACached = getIdentityStore(domain);
427
+ let caCached = identityCACached.get();
428
+ if (!caCached) {
429
+ console.log(`Generating new identity CA`);
430
+ const keyPair = generateKeyPair();
431
+ let caPublicKeyPart = getDomainPartFromPublicKey(keyPair.publicKey);
432
+ let fullDomain = `${caPublicKeyPart}.${domain}`;
427
433
 
428
- let value = createX509({ domain: fullDomain, issuer: "self", keyPair, lifeSpan: timeInDay * 365 * 20 });
434
+ let value = createX509({ domain: fullDomain, issuer: "self", keyPair, lifeSpan: timeInDay * 365 * 20 });
429
435
 
430
- caCached = {
431
- domain: value.domain,
432
- certB64: value.cert.toString("base64"),
433
- keyB64: value.key.toString("base64"),
434
- };
435
- await identityCACached.set(caCached);
436
- }
437
- let result = {
438
- domain: caCached.domain,
439
- cert: Buffer.from(caCached.certB64, "base64"),
440
- key: Buffer.from(caCached.keyB64, "base64"),
436
+ caCached = {
437
+ domain: value.domain,
438
+ certB64: value.cert.toString("base64"),
439
+ keyB64: value.key.toString("base64"),
441
440
  };
442
- trustCertificate(result.cert.toString());
443
- identityCA.set(result);
444
- return result;
445
- }) as (() => MaybePromise<X509KeyPair>));
446
- return identityCA;
447
- });
441
+ identityCACached.set(caCached);
442
+ }
443
+ let result = {
444
+ domain: caCached.domain,
445
+ cert: Buffer.from(caCached.certB64, "base64"),
446
+ key: Buffer.from(caCached.keyB64, "base64"),
447
+ };
448
+ trustCertificate(result.cert.toString());
449
+ return result;
450
+ }));
448
451
 
449
452
  // IMPORTANT! We do not embed any debug info in this domain. If we did, it would be useful,
450
453
  // but... potentally a security vulnerability, as if the debug info (such as a prefix)
@@ -535,24 +538,23 @@ export async function setIdentityCARaw(domain: string, json: string) {
535
538
  trustCertificate(ca.cert.toString());
536
539
  identityCA(domain).set(ca);
537
540
  getThreadKeyCertBase(domain).reset();
538
- await identityCACached.set(obj);
541
+ identityCACached.set(obj);
539
542
  resetAllNodeCallFactories();
540
543
  }
541
544
 
545
+ // NOTE: The identity CA is available synchronously (storage is fs/localStorage, both
546
+ // synchronous), so this only exists for backwards compatibility with startup code
547
+ // that awaits it.
542
548
  export async function loadIdentityCA(domain: string) {
543
- await identityCA(domain)();
549
+ identityCA(domain)();
544
550
  }
545
551
  export function getIdentityCA(domain: string): X509KeyPair {
546
- let value = identityCA(domain)();
547
- if (value instanceof Promise) {
548
- throw new Error(`Identity CA is not yet loaded. Call and wait for loadIdentityCA(${JSON.stringify(domain)}) in your startup before accessing the identity (or call getIdentityCAPromise(${JSON.stringify(domain)}))`);
549
- }
550
- return value;
552
+ return identityCA(domain)();
551
553
  }
552
554
 
553
555
  // TODO: Replace this with a database, so it is easy for us to trust CAs
554
556
  // cross machine, and even have multiple users, etc, etc.
555
- export function getIdentityCAPromise(domain: string): MaybePromise<X509KeyPair> {
557
+ export function getIdentityCAPromise(domain: string): X509KeyPair {
556
558
  return identityCA(domain)();
557
559
  }
558
560
 
@@ -1,5 +1,4 @@
1
- import { MaybePromise } from "socket-function/src/types";
2
1
  export declare function getKeyStore<T>(appName: string, key: string): {
3
- get(): MaybePromise<T | undefined>;
4
- set(value: T | null): MaybePromise<void>;
2
+ get(): T | undefined;
3
+ set(value: T | null): void;
5
4
  };
@@ -1,12 +1,11 @@
1
1
  import { isNode } from "socket-function/src/misc";
2
2
  import fs from "fs";
3
3
  import os from "os";
4
- import { MaybePromise } from "socket-function/src/types";
5
4
  import { cache } from "socket-function/src/caching";
6
5
 
7
6
  export function getKeyStore<T>(appName: string, key: string): {
8
- get(): MaybePromise<T | undefined>;
9
- set(value: T | null): MaybePromise<void>;
7
+ get(): T | undefined;
8
+ set(value: T | null): void;
10
9
  } {
11
10
  if (isNode()) {
12
11
  let path = os.homedir() + `/keystore_${appName}_` + key + ".json";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [